keycloak-memoizeit

Merge pull request #1464 from stianst/master KEYCLOAK-1385

7/17/2015 9:04:59 AM

Changes

.gitattributes 20(+20 -0)

broker/core/pom.xml 100(+50 -50)

broker/oidc/pom.xml 116(+58 -58)

broker/pom.xml 46(+23 -23)

broker/saml/pom.xml 100(+50 -50)

connections/pom.xml 72(+36 -36)

core/pom.xml 224(+112 -112)

core-jaxrs/pom.xml 132(+66 -66)

dependencies/pom.xml 64(+32 -32)

distribution/pom.xml 56(+28 -28)

docbook/pom.xml 268(+134 -134)

events/api/pom.xml 76(+38 -38)

events/email/pom.xml 96(+48 -48)

events/jpa/pom.xml 114(+57 -57)

events/mongo/pom.xml 94(+47 -47)

events/pom.xml 52(+26 -26)

examples/cors/pom.xml 44(+22 -22)

examples/pom.xml 98(+49 -49)

examples/saml/pom.xml 68(+34 -34)

forms/pom.xml 56(+28 -28)

integration/pom.xml 66(+33 -33)

model/api/pom.xml 132(+66 -66)

model/jpa/pom.xml 188(+94 -94)

model/mongo/pom.xml 106(+53 -53)

model/pom.xml 76(+38 -38)

pom.xml 2816(+1408 -1408)

proxy/pom.xml 62(+31 -31)

saml/pom.xml 40(+20 -20)

saml/saml-core/pom.xml 110(+55 -55)

services/pom.xml 428(+214 -214)

social/core/pom.xml 76(+38 -38)

social/google/pom.xml 76(+38 -38)

social/pom.xml 54(+27 -27)

social/twitter/pom.xml 108(+54 -54)

testsuite/pom.xml 176(+88 -88)

testsuite/proxy/pom.xml 986(+493 -493)

testsuite/tomcat6/pom.xml 970(+485 -485)

testsuite/tomcat7/pom.xml 978(+489 -489)

testsuite/tomcat8/pom.xml 976(+488 -488)

timer/api/pom.xml 54(+27 -27)

timer/basic/pom.xml 76(+38 -38)

timer/pom.xml 44(+22 -22)

Details

.gitattributes 20(+20 -0)

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2b70adf
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,20 @@
+* text=auto
+
+*.html text eol=lf
+*.java text eol=lf
+*.js text eol=lf
+*.json text eol=lf
+*.jsp text eol=lf
+*.md text eol=lf
+*.properties text eol=lf
+*.svg text auto
+*.xml text eol=lf
+*.xsl text eol=lf
+
+*.png binary
+*.jpg binary
+*.gif binary
+*.ttf binary
+*.eot binary
+*.otf binary
+*.woff binary

broker/core/pom.xml 100(+50 -50)

diff --git a/broker/core/pom.xml b/broker/core/pom.xml
index ab121a7..5118a8c 100755
--- a/broker/core/pom.xml
+++ b/broker/core/pom.xml
@@ -1,50 +1,50 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-broker-core</artifactId>
-    <name>Keycloak Broker Core</name>
-    <description/>
-    <packaging>jar</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-broker-core</artifactId>
+    <name>Keycloak Broker Core</name>
+    <description/>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderMapper.java
index 092f23b..ee327c3 100755
--- a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderMapper.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderMapper.java
@@ -1,38 +1,38 @@
-package org.keycloak.broker.provider;
-
-import org.keycloak.broker.provider.IdentityProviderMapper;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public IdentityProviderMapper create(KeycloakSession session) {
-        return null;
-    }
-
-    @Override
-    public void init(org.keycloak.Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-
-    }
-}
+package org.keycloak.broker.provider;
+
+import org.keycloak.broker.provider.IdentityProviderMapper;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public IdentityProviderMapper create(KeycloakSession session) {
+        return null;
+    }
+
+    @Override
+    public void init(org.keycloak.Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+
+    }
+}
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
index 6eb4db9..309e26a 100755
--- a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
@@ -1,110 +1,110 @@
-package org.keycloak.broker.provider;
-
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
-    public static final String ROLE = "role";
-    protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ROLE);
-        property.setLabel("Role");
-        property.setHelpText("Role to grant to user.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-
-
-    public static String[] parseRole(String role) {
-        int scopeIndex = role.lastIndexOf('.');
-        if (scopeIndex > -1) {
-            String appName = role.substring(0, scopeIndex);
-            role = role.substring(scopeIndex + 1);
-            String[] rtn = {appName, role};
-            return rtn;
-        } else {
-            String[] rtn = {null, role};
-            return rtn;
-
-        }
-    }
-
-    public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
-        String[] parsedRole = parseRole(roleName);
-        RoleModel role = null;
-        if (parsedRole[0] == null) {
-            role = realm.getRole(parsedRole[1]);
-        } else {
-            ClientModel client = realm.getClientByClientId(parsedRole[0]);
-            role = client.getRole(parsedRole[1]);
-        }
-        return role;
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Importer";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Hardcoded Role";
-    }
-
-    public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
-
-
-    public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String roleName = mapperModel.getConfig().get(ROLE);
-        RoleModel role = getRoleFromString(realm, roleName);
-        if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-        user.grantRole(role);
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "When user is imported from provider, hardcode a role mapping for it.";
-    }
-}
+package org.keycloak.broker.provider;
+
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
+    public static final String ROLE = "role";
+    protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ROLE);
+        property.setLabel("Role");
+        property.setHelpText("Role to grant to user.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+
+
+    public static String[] parseRole(String role) {
+        int scopeIndex = role.lastIndexOf('.');
+        if (scopeIndex > -1) {
+            String appName = role.substring(0, scopeIndex);
+            role = role.substring(scopeIndex + 1);
+            String[] rtn = {appName, role};
+            return rtn;
+        } else {
+            String[] rtn = {null, role};
+            return rtn;
+
+        }
+    }
+
+    public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
+        String[] parsedRole = parseRole(roleName);
+        RoleModel role = null;
+        if (parsedRole[0] == null) {
+            role = realm.getRole(parsedRole[1]);
+        } else {
+            ClientModel client = realm.getClientByClientId(parsedRole[0]);
+            role = client.getRole(parsedRole[1]);
+        }
+        return role;
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Importer";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded Role";
+    }
+
+    public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
+
+
+    public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String roleName = mapperModel.getConfig().get(ROLE);
+        RoleModel role = getRoleFromString(realm, roleName);
+        if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+        user.grantRole(role);
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "When user is imported from provider, hardcode a role mapping for it.";
+    }
+}
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java
index d20aa00..b76a6af 100755
--- a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java
@@ -1,56 +1,56 @@
-package org.keycloak.broker.provider;
-
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ConfiguredProvider;
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
-    public static final String ANY_PROVIDER = "*";
-
-    String[] getCompatibleProviders();
-    String getDisplayCategory();
-    String getDisplayType();
-
-    /**
-     * Called to determine what keycloak username and email to use to process the login request from the external IDP
-     * Usually used to map BrokeredIdentityContet.username or email.
-     *
-     * @param session
-     * @param realm
-     * @param mapperModel
-     * @param context
-     */
-    void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
-
-    /**
-     * Called after UserModel is created for first time for this user.
-     *
-     * @param session
-     * @param realm
-     * @param user
-     * @param mapperModel
-     * @param context
-     */
-    void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
-
-    /**
-     * Called when this user has logged in before and has already been imported.
-     *
-     * @param session
-     * @param realm
-     * @param user
-     * @param mapperModel
-     * @param context
-     */
-    void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
-
-
-}
+package org.keycloak.broker.provider;
+
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ConfiguredProvider;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
+    public static final String ANY_PROVIDER = "*";
+
+    String[] getCompatibleProviders();
+    String getDisplayCategory();
+    String getDisplayType();
+
+    /**
+     * Called to determine what keycloak username and email to use to process the login request from the external IDP
+     * Usually used to map BrokeredIdentityContet.username or email.
+     *
+     * @param session
+     * @param realm
+     * @param mapperModel
+     * @param context
+     */
+    void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
+
+    /**
+     * Called after UserModel is created for first time for this user.
+     *
+     * @param session
+     * @param realm
+     * @param user
+     * @param mapperModel
+     * @param context
+     */
+    void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
+
+    /**
+     * Called when this user has logged in before and has already been imported.
+     *
+     * @param session
+     * @param realm
+     * @param user
+     * @param mapperModel
+     * @param context
+     */
+    void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
+
+
+}
diff --git a/broker/core/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/broker/core/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index fa44621..1292531 100755
--- a/broker/core/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/broker/core/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,2 +1,2 @@
-org.keycloak.broker.provider.IdentityProviderSpi
+org.keycloak.broker.provider.IdentityProviderSpi
 org.keycloak.broker.provider.IdentityProviderMapperSpi
\ No newline at end of file

broker/oidc/pom.xml 116(+58 -58)

diff --git a/broker/oidc/pom.xml b/broker/oidc/pom.xml
index f3be798..8327eb3 100755
--- a/broker/oidc/pom.xml
+++ b/broker/oidc/pom.xml
@@ -1,58 +1,58 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-broker-oidc</artifactId>
-    <name>Keycloak Broker - OpenID Connect Identity Provider</name>
-    <description/>
-    <packaging>jar</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-broker-oidc</artifactId>
+    <name>Keycloak Broker - OpenID Connect Identity Provider</name>
+    <description/>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
index d791765..eebf18d 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
@@ -1,114 +1,114 @@
-package org.keycloak.broker.oidc;
-
-import org.keycloak.broker.provider.util.SimpleHttp;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.JsonWebToken;
-import org.keycloak.representations.adapters.action.AdminAction;
-import org.keycloak.representations.adapters.action.LogoutAction;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.util.JsonSerialization;
-
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.security.PublicKey;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
-
-    public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
-
-    public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
-        super(config);
-    }
-
-    @Override
-    public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
-        return new KeycloakEndpoint(callback, realm, event);
-    }
-
-    @Override
-    protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
-        JsonWebToken access = validateToken(idpKey, response.getToken());
-        context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
-    }
-
-    protected class KeycloakEndpoint extends OIDCEndpoint {
-        public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
-            super(callback, realm, event);
-        }
-
-        @POST
-        @Path(AdapterConstants.K_LOGOUT)
-        public Response backchannelLogout(String input) {
-            JWSInput token = new JWSInput(input);
-            PublicKey key = getExternalIdpKey();
-            if (key != null) {
-                if (!verify(token, key)) {
-                    logger.warn("Failed to verify logout request");
-                    return Response.status(400).build();
-                }
-            }
-            LogoutAction action = null;
-            try {
-                action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-            if (!validateAction(action)) return Response.status(400).build();
-            if (action.getKeycloakSessionIds() != null) {
-                for (String sessionId : action.getKeycloakSessionIds()) {
-                    String brokerSessionId = getConfig().getAlias() + "." + sessionId;
-                    UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
-                    if (userSession != null
-                            && userSession.getState() != UserSessionModel.State.LOGGING_OUT
-                            && userSession.getState() != UserSessionModel.State.LOGGED_OUT
-                            ) {
-                        AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
-                    }
-                }
-
-            }
-            return Response.ok().build();
-        }
-
-        protected boolean validateAction(AdminAction action)  {
-            if (!action.validate()) {
-                logger.warn("admin request failed, not validated" + action.getAction());
-                return false;
-            }
-            if (action.isExpired()) {
-                logger.warn("admin request failed, expired token");
-                return false;
-            }
-            if (!getConfig().getClientId().equals(action.getResource())) {
-                logger.warn("Resource name does not match");
-                return false;
-
-            }
-            return true;
-        }
-
-        @Override
-        public SimpleHttp generateTokenRequest(String authorizationCode) {
-            return super.generateTokenRequest(authorizationCode)
-                    .param(AdapterConstants.CLIENT_SESSION_STATE, "n/a");  // hack to get backchannel logout to work
-
-        }
-
-
-
-    }
-
-
-}
+package org.keycloak.broker.oidc;
+
+import org.keycloak.broker.provider.util.SimpleHttp;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.JsonWebToken;
+import org.keycloak.representations.adapters.action.AdminAction;
+import org.keycloak.representations.adapters.action.LogoutAction;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.util.JsonSerialization;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
+
+    public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
+
+    public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
+        super(config);
+    }
+
+    @Override
+    public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
+        return new KeycloakEndpoint(callback, realm, event);
+    }
+
+    @Override
+    protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
+        JsonWebToken access = validateToken(idpKey, response.getToken());
+        context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
+    }
+
+    protected class KeycloakEndpoint extends OIDCEndpoint {
+        public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
+            super(callback, realm, event);
+        }
+
+        @POST
+        @Path(AdapterConstants.K_LOGOUT)
+        public Response backchannelLogout(String input) {
+            JWSInput token = new JWSInput(input);
+            PublicKey key = getExternalIdpKey();
+            if (key != null) {
+                if (!verify(token, key)) {
+                    logger.warn("Failed to verify logout request");
+                    return Response.status(400).build();
+                }
+            }
+            LogoutAction action = null;
+            try {
+                action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            if (!validateAction(action)) return Response.status(400).build();
+            if (action.getKeycloakSessionIds() != null) {
+                for (String sessionId : action.getKeycloakSessionIds()) {
+                    String brokerSessionId = getConfig().getAlias() + "." + sessionId;
+                    UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
+                    if (userSession != null
+                            && userSession.getState() != UserSessionModel.State.LOGGING_OUT
+                            && userSession.getState() != UserSessionModel.State.LOGGED_OUT
+                            ) {
+                        AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
+                    }
+                }
+
+            }
+            return Response.ok().build();
+        }
+
+        protected boolean validateAction(AdminAction action)  {
+            if (!action.validate()) {
+                logger.warn("admin request failed, not validated" + action.getAction());
+                return false;
+            }
+            if (action.isExpired()) {
+                logger.warn("admin request failed, expired token");
+                return false;
+            }
+            if (!getConfig().getClientId().equals(action.getResource())) {
+                logger.warn("Resource name does not match");
+                return false;
+
+            }
+            return true;
+        }
+
+        @Override
+        public SimpleHttp generateTokenRequest(String authorizationCode) {
+            return super.generateTokenRequest(authorizationCode)
+                    .param(AdapterConstants.CLIENT_SESSION_STATE, "n/a");  // hack to get backchannel logout to work
+
+        }
+
+
+
+    }
+
+
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java
index 85ec561..4178069 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java
@@ -1,97 +1,97 @@
-package org.keycloak.broker.oidc.mappers;
-
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.JsonWebToken;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
-    public static final String CLAIM = "claim";
-    public static final String CLAIM_VALUE = "claim.value";
-
-    public static Object getClaimValue(JsonWebToken token, String claim) {
-        String[] split = claim.split("\\.");
-        Map<String, Object> jsonObject = token.getOtherClaims();
-        for (int i = 0; i < split.length; i++) {
-            if (i == split.length - 1) {
-                return jsonObject.get(split[i]);
-            } else {
-                Object val = jsonObject.get(split[i]);
-                if (!(val instanceof Map)) return null;
-                jsonObject = (Map<String, Object>)val;
-            }
-        }
-        return null;
-    }
-
-    public static Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String claim = mapperModel.getConfig().get(CLAIM);
-        return getClaimValue(context, claim);
-    }
-
-    public static Object getClaimValue(BrokeredIdentityContext context, String claim) {
-        {  // search access token
-            JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
-            if (token != null) {
-                Object value = getClaimValue(token, claim);
-                if (value != null) return value;
-            }
-
-        }
-        {  // search ID Token
-            JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
-            if (token != null) {
-                Object value = getClaimValue(token, claim);
-                if (value != null) return value;
-            }
-
-        }
-        return null;
-    }
-
-
-    protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        Object value = getClaimValue(mapperModel, context);
-        String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
-        return valueEquals(desiredValue, value);
-    }
-
-    public boolean valueEquals(String desiredValue, Object value) {
-        if (value instanceof String) {
-            if (desiredValue.equals(value)) return true;
-        } else if (value instanceof Double) {
-            try {
-                if (Double.valueOf(desiredValue).equals(value)) return true;
-            } catch (Exception e) {
-
-            }
-        } else if (value instanceof Integer) {
-            try {
-                if (Integer.valueOf(desiredValue).equals(value)) return true;
-            } catch (Exception e) {
-
-            }
-        } else if (value instanceof Boolean) {
-            try {
-                if (Boolean.valueOf(desiredValue).equals(value)) return true;
-            } catch (Exception e) {
-
-            }
-        } else if (value instanceof List) {
-            List list = (List)value;
-            for (Object val : list) {
-                return valueEquals(desiredValue, val);
-            }
-        }
-        return false;
-    }
-}
+package org.keycloak.broker.oidc.mappers;
+
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.JsonWebToken;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
+    public static final String CLAIM = "claim";
+    public static final String CLAIM_VALUE = "claim.value";
+
+    public static Object getClaimValue(JsonWebToken token, String claim) {
+        String[] split = claim.split("\\.");
+        Map<String, Object> jsonObject = token.getOtherClaims();
+        for (int i = 0; i < split.length; i++) {
+            if (i == split.length - 1) {
+                return jsonObject.get(split[i]);
+            } else {
+                Object val = jsonObject.get(split[i]);
+                if (!(val instanceof Map)) return null;
+                jsonObject = (Map<String, Object>)val;
+            }
+        }
+        return null;
+    }
+
+    public static Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String claim = mapperModel.getConfig().get(CLAIM);
+        return getClaimValue(context, claim);
+    }
+
+    public static Object getClaimValue(BrokeredIdentityContext context, String claim) {
+        {  // search access token
+            JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
+            if (token != null) {
+                Object value = getClaimValue(token, claim);
+                if (value != null) return value;
+            }
+
+        }
+        {  // search ID Token
+            JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
+            if (token != null) {
+                Object value = getClaimValue(token, claim);
+                if (value != null) return value;
+            }
+
+        }
+        return null;
+    }
+
+
+    protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        Object value = getClaimValue(mapperModel, context);
+        String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
+        return valueEquals(desiredValue, value);
+    }
+
+    public boolean valueEquals(String desiredValue, Object value) {
+        if (value instanceof String) {
+            if (desiredValue.equals(value)) return true;
+        } else if (value instanceof Double) {
+            try {
+                if (Double.valueOf(desiredValue).equals(value)) return true;
+            } catch (Exception e) {
+
+            }
+        } else if (value instanceof Integer) {
+            try {
+                if (Integer.valueOf(desiredValue).equals(value)) return true;
+            } catch (Exception e) {
+
+            }
+        } else if (value instanceof Boolean) {
+            try {
+                if (Boolean.valueOf(desiredValue).equals(value)) return true;
+            } catch (Exception e) {
+
+            }
+        } else if (value instanceof List) {
+            List list = (List)value;
+            for (Object val : list) {
+                return valueEquals(desiredValue, val);
+            }
+        }
+        return false;
+    }
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java
index 6d3f8db..4d2a4e2 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java
@@ -1,206 +1,206 @@
-package org.keycloak.broker.oidc.mappers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.codehaus.jackson.JsonNode;
-import org.jboss.logging.Logger;
-import org.keycloak.broker.oidc.OIDCIdentityProvider;
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-/**
- * Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user
- * attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who
- * uses {@link JsonNode} user profile.
- * 
- * @author Vlastimil Elias (velias at redhat dot com)
- */
-public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper {
-
-
-	protected static final Logger logger = Logger.getLogger(AbstractJsonUserAttributeMapper.class);
-
-	protected static final Logger LOGGER_DUMP_USER_PROFILE = Logger.getLogger("org.keycloak.social.user_profile_dump");
-
-	private static final String JSON_PATH_DELIMITER = ".";
-
-	/**
-	 * Config param where name of mapping source JSON User Profile field is stored.
-	 */
-	public static final String CONF_JSON_FIELD = "jsonField";
-	/**
-	 * Config param where name of mapping target USer attribute is stored.
-	 */
-	public static final String CONF_USER_ATTRIBUTE = "userAttribute";
-
-	/**
-	 * Key in {@link BrokeredIdentityContext#getContextData()} where {@link JsonNode} with user profile is stored.
-	 */
-	public static final String CONTEXT_JSON_NODE = OIDCIdentityProvider.USER_INFO;
-
-	private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-	static {
-		ProviderConfigProperty property;
-		ProviderConfigProperty property1;
-		property1 = new ProviderConfigProperty();
-		property1.setName(CONF_JSON_FIELD);
-		property1.setLabel("Social Profile JSON Field Path");
-		property1.setHelpText("Path of field in Social provider User Profile JSON data to get value from. You can use dot notation for nesting and square brackets for array index. Eg. 'contact.address[0].country'.");
-		property1.setType(ProviderConfigProperty.STRING_TYPE);
-		configProperties.add(property1);
-		property = new ProviderConfigProperty();
-		property.setName(CONF_USER_ATTRIBUTE);
-		property.setLabel("User Attribute Name");
-		property.setHelpText("User attribute name to store information into.");
-		property.setType(ProviderConfigProperty.STRING_TYPE);
-		configProperties.add(property);
-	}
-
-	/**
-	 * Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure. 
-	 * 
-	 * @param user context to store profile data into
-	 * @param profile to store into context
-	 * @param provider identification of social provider to be used in log dump
-	 * 
-	 * @see #importNewUser(KeycloakSession, RealmModel, UserModel, IdentityProviderMapperModel, BrokeredIdentityContext)
-	 * @see BrokeredIdentityContext#getContextData()
-	 */
-	public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
-		user.getContextData().put(AbstractJsonUserAttributeMapper.CONTEXT_JSON_NODE, profile);
-		if (LOGGER_DUMP_USER_PROFILE.isDebugEnabled())
-			LOGGER_DUMP_USER_PROFILE.debug("User Profile JSON Data for provider "+provider+": " + profile);
-	}
-
-	@Override
-	public List<ProviderConfigProperty> getConfigProperties() {
-		return configProperties;
-	}
-
-	@Override
-	public String getDisplayCategory() {
-		return "Attribute Importer";
-	}
-
-	@Override
-	public String getDisplayType() {
-		return "Attribute Importer";
-	}
-
-	@Override
-	public String getHelpText() {
-		return "Import user profile information if it exists in Social provider JSON data into the specified user attribute.";
-	}
-
-	@Override
-	public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-		String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
-		if (attribute == null || attribute.trim().isEmpty()) {
-			logger.debug("Attribute is not configured");
-			return;
-		}
-		attribute = attribute.trim();
-
-		String value = getJsonValue(mapperModel, context);
-		if (value != null) {
-			user.setSingleAttribute(attribute, value);
-		}
-	}
-
-	@Override
-	public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-		// we do not update user profile from social provider
-	}
-
-	protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-
-		String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
-		if (jsonField == null || jsonField.trim().isEmpty()) {
-			logger.debug("JSON field path is not configured");
-			return null;
-		}
-		jsonField = jsonField.trim();
-
-		if (jsonField.startsWith(JSON_PATH_DELIMITER) || jsonField.endsWith(JSON_PATH_DELIMITER) || jsonField.startsWith("[")) {
-			logger.debug("JSON field path is invalid " + jsonField);
-			return null;
-		}
-
-		JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE);
-
-		String value = getJsonValue(profileJsonNode, jsonField);
-
-		if (value == null) {
-			logger.debug("User profile JSON value '" + jsonField + "' is not available.");
-		}
-
-		return value;
-	}
-
-	protected static String getJsonValue(JsonNode baseNode, String fieldPath) {
-		logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
-		if (baseNode != null) {
-
-			int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
-
-			String currentFieldName = fieldPath;
-			if (idx > 0) {
-				currentFieldName = fieldPath.substring(0, idx).trim();
-				if (currentFieldName.isEmpty()) {
-					logger.debug("JSON path is invalid " + fieldPath);
-					return null;
-				}
-			}
-
-			String currentNodeName = currentFieldName;
-			int arrayIndex = -1;
-			if (currentFieldName.endsWith("]")) {
-				int bi = currentFieldName.indexOf("[");
-				if (bi == -1) {
-					logger.debug("Invalid array index construct in " + currentFieldName);
-					return null;
-				}
-				try {
-				String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
-					arrayIndex = Integer.parseInt(is);
-				} catch (Exception e) {
-					logger.debug("Invalid array index construct in " + currentFieldName);
-					return null;
-				}
-				currentNodeName = currentFieldName.substring(0,bi).trim();
-			}
-
-			JsonNode currentNode = baseNode.get(currentNodeName);
-			if (arrayIndex > -1 && currentNode.isArray()) {
-				logger.debug("Going to take array node at index " + arrayIndex);
-				currentNode = currentNode.get(arrayIndex);
-			}
-
-			if (currentNode == null) {
-				logger.debug("JsonNode not found for name " + currentFieldName);
-				return null;
-			}
-
-			if (idx < 0) {
-				if (!currentNode.isValueNode()) {
-					logger.debug("JsonNode is not value node for name " + currentFieldName);
-					return null;
-				}
-				String ret = currentNode.asText();
-				if (ret != null && !ret.trim().isEmpty())
-					return ret.trim();
-			} else {
-				return getJsonValue(currentNode, fieldPath.substring(idx + 1));
-			}
-		}
-		return null;
-	}
-
-}
+package org.keycloak.broker.oidc.mappers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.jackson.JsonNode;
+import org.jboss.logging.Logger;
+import org.keycloak.broker.oidc.OIDCIdentityProvider;
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+/**
+ * Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user
+ * attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who
+ * uses {@link JsonNode} user profile.
+ * 
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper {
+
+
+	protected static final Logger logger = Logger.getLogger(AbstractJsonUserAttributeMapper.class);
+
+	protected static final Logger LOGGER_DUMP_USER_PROFILE = Logger.getLogger("org.keycloak.social.user_profile_dump");
+
+	private static final String JSON_PATH_DELIMITER = ".";
+
+	/**
+	 * Config param where name of mapping source JSON User Profile field is stored.
+	 */
+	public static final String CONF_JSON_FIELD = "jsonField";
+	/**
+	 * Config param where name of mapping target USer attribute is stored.
+	 */
+	public static final String CONF_USER_ATTRIBUTE = "userAttribute";
+
+	/**
+	 * Key in {@link BrokeredIdentityContext#getContextData()} where {@link JsonNode} with user profile is stored.
+	 */
+	public static final String CONTEXT_JSON_NODE = OIDCIdentityProvider.USER_INFO;
+
+	private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+	static {
+		ProviderConfigProperty property;
+		ProviderConfigProperty property1;
+		property1 = new ProviderConfigProperty();
+		property1.setName(CONF_JSON_FIELD);
+		property1.setLabel("Social Profile JSON Field Path");
+		property1.setHelpText("Path of field in Social provider User Profile JSON data to get value from. You can use dot notation for nesting and square brackets for array index. Eg. 'contact.address[0].country'.");
+		property1.setType(ProviderConfigProperty.STRING_TYPE);
+		configProperties.add(property1);
+		property = new ProviderConfigProperty();
+		property.setName(CONF_USER_ATTRIBUTE);
+		property.setLabel("User Attribute Name");
+		property.setHelpText("User attribute name to store information into.");
+		property.setType(ProviderConfigProperty.STRING_TYPE);
+		configProperties.add(property);
+	}
+
+	/**
+	 * Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure. 
+	 * 
+	 * @param user context to store profile data into
+	 * @param profile to store into context
+	 * @param provider identification of social provider to be used in log dump
+	 * 
+	 * @see #importNewUser(KeycloakSession, RealmModel, UserModel, IdentityProviderMapperModel, BrokeredIdentityContext)
+	 * @see BrokeredIdentityContext#getContextData()
+	 */
+	public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
+		user.getContextData().put(AbstractJsonUserAttributeMapper.CONTEXT_JSON_NODE, profile);
+		if (LOGGER_DUMP_USER_PROFILE.isDebugEnabled())
+			LOGGER_DUMP_USER_PROFILE.debug("User Profile JSON Data for provider "+provider+": " + profile);
+	}
+
+	@Override
+	public List<ProviderConfigProperty> getConfigProperties() {
+		return configProperties;
+	}
+
+	@Override
+	public String getDisplayCategory() {
+		return "Attribute Importer";
+	}
+
+	@Override
+	public String getDisplayType() {
+		return "Attribute Importer";
+	}
+
+	@Override
+	public String getHelpText() {
+		return "Import user profile information if it exists in Social provider JSON data into the specified user attribute.";
+	}
+
+	@Override
+	public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+		String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
+		if (attribute == null || attribute.trim().isEmpty()) {
+			logger.debug("Attribute is not configured");
+			return;
+		}
+		attribute = attribute.trim();
+
+		String value = getJsonValue(mapperModel, context);
+		if (value != null) {
+			user.setSingleAttribute(attribute, value);
+		}
+	}
+
+	@Override
+	public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+		// we do not update user profile from social provider
+	}
+
+	protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+
+		String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
+		if (jsonField == null || jsonField.trim().isEmpty()) {
+			logger.debug("JSON field path is not configured");
+			return null;
+		}
+		jsonField = jsonField.trim();
+
+		if (jsonField.startsWith(JSON_PATH_DELIMITER) || jsonField.endsWith(JSON_PATH_DELIMITER) || jsonField.startsWith("[")) {
+			logger.debug("JSON field path is invalid " + jsonField);
+			return null;
+		}
+
+		JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE);
+
+		String value = getJsonValue(profileJsonNode, jsonField);
+
+		if (value == null) {
+			logger.debug("User profile JSON value '" + jsonField + "' is not available.");
+		}
+
+		return value;
+	}
+
+	protected static String getJsonValue(JsonNode baseNode, String fieldPath) {
+		logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
+		if (baseNode != null) {
+
+			int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
+
+			String currentFieldName = fieldPath;
+			if (idx > 0) {
+				currentFieldName = fieldPath.substring(0, idx).trim();
+				if (currentFieldName.isEmpty()) {
+					logger.debug("JSON path is invalid " + fieldPath);
+					return null;
+				}
+			}
+
+			String currentNodeName = currentFieldName;
+			int arrayIndex = -1;
+			if (currentFieldName.endsWith("]")) {
+				int bi = currentFieldName.indexOf("[");
+				if (bi == -1) {
+					logger.debug("Invalid array index construct in " + currentFieldName);
+					return null;
+				}
+				try {
+				String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
+					arrayIndex = Integer.parseInt(is);
+				} catch (Exception e) {
+					logger.debug("Invalid array index construct in " + currentFieldName);
+					return null;
+				}
+				currentNodeName = currentFieldName.substring(0,bi).trim();
+			}
+
+			JsonNode currentNode = baseNode.get(currentNodeName);
+			if (arrayIndex > -1 && currentNode.isArray()) {
+				logger.debug("Going to take array node at index " + arrayIndex);
+				currentNode = currentNode.get(arrayIndex);
+			}
+
+			if (currentNode == null) {
+				logger.debug("JsonNode not found for name " + currentFieldName);
+				return null;
+			}
+
+			if (idx < 0) {
+				if (!currentNode.isValueNode()) {
+					logger.debug("JsonNode is not value node for name " + currentFieldName);
+					return null;
+				}
+				String ret = currentNode.asText();
+				if (ret != null && !ret.trim().isEmpty())
+					return ret.trim();
+			} else {
+				return getJsonValue(currentNode, fieldPath.substring(idx + 1));
+			}
+		}
+		return null;
+	}
+
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
index 60f0d1b..b3bd191 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
@@ -1,105 +1,105 @@
-package org.keycloak.broker.oidc.mappers;
-
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
-import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.HardcodedRoleMapper;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClaimToRoleMapper extends AbstractClaimMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        ProviderConfigProperty property1;
-        property1 = new ProviderConfigProperty();
-        property1.setName(CLAIM);
-        property1.setLabel("Claim");
-        property1.setHelpText("Name of claim to search for in token.  You can reference nested claims using a '.', i.e. 'address.locality'.");
-        property1.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property1);
-        property1 = new ProviderConfigProperty();
-        property1.setName(CLAIM_VALUE);
-        property1.setLabel("Claim Value");
-        property1.setHelpText("Value the claim must have.  If the claim is an array, then the value must be contained in the array.");
-        property1.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property1);
-        property = new ProviderConfigProperty();
-        property.setName(HardcodedRoleMapper.ROLE);
-        property.setLabel("Role");
-        property.setHelpText("Role to grant to user if claim is present.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "oidc-role-idp-mapper";
-
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Importer";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Claim to Role";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        if (hasClaimValue(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
-            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-            user.grantRole(role);
-        }
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        if (!hasClaimValue(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
-            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-            user.deleteRoleMapping(role);
-        }
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "If a claim exists, grant the user the specified realm or application role.";
-    }
-
-}
+package org.keycloak.broker.oidc.mappers;
+
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
+import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.HardcodedRoleMapper;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClaimToRoleMapper extends AbstractClaimMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        ProviderConfigProperty property1;
+        property1 = new ProviderConfigProperty();
+        property1.setName(CLAIM);
+        property1.setLabel("Claim");
+        property1.setHelpText("Name of claim to search for in token.  You can reference nested claims using a '.', i.e. 'address.locality'.");
+        property1.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property1);
+        property1 = new ProviderConfigProperty();
+        property1.setName(CLAIM_VALUE);
+        property1.setLabel("Claim Value");
+        property1.setHelpText("Value the claim must have.  If the claim is an array, then the value must be contained in the array.");
+        property1.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property1);
+        property = new ProviderConfigProperty();
+        property.setName(HardcodedRoleMapper.ROLE);
+        property.setLabel("Role");
+        property.setHelpText("Role to grant to user if claim is present.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "oidc-role-idp-mapper";
+
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Importer";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Claim to Role";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
+        if (hasClaimValue(mapperModel, context)) {
+            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+            user.grantRole(role);
+        }
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
+        if (!hasClaimValue(mapperModel, context)) {
+            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+            user.deleteRoleMapping(role);
+        }
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "If a claim exists, grant the user the specified realm or application role.";
+    }
+
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
index 0b93a3a..e4e0de0 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
@@ -1,118 +1,118 @@
-package org.keycloak.broker.oidc.mappers;
-
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
-import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.HardcodedRoleMapper;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.JsonWebToken;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-    private static final String EXTERNAL_ROLE = "external.role";
-
-    static {
-        ProviderConfigProperty property;
-        ProviderConfigProperty property1;
-        property1 = new ProviderConfigProperty();
-        property1.setName(EXTERNAL_ROLE);
-        property1.setLabel("External role");
-        property1.setHelpText("External role to check for.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
-        property1.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property1);
-        property = new ProviderConfigProperty();
-        property.setName(HardcodedRoleMapper.ROLE);
-        property.setLabel("Role");
-        property.setHelpText("Role to grant to user if external role is present.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
-
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Importer";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "External Role to Role";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        RoleModel role = hasRole(realm, mapperModel, context);
-        if (role != null) {
-            user.grantRole(role);
-        }
-    }
-
-    private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
-        //if (token == null) return;
-        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
-        String externalRoleName = parseRole[1];
-        String claimName = null;
-        if (parseRole[0] == null) {
-            claimName = "realm_access.roles";
-        } else {
-            claimName = "resource_access." + parseRole[0] + ".roles";
-        }
-        Object claim = getClaimValue(token, claimName);
-        if (valueEquals(externalRoleName, claim)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
-            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-            return role;
-        }
-        return null;
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        RoleModel role = hasRole(realm, mapperModel, context);
-        if (role == null) {
-            user.deleteRoleMapping(role);
-        }
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Looks for an external role in a keycloak access token.  If external role exists, grant the user the specified realm or application role.";
-    }
-
-}
+package org.keycloak.broker.oidc.mappers;
+
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
+import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.HardcodedRoleMapper;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.JsonWebToken;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+    private static final String EXTERNAL_ROLE = "external.role";
+
+    static {
+        ProviderConfigProperty property;
+        ProviderConfigProperty property1;
+        property1 = new ProviderConfigProperty();
+        property1.setName(EXTERNAL_ROLE);
+        property1.setLabel("External role");
+        property1.setHelpText("External role to check for.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
+        property1.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property1);
+        property = new ProviderConfigProperty();
+        property.setName(HardcodedRoleMapper.ROLE);
+        property.setLabel("Role");
+        property.setHelpText("Role to grant to user if external role is present.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
+
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Importer";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "External Role to Role";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        RoleModel role = hasRole(realm, mapperModel, context);
+        if (role != null) {
+            user.grantRole(role);
+        }
+    }
+
+    private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
+        //if (token == null) return;
+        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
+        String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
+        String externalRoleName = parseRole[1];
+        String claimName = null;
+        if (parseRole[0] == null) {
+            claimName = "realm_access.roles";
+        } else {
+            claimName = "resource_access." + parseRole[0] + ".roles";
+        }
+        Object claim = getClaimValue(token, claimName);
+        if (valueEquals(externalRoleName, claim)) {
+            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+            return role;
+        }
+        return null;
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        RoleModel role = hasRole(realm, mapperModel, context);
+        if (role == null) {
+            user.deleteRoleMapping(role);
+        }
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Looks for an external role in a keycloak access token.  If external role exists, grant the user the specified realm or application role.";
+    }
+
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java
index d9cb079..b810f48 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java
@@ -1,98 +1,98 @@
-package org.keycloak.broker.oidc.mappers;
-
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
-import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAttributeMapper extends AbstractClaimMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String USER_ATTRIBUTE = "user.attribute";
-
-    static {
-        ProviderConfigProperty property;
-        ProviderConfigProperty property1;
-        property1 = new ProviderConfigProperty();
-        property1.setName(CLAIM);
-        property1.setLabel("Claim");
-        property1.setHelpText("Name of claim to search for in token.  You can reference nested claims using a '.', i.e. 'address.locality'.");
-        property1.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property1);
-        property = new ProviderConfigProperty();
-        property.setName(USER_ATTRIBUTE);
-        property.setLabel("User Attribute Name");
-        property.setHelpText("User attribute name to store claim.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Attribute Importer";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Attribute Importer";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
-        Object value = getClaimValue(mapperModel, context);
-        if (value != null) {
-            user.setSingleAttribute(attribute, value.toString());
-        }
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
-        Object value = getClaimValue(mapperModel, context);
-        String current = user.getFirstAttribute(attribute);
-        if (value != null && !value.equals(current)) {
-            user.setSingleAttribute(attribute, value.toString());
-        } else if (value == null) {
-            user.removeAttribute(attribute);
-        }
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Import declared claim if it exists in ID or access token into the specified user attribute.";
-    }
-
-}
+package org.keycloak.broker.oidc.mappers;
+
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
+import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAttributeMapper extends AbstractClaimMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String USER_ATTRIBUTE = "user.attribute";
+
+    static {
+        ProviderConfigProperty property;
+        ProviderConfigProperty property1;
+        property1 = new ProviderConfigProperty();
+        property1.setName(CLAIM);
+        property1.setLabel("Claim");
+        property1.setHelpText("Name of claim to search for in token.  You can reference nested claims using a '.', i.e. 'address.locality'.");
+        property1.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property1);
+        property = new ProviderConfigProperty();
+        property.setName(USER_ATTRIBUTE);
+        property.setLabel("User Attribute Name");
+        property.setHelpText("User attribute name to store claim.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Attribute Importer";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Attribute Importer";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
+        Object value = getClaimValue(mapperModel, context);
+        if (value != null) {
+            user.setSingleAttribute(attribute, value.toString());
+        }
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
+        Object value = getClaimValue(mapperModel, context);
+        String current = user.getFirstAttribute(attribute);
+        if (value != null && !value.equals(current)) {
+            user.setSingleAttribute(attribute, value.toString());
+        } else if (value == null) {
+            user.removeAttribute(attribute);
+        }
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Import declared claim if it exists in ID or access token into the specified user attribute.";
+    }
+
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UsernameTemplateMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UsernameTemplateMapper.java
index b648f5f..d246086 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UsernameTemplateMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/UsernameTemplateMapper.java
@@ -1,109 +1,109 @@
-package org.keycloak.broker.oidc.mappers;
-
-import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
-import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernameTemplateMapper extends AbstractClaimMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String TEMPLATE = "template";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(TEMPLATE);
-        property.setLabel("Template");
-        property.setHelpText("Template to use to format the username to import.  Substitutions are enclosed in ${}.  For example: '${ALIAS}.${CLAIM.sub}'.  ALIAS is the provider alias.  CLAIM.<NAME> references an ID or Access token claim.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setDefaultValue("${ALIAS}.${CLAIM.preferred_username}");
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "oidc-username-idp-mapper";
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Preprocessor";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Username Template Importer";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-    }
-
-    static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
-
-    @Override
-    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String template = mapperModel.getConfig().get(TEMPLATE);
-        Matcher m = substitution.matcher(template);
-        StringBuffer sb = new StringBuffer();
-        while (m.find()) {
-            String variable = m.group(1);
-            if (variable.equals("ALIAS")) {
-                m.appendReplacement(sb, context.getIdpConfig().getAlias());
-            } else if (variable.equals("UUID")) {
-                m.appendReplacement(sb, KeycloakModelUtils.generateId());
-            } else if (variable.startsWith("CLAIM.")) {
-                String name = variable.substring("CLAIM.".length());
-                Object value = AbstractClaimMapper.getClaimValue(context, name);
-                if (value == null) value = "";
-                m.appendReplacement(sb, value.toString());
-            } else {
-                m.appendReplacement(sb, m.group(1));
-            }
-
-        }
-        m.appendTail(sb);
-        String username = sb.toString();
-        context.setModelUsername(username);
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Format the username to import.";
-    }
-}
+package org.keycloak.broker.oidc.mappers;
+
+import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
+import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernameTemplateMapper extends AbstractClaimMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String TEMPLATE = "template";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(TEMPLATE);
+        property.setLabel("Template");
+        property.setHelpText("Template to use to format the username to import.  Substitutions are enclosed in ${}.  For example: '${ALIAS}.${CLAIM.sub}'.  ALIAS is the provider alias.  CLAIM.<NAME> references an ID or Access token claim.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setDefaultValue("${ALIAS}.${CLAIM.preferred_username}");
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "oidc-username-idp-mapper";
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Preprocessor";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Username Template Importer";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+    }
+
+    static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
+
+    @Override
+    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String template = mapperModel.getConfig().get(TEMPLATE);
+        Matcher m = substitution.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String variable = m.group(1);
+            if (variable.equals("ALIAS")) {
+                m.appendReplacement(sb, context.getIdpConfig().getAlias());
+            } else if (variable.equals("UUID")) {
+                m.appendReplacement(sb, KeycloakModelUtils.generateId());
+            } else if (variable.startsWith("CLAIM.")) {
+                String name = variable.substring("CLAIM.".length());
+                Object value = AbstractClaimMapper.getClaimValue(context, name);
+                if (value == null) value = "";
+                m.appendReplacement(sb, value.toString());
+            } else {
+                m.appendReplacement(sb, m.group(1));
+            }
+
+        }
+        m.appendTail(sb);
+        String username = sb.toString();
+        context.setModelUsername(username);
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Format the username to import.";
+    }
+}
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/util/JsonSimpleHttp.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/util/JsonSimpleHttp.java
index 6f63584..3f9d5f8 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/util/JsonSimpleHttp.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/util/JsonSimpleHttp.java
@@ -1,32 +1,32 @@
-package org.keycloak.broker.oidc.util;
-
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.keycloak.broker.provider.util.SimpleHttp;
-
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JsonSimpleHttp extends SimpleHttp {
-    public JsonSimpleHttp(String url, String method) {
-        super(url, method);
-    }
-
-    public static JsonSimpleHttp doGet(String url) {
-        return new JsonSimpleHttp(url, "GET");
-    }
-
-    public static JsonSimpleHttp doPost(String url) {
-        return new JsonSimpleHttp(url, "POST");
-    }
-
-    private static ObjectMapper mapper = new ObjectMapper();
-
-    public static JsonNode asJson(SimpleHttp request) throws IOException {
-        return mapper.readTree(request.asString());
-    }
-
-}
+package org.keycloak.broker.oidc.util;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.keycloak.broker.provider.util.SimpleHttp;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JsonSimpleHttp extends SimpleHttp {
+    public JsonSimpleHttp(String url, String method) {
+        super(url, method);
+    }
+
+    public static JsonSimpleHttp doGet(String url) {
+        return new JsonSimpleHttp(url, "GET");
+    }
+
+    public static JsonSimpleHttp doPost(String url) {
+        return new JsonSimpleHttp(url, "POST");
+    }
+
+    private static ObjectMapper mapper = new ObjectMapper();
+
+    public static JsonNode asJson(SimpleHttp request) throws IOException {
+        return mapper.readTree(request.asString());
+    }
+
+}
diff --git a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory
index faa4eb8..43589a2 100755
--- a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory
+++ b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory
@@ -1,2 +1,2 @@
-org.keycloak.broker.oidc.OIDCIdentityProviderFactory
+org.keycloak.broker.oidc.OIDCIdentityProviderFactory
 org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory
\ No newline at end of file
diff --git a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
index 62e6741..0fdd7d8 100755
--- a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
+++ b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
@@ -1,4 +1,4 @@
-org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
-org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
-org.keycloak.broker.oidc.mappers.UserAttributeMapper
+org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
+org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
+org.keycloak.broker.oidc.mappers.UserAttributeMapper
 org.keycloak.broker.oidc.mappers.UsernameTemplateMapper
\ No newline at end of file

broker/pom.xml 46(+23 -23)

diff --git a/broker/pom.xml b/broker/pom.xml
index 885206e..2e2845c 100755
--- a/broker/pom.xml
+++ b/broker/pom.xml
@@ -1,23 +1,23 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-broker-parent</artifactId>
-    <name>Keycloak Broker Parent</name>
-    <description/>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>core</module>
-        <module>oidc</module>
-        <module>saml</module>
-    </modules>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-broker-parent</artifactId>
+    <name>Keycloak Broker Parent</name>
+    <description/>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>core</module>
+        <module>oidc</module>
+        <module>saml</module>
+    </modules>
+
+</project>

broker/saml/pom.xml 100(+50 -50)

diff --git a/broker/saml/pom.xml b/broker/saml/pom.xml
index dfeeb11..a33d7f4 100755
--- a/broker/saml/pom.xml
+++ b/broker/saml/pom.xml
@@ -1,50 +1,50 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-broker-saml</artifactId>
-    <name>Keycloak Broker - SAML Identity Provider</name>
-    <description/>
-    <packaging>jar</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-protocol</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-broker-saml</artifactId>
+    <name>Keycloak Broker - SAML Identity Provider</name>
+    <description/>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-protocol</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
index c90b0b2..4014a9a 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
@@ -1,140 +1,140 @@
-package org.keycloak.broker.saml.mappers;
-
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.HardcodedRoleMapper;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.broker.saml.SAMLEndpoint;
-import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.JsonWebToken;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String ATTRIBUTE_NAME = "attribute.name";
-    public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
-    public static final String ATTRIBUTE_VALUE = "attribute.value";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_NAME);
-        property.setLabel("Attribute Name");
-        property.setHelpText("Name of attribute to search for in assertion.  You can leave this blank and specify a friendly name instead.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_FRIENDLY_NAME);
-        property.setLabel("Friendly Name");
-        property.setHelpText("Friendly name of attribute to search for in assertion.  You can leave this blank and specify a name instead.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_VALUE);
-        property.setLabel("Attribute Value");
-        property.setHelpText("Value the attribute must have.  If the attribute is a list, then the value must be contained in the list.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(HardcodedRoleMapper.ROLE);
-        property.setLabel("Role");
-        property.setHelpText("Role to grant to user.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "saml-role-idp-mapper";
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Mapper";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "SAML Attribute to Role";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        if (isAttributePresent(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
-            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-            user.grantRole(role);
-        }
-    }
-
-    protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
-        if (name != null && name.trim().equals("")) name = null;
-        String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
-        if (friendly != null && friendly.trim().equals("")) friendly = null;
-        String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
-        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
-        for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-            for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                AttributeType attr = choice.getAttribute();
-                if (name != null && !name.equals(attr.getName())) continue;
-                if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
-                for (Object val : attr.getAttributeValue()) {
-                    if (val.equals(desiredValue)) return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        if (!isAttributePresent(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
-            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
-            user.deleteRoleMapping(role);
-        }
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "If a claim exists, grant the user the specified realm or application role.";
-    }
-
-}
+package org.keycloak.broker.saml.mappers;
+
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.HardcodedRoleMapper;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.saml.SAMLEndpoint;
+import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.JsonWebToken;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String ATTRIBUTE_NAME = "attribute.name";
+    public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
+    public static final String ATTRIBUTE_VALUE = "attribute.value";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_NAME);
+        property.setLabel("Attribute Name");
+        property.setHelpText("Name of attribute to search for in assertion.  You can leave this blank and specify a friendly name instead.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_FRIENDLY_NAME);
+        property.setLabel("Friendly Name");
+        property.setHelpText("Friendly name of attribute to search for in assertion.  You can leave this blank and specify a name instead.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_VALUE);
+        property.setLabel("Attribute Value");
+        property.setHelpText("Value the attribute must have.  If the attribute is a list, then the value must be contained in the list.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(HardcodedRoleMapper.ROLE);
+        property.setLabel("Role");
+        property.setHelpText("Role to grant to user.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "saml-role-idp-mapper";
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Mapper";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "SAML Attribute to Role";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
+        if (isAttributePresent(mapperModel, context)) {
+            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+            user.grantRole(role);
+        }
+    }
+
+    protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
+        if (name != null && name.trim().equals("")) name = null;
+        String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
+        if (friendly != null && friendly.trim().equals("")) friendly = null;
+        String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
+        for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+            for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+                AttributeType attr = choice.getAttribute();
+                if (name != null && !name.equals(attr.getName())) continue;
+                if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
+                for (Object val : attr.getAttributeValue()) {
+                    if (val.equals(desiredValue)) return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
+        if (!isAttributePresent(mapperModel, context)) {
+            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+            user.deleteRoleMapping(role);
+        }
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "If a claim exists, grant the user the specified realm or application role.";
+    }
+
+}
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java
index a1feac8..9834352 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java
@@ -1,129 +1,129 @@
-package org.keycloak.broker.saml.mappers;
-
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.saml.SAMLEndpoint;
-import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAttributeMapper extends AbstractIdentityProviderMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String ATTRIBUTE_NAME = "attribute.name";
-    public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
-    public static final String USER_ATTRIBUTE = "user.attribute";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_NAME);
-        property.setLabel("Attribute Name");
-        property.setHelpText("Name of attribute to search for in assertion.  You can leave this blank and specify a friendly name instead.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_FRIENDLY_NAME);
-        property.setLabel("Friendly Name");
-        property.setHelpText("Friendly name of attribute to search for in assertion.  You can leave this blank and specify a name instead.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(USER_ATTRIBUTE);
-        property.setLabel("User Attribute Name");
-        property.setHelpText("User attribute name to store saml attribute.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Attribute Importer";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Attribute Importer";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
-        Object value = getAttribute(mapperModel, context);
-        if (value != null) {
-            user.setSingleAttribute(attribute, value.toString());
-        }
-    }
-
-    protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
-        if (name != null && name.trim().equals("")) name = null;
-        String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
-        if (friendly != null && friendly.trim().equals("")) friendly = null;
-        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
-        for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-            for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                AttributeType attr = choice.getAttribute();
-                if (name != null && !name.equals(attr.getName())) continue;
-                if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
-
-                List<Object> attributeValue = attr.getAttributeValue();
-                if (attributeValue == null || attributeValue.isEmpty()) return null;
-                return attributeValue.get(0).toString();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
-        Object value = getAttribute(mapperModel, context);
-        String current = user.getFirstAttribute(attribute);
-        if (value != null && !value.equals(current)) {
-            user.setSingleAttribute(attribute, value.toString());
-        } else if (value == null) {
-            user.removeAttribute(attribute);
-        }
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
-    }
-
-}
+package org.keycloak.broker.saml.mappers;
+
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.saml.SAMLEndpoint;
+import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAttributeMapper extends AbstractIdentityProviderMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String ATTRIBUTE_NAME = "attribute.name";
+    public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
+    public static final String USER_ATTRIBUTE = "user.attribute";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_NAME);
+        property.setLabel("Attribute Name");
+        property.setHelpText("Name of attribute to search for in assertion.  You can leave this blank and specify a friendly name instead.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_FRIENDLY_NAME);
+        property.setLabel("Friendly Name");
+        property.setHelpText("Friendly name of attribute to search for in assertion.  You can leave this blank and specify a name instead.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(USER_ATTRIBUTE);
+        property.setLabel("User Attribute Name");
+        property.setHelpText("User attribute name to store saml attribute.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Attribute Importer";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Attribute Importer";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
+        Object value = getAttribute(mapperModel, context);
+        if (value != null) {
+            user.setSingleAttribute(attribute, value.toString());
+        }
+    }
+
+    protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
+        if (name != null && name.trim().equals("")) name = null;
+        String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
+        if (friendly != null && friendly.trim().equals("")) friendly = null;
+        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
+        for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+            for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+                AttributeType attr = choice.getAttribute();
+                if (name != null && !name.equals(attr.getName())) continue;
+                if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
+
+                List<Object> attributeValue = attr.getAttributeValue();
+                if (attributeValue == null || attributeValue.isEmpty()) return null;
+                return attributeValue.get(0).toString();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
+        Object value = getAttribute(mapperModel, context);
+        String current = user.getFirstAttribute(attribute);
+        if (value != null && !value.equals(current)) {
+            user.setSingleAttribute(attribute, value.toString());
+        } else if (value == null) {
+            user.removeAttribute(attribute);
+        }
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
+    }
+
+}
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java
index 0ed0c1b..0a44e4b 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/UsernameTemplateMapper.java
@@ -1,133 +1,133 @@
-package org.keycloak.broker.saml.mappers;
-
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.saml.SAMLEndpoint;
-import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.dom.saml.v2.assertion.NameIDType;
-import org.keycloak.dom.saml.v2.assertion.SubjectType;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
-
-    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String TEMPLATE = "template";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(TEMPLATE);
-        property.setLabel("Template");
-        property.setHelpText("Template to use to format the username to import.  Substitutions are enclosed in ${}.  For example: '${ALIAS}.${NAMEID}'.  ALIAS is the provider alias.  NAMEID is that SAML name id assertion.  ATTRIBUTE.<NAME> references a SAML attribute where name is the attribute name or friendly name.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setDefaultValue("${ALIAS}.${NAMEID}");
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "saml-username-idp-mapper";
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String[] getCompatibleProviders() {
-        return COMPATIBLE_PROVIDERS;
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Preprocessor";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Username Template Importer";
-    }
-
-    @Override
-    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-
-    }
-
-    @Override
-    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-
-    }
-    static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
-
-    @Override
-    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
-        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
-        String template = mapperModel.getConfig().get(TEMPLATE);
-        Matcher m = substitution.matcher(template);
-        StringBuffer sb = new StringBuffer();
-        while (m.find()) {
-            String variable = m.group(1);
-            if (variable.equals("ALIAS")) {
-                m.appendReplacement(sb, context.getIdpConfig().getAlias());
-            } else if (variable.equals("UUID")) {
-                m.appendReplacement(sb, KeycloakModelUtils.generateId());
-            } else if (variable.equals("NAMEID")) {
-                SubjectType subject = assertion.getSubject();
-                SubjectType.STSubType subType = subject.getSubType();
-                NameIDType subjectNameID = (NameIDType) subType.getBaseID();
-                m.appendReplacement(sb, subjectNameID.getValue());
-            } else if (variable.startsWith("ATTRIBUTE.")) {
-                String name = variable.substring("ATTRIBUTE.".length());
-                String value = "";
-                for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-                    for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                        AttributeType attr = choice.getAttribute();
-                        if (name.equals(attr.getName()) || name.equals(attr.getFriendlyName())) {
-                            List<Object> attributeValue = attr.getAttributeValue();
-                            if (attributeValue != null && !attributeValue.isEmpty()) {
-                                value = attributeValue.get(0).toString();
-                            }
-                            break;
-                        }
-                    }
-                }
-                m.appendReplacement(sb, value);
-            } else {
-                m.appendReplacement(sb, m.group(1));
-            }
-
-        }
-        m.appendTail(sb);
-        context.setModelUsername(sb.toString());
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Format the username to import.";
-    }
-
-}
+package org.keycloak.broker.saml.mappers;
+
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.saml.SAMLEndpoint;
+import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
+
+    public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String TEMPLATE = "template";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(TEMPLATE);
+        property.setLabel("Template");
+        property.setHelpText("Template to use to format the username to import.  Substitutions are enclosed in ${}.  For example: '${ALIAS}.${NAMEID}'.  ALIAS is the provider alias.  NAMEID is that SAML name id assertion.  ATTRIBUTE.<NAME> references a SAML attribute where name is the attribute name or friendly name.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setDefaultValue("${ALIAS}.${NAMEID}");
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "saml-username-idp-mapper";
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String[] getCompatibleProviders() {
+        return COMPATIBLE_PROVIDERS;
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Preprocessor";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Username Template Importer";
+    }
+
+    @Override
+    public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+
+    }
+
+    @Override
+    public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+
+    }
+    static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
+
+    @Override
+    public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+        AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
+        String template = mapperModel.getConfig().get(TEMPLATE);
+        Matcher m = substitution.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String variable = m.group(1);
+            if (variable.equals("ALIAS")) {
+                m.appendReplacement(sb, context.getIdpConfig().getAlias());
+            } else if (variable.equals("UUID")) {
+                m.appendReplacement(sb, KeycloakModelUtils.generateId());
+            } else if (variable.equals("NAMEID")) {
+                SubjectType subject = assertion.getSubject();
+                SubjectType.STSubType subType = subject.getSubType();
+                NameIDType subjectNameID = (NameIDType) subType.getBaseID();
+                m.appendReplacement(sb, subjectNameID.getValue());
+            } else if (variable.startsWith("ATTRIBUTE.")) {
+                String name = variable.substring("ATTRIBUTE.".length());
+                String value = "";
+                for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+                    for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+                        AttributeType attr = choice.getAttribute();
+                        if (name.equals(attr.getName()) || name.equals(attr.getFriendlyName())) {
+                            List<Object> attributeValue = attr.getAttributeValue();
+                            if (attributeValue != null && !attributeValue.isEmpty()) {
+                                value = attributeValue.get(0).toString();
+                            }
+                            break;
+                        }
+                    }
+                }
+                m.appendReplacement(sb, value);
+            } else {
+                m.appendReplacement(sb, m.group(1));
+            }
+
+        }
+        m.appendTail(sb);
+        context.setModelUsername(sb.toString());
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Format the username to import.";
+    }
+
+}
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
index 21a0e58..f6ea2f5 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
@@ -1,492 +1,492 @@
-package org.keycloak.broker.saml;
-
-import org.jboss.logging.Logger;
-import org.keycloak.ClientConnection;
-import org.keycloak.VerificationException;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.broker.provider.IdentityProvider;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
-import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
-import org.keycloak.dom.saml.v2.assertion.NameIDType;
-import org.keycloak.dom.saml.v2.assertion.SubjectType;
-import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
-import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
-import org.keycloak.protocol.saml.SAMLRequestParser;
-import org.keycloak.protocol.saml.SamlProtocol;
-import org.keycloak.protocol.saml.SamlProtocolUtils;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.common.util.DocumentUtil;
-import org.keycloak.saml.common.util.StaxParserUtil;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
-import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
-import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
-import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
-import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
-import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
-import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-import org.keycloak.services.ErrorPage;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.messages.Messages;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.xml.namespace.QName;
-import java.io.IOException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAMLEndpoint {
-    protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
-    public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
-    public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
-    public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
-    public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
-    public static final String SAML_ASSERTION = "SAML_ASSERTION";
-    public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
-    protected RealmModel realm;
-    protected EventBuilder event;
-    protected SAMLIdentityProviderConfig config;
-    protected IdentityProvider.AuthenticationCallback callback;
-    protected SAMLIdentityProvider provider;
-
-    @Context
-    private UriInfo uriInfo;
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private ClientConnection clientConnection;
-
-    @Context
-    private HttpHeaders headers;
-
-
-    public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
-        this.realm = realm;
-        this.config = config;
-        this.callback = callback;
-        this.provider = provider;
-    }
-
-    @GET
-    public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
-                                    @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
-                                    @QueryParam(GeneralConstants.RELAY_STATE) String relayState)  {
-        return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
-    }
-
-
-    /**
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
-                                @FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
-                                @FormParam(GeneralConstants.RELAY_STATE) String relayState) {
-        return new PostBinding().execute(samlRequest, samlResponse, relayState);
-    }
-
-    protected abstract class Binding {
-        private boolean checkSsl() {
-            if (uriInfo.getBaseUri().getScheme().equals("https")) {
-                return true;
-            } else {
-                return !realm.getSslRequired().isRequired(clientConnection);
-            }
-        }
-
-        protected Response basicChecks(String samlRequest, String samlResponse) {
-            if (!checkSsl()) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.SSL_REQUIRED);
-                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
-            }
-            if (!realm.isEnabled()) {
-                event.event(EventType.LOGIN_ERROR);
-                event.error(Errors.REALM_DISABLED);
-                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
-            }
-
-            if (samlRequest == null && samlResponse == null) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_REQUEST);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-
-            }
-            return null;
-        }
-
-        protected abstract String getBindingType();
-        protected abstract void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException;
-        protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
-        protected abstract SAMLDocumentHolder extractResponseDocument(String response);
-        protected PublicKey getIDPKey() {
-            X509Certificate certificate = null;
-            try {
-                certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
-            } catch (ProcessingException e) {
-                throw new RuntimeException(e);
-            }
-            return certificate.getPublicKey();
-        }
-
-        public Response execute(String samlRequest, String samlResponse, String relayState) {
-            event = new EventBuilder(realm, session, clientConnection);
-            Response response = basicChecks(samlRequest, samlResponse);
-            if (response != null) return response;
-            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
-            else return handleSamlResponse(samlResponse, relayState);
-        }
-
-        protected Response handleSamlRequest(String samlRequest, String relayState) {
-            SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
-            RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
-            // validate destination
-            if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
-                event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
-                event.detail(Details.REASON, "invalid_destination");
-                event.error(Errors.INVALID_SAML_RESPONSE);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-            if (config.isValidateSignature()) {
-                try {
-                    verifySignature(holder);
-                } catch (VerificationException e) {
-                    logger.error("validation failed", e);
-                    event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
-                    event.error(Errors.INVALID_SIGNATURE);
-                    return ErrorPage.error(session, Messages.INVALID_REQUESTER);
-                }
-            }
-
-            if (requestAbstractType instanceof LogoutRequestType) {
-                logger.debug("** logout request");
-                event.event(EventType.LOGOUT);
-                LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
-                return logoutRequest(logout, relayState);
-
-            } else {
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_TOKEN);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-        }
-
-        protected Response logoutRequest(LogoutRequestType request, String relayState) {
-            String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
-            if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
-                List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
-                for (UserSessionModel userSession : userSessions) {
-                    if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
-                        continue;
-                    }
-                    try {
-                        AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
-                    } catch (Exception e) {
-                        logger.warn("failed to do backchannel logout for userSession", e);
-                    }
-                }
-
-            }  else {
-                for (String sessionIndex : request.getSessionIndex()) {
-                    String brokerSessionId = brokerUserId + "." + sessionIndex;
-                    UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
-                    if (userSession != null) {
-                        if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
-                            continue;
-                        }
-                        try {
-                            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
-                        } catch (Exception e) {
-                            logger.warn("failed to do backchannel logout for userSession", e);
-                        }
-                    }
-                }
-            }
-
-            String issuerURL = getEntityId(uriInfo, realm);
-            SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
-            builder.logoutRequestID(request.getID());
-            builder.destination(config.getSingleLogoutServiceUrl());
-            builder.issuer(issuerURL);
-            builder.relayState(relayState);
-            if (config.isWantAuthnRequestsSigned()) {
-                builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                        .signDocument();
-            }
-            try {
-                if (config.isPostBindingResponse()) {
-                    return builder.postBinding().response();
-                } else {
-                    return builder.redirectBinding().response();
-                }
-            } catch (ConfigurationException e) {
-                throw new RuntimeException(e);
-            } catch (ProcessingException e) {
-                throw new RuntimeException(e);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-
-        }
-
-        private String getEntityId(UriInfo uriInfo, RealmModel realm) {
-            return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
-        }
-        protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
-
-            try {
-                AssertionType assertion = getAssertion(responseType);
-                SubjectType subject = assertion.getSubject();
-                SubjectType.STSubType subType = subject.getSubType();
-                NameIDType subjectNameID = (NameIDType) subType.getBaseID();
-                //Map<String, String> notes = new HashMap<>();
-                BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
-                identity.setCode(relayState);
-                identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
-                identity.getContextData().put(SAML_ASSERTION, assertion);
-
-                identity.setUsername(subjectNameID.getValue());
-
-                //SAML Spec 2.2.2 Format is optional
-                if (subjectNameID.getFormat() != null && subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
-                    identity.setEmail(subjectNameID.getValue());
-                }
-
-                if (config.isStoreToken()) {
-                    identity.setToken(samlResponse);
-                }
-
-                AuthnStatementType authn = null;
-                for (Object statement : assertion.getStatements()) {
-                    if (statement instanceof AuthnStatementType) {
-                        authn = (AuthnStatementType)statement;
-                        identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
-                        break;
-                    }
-                }
-                if (assertion.getAttributeStatements() != null ) {
-                    for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
-                        for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
-                            AttributeType attribute = choice.getAttribute();
-                            if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
-                                    || X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
-                                if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
-                            }
-                        }
-
-                    }
-
-                }
-                String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
-                identity.setBrokerUserId(brokerUserId);
-                identity.setIdpConfig(config);
-                identity.setIdp(provider);
-                if (authn != null && authn.getSessionIndex() != null) {
-                    identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
-                 }
-
-
-                return callback.authenticated(identity);
-
-            } catch (Exception e) {
-                throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
-            }
-        }
-
-
-
-        private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
-            List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
-
-            if (assertions.isEmpty()) {
-                throw new IdentityBrokerException("No assertion from response.");
-            }
-
-            ResponseType.RTChoiceType rtChoiceType = assertions.get(0);
-            EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
-
-            if (encryptedAssertion != null) {
-                decryptAssertion(responseType, realm.getPrivateKey());
-
-            }
-            return responseType.getAssertions().get(0).getAssertion();
-        }
-
-        public Response handleSamlResponse(String samlResponse, String relayState) {
-            SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
-            StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
-            // validate destination
-            if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
-                event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
-                event.detail(Details.REASON, "invalid_destination");
-                event.error(Errors.INVALID_SAML_RESPONSE);
-                return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
-            }
-            if (config.isValidateSignature()) {
-                try {
-                    verifySignature(holder);
-                } catch (VerificationException e) {
-                    logger.error("validation failed", e);
-                    event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
-                    event.error(Errors.INVALID_SIGNATURE);
-                    return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
-                }
-            }
-            if (statusResponse instanceof ResponseType) {
-                return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
-
-            } else {
-                // todo need to check that it is actually a LogoutResponse
-                return handleLogoutResponse(holder, statusResponse, relayState);
-            }
-            //throw new RuntimeException("Unknown response type");
-
-        }
-
-        protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
-            if (relayState == null) {
-                logger.error("no valid user session");
-                event.event(EventType.LOGOUT);
-                event.error(Errors.USER_SESSION_NOT_FOUND);
-                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
-            }
-            UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
-            if (userSession == null) {
-                logger.error("no valid user session");
-                event.event(EventType.LOGOUT);
-                event.error(Errors.USER_SESSION_NOT_FOUND);
-                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
-            }
-            if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
-                logger.error("usersession in different state");
-                event.event(EventType.LOGOUT);
-                event.error(Errors.USER_SESSION_NOT_FOUND);
-                return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
-            }
-            return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
-        }
-
-
-        protected ResponseType decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ProcessingException {
-            SAML2Response saml2Response = new SAML2Response();
-
-            try {
-                Document doc = saml2Response.convert(responseType);
-                Element enc = DocumentUtil.getElement(doc, new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
-
-                if (enc == null) {
-                    throw new IdentityBrokerException("No encrypted assertion found.");
-                }
-
-                String oldID = enc.getAttribute(JBossSAMLConstants.ID.get());
-                Document newDoc = DocumentUtil.createDocument();
-                Node importedNode = newDoc.importNode(enc, true);
-                newDoc.appendChild(importedNode);
-
-                Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
-                SAMLParser parser = new SAMLParser();
-
-                JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
-                AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
-                        .getNodeAsStream(decryptedDocumentElement)));
-
-                responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
-
-                return responseType;
-            } catch (Exception e) {
-                throw new IdentityBrokerException("Could not decrypt assertion.", e);
-            }
-        }
-
-
-    }
-
-    protected class PostBinding extends Binding {
-        @Override
-        protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
-            SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
-        }
-
-        @Override
-        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
-            return SAMLRequestParser.parseRequestPostBinding(samlRequest);
-        }
-        @Override
-        protected SAMLDocumentHolder extractResponseDocument(String response) {
-            byte[] samlBytes = PostBindingUtil.base64Decode(response);
-            String xml = new String(samlBytes);
-            return SAMLRequestParser.parseResponseDocument(samlBytes);
-        }
-
-        @Override
-        protected String getBindingType() {
-            return SamlProtocol.SAML_POST_BINDING;
-        }
-    }
-
-    protected class RedirectBinding extends Binding {
-        @Override
-        protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
-            PublicKey publicKey = getIDPKey();
-            SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
-        }
-
-
-
-        @Override
-        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
-            return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
-        }
-
-        @Override
-        protected SAMLDocumentHolder extractResponseDocument(String response) {
-            return SAMLRequestParser.parseRequestRedirectBinding(response);
-        }
-
-        @Override
-        protected String getBindingType() {
-            return SamlProtocol.SAML_REDIRECT_BINDING;
-        }
-
-    }
-
-}
+package org.keycloak.broker.saml;
+
+import org.jboss.logging.Logger;
+import org.keycloak.ClientConnection;
+import org.keycloak.VerificationException;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.provider.IdentityProvider;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
+import org.keycloak.protocol.saml.SAMLRequestParser;
+import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.protocol.saml.SamlProtocolUtils;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.DocumentUtil;
+import org.keycloak.saml.common.util.StaxParserUtil;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
+import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
+import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
+import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
+import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+import org.keycloak.services.ErrorPage;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.messages.Messages;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAMLEndpoint {
+    protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
+    public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
+    public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
+    public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
+    public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
+    public static final String SAML_ASSERTION = "SAML_ASSERTION";
+    public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
+    protected RealmModel realm;
+    protected EventBuilder event;
+    protected SAMLIdentityProviderConfig config;
+    protected IdentityProvider.AuthenticationCallback callback;
+    protected SAMLIdentityProvider provider;
+
+    @Context
+    private UriInfo uriInfo;
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private ClientConnection clientConnection;
+
+    @Context
+    private HttpHeaders headers;
+
+
+    public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
+        this.realm = realm;
+        this.config = config;
+        this.callback = callback;
+        this.provider = provider;
+    }
+
+    @GET
+    public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
+                                    @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
+                                    @QueryParam(GeneralConstants.RELAY_STATE) String relayState)  {
+        return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
+    }
+
+
+    /**
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
+                                @FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
+                                @FormParam(GeneralConstants.RELAY_STATE) String relayState) {
+        return new PostBinding().execute(samlRequest, samlResponse, relayState);
+    }
+
+    protected abstract class Binding {
+        private boolean checkSsl() {
+            if (uriInfo.getBaseUri().getScheme().equals("https")) {
+                return true;
+            } else {
+                return !realm.getSslRequired().isRequired(clientConnection);
+            }
+        }
+
+        protected Response basicChecks(String samlRequest, String samlResponse) {
+            if (!checkSsl()) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.SSL_REQUIRED);
+                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
+            }
+            if (!realm.isEnabled()) {
+                event.event(EventType.LOGIN_ERROR);
+                event.error(Errors.REALM_DISABLED);
+                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
+            }
+
+            if (samlRequest == null && samlResponse == null) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+
+            }
+            return null;
+        }
+
+        protected abstract String getBindingType();
+        protected abstract void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException;
+        protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
+        protected abstract SAMLDocumentHolder extractResponseDocument(String response);
+        protected PublicKey getIDPKey() {
+            X509Certificate certificate = null;
+            try {
+                certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
+            } catch (ProcessingException e) {
+                throw new RuntimeException(e);
+            }
+            return certificate.getPublicKey();
+        }
+
+        public Response execute(String samlRequest, String samlResponse, String relayState) {
+            event = new EventBuilder(realm, session, clientConnection);
+            Response response = basicChecks(samlRequest, samlResponse);
+            if (response != null) return response;
+            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
+            else return handleSamlResponse(samlResponse, relayState);
+        }
+
+        protected Response handleSamlRequest(String samlRequest, String relayState) {
+            SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
+            RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
+            // validate destination
+            if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
+                event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
+                event.detail(Details.REASON, "invalid_destination");
+                event.error(Errors.INVALID_SAML_RESPONSE);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+            if (config.isValidateSignature()) {
+                try {
+                    verifySignature(holder);
+                } catch (VerificationException e) {
+                    logger.error("validation failed", e);
+                    event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
+                    event.error(Errors.INVALID_SIGNATURE);
+                    return ErrorPage.error(session, Messages.INVALID_REQUESTER);
+                }
+            }
+
+            if (requestAbstractType instanceof LogoutRequestType) {
+                logger.debug("** logout request");
+                event.event(EventType.LOGOUT);
+                LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
+                return logoutRequest(logout, relayState);
+
+            } else {
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_TOKEN);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+        }
+
+        protected Response logoutRequest(LogoutRequestType request, String relayState) {
+            String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
+            if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
+                List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
+                for (UserSessionModel userSession : userSessions) {
+                    if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
+                        continue;
+                    }
+                    try {
+                        AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
+                    } catch (Exception e) {
+                        logger.warn("failed to do backchannel logout for userSession", e);
+                    }
+                }
+
+            }  else {
+                for (String sessionIndex : request.getSessionIndex()) {
+                    String brokerSessionId = brokerUserId + "." + sessionIndex;
+                    UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
+                    if (userSession != null) {
+                        if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
+                            continue;
+                        }
+                        try {
+                            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
+                        } catch (Exception e) {
+                            logger.warn("failed to do backchannel logout for userSession", e);
+                        }
+                    }
+                }
+            }
+
+            String issuerURL = getEntityId(uriInfo, realm);
+            SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
+            builder.logoutRequestID(request.getID());
+            builder.destination(config.getSingleLogoutServiceUrl());
+            builder.issuer(issuerURL);
+            builder.relayState(relayState);
+            if (config.isWantAuthnRequestsSigned()) {
+                builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                        .signDocument();
+            }
+            try {
+                if (config.isPostBindingResponse()) {
+                    return builder.postBinding().response();
+                } else {
+                    return builder.redirectBinding().response();
+                }
+            } catch (ConfigurationException e) {
+                throw new RuntimeException(e);
+            } catch (ProcessingException e) {
+                throw new RuntimeException(e);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        private String getEntityId(UriInfo uriInfo, RealmModel realm) {
+            return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
+        }
+        protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
+
+            try {
+                AssertionType assertion = getAssertion(responseType);
+                SubjectType subject = assertion.getSubject();
+                SubjectType.STSubType subType = subject.getSubType();
+                NameIDType subjectNameID = (NameIDType) subType.getBaseID();
+                //Map<String, String> notes = new HashMap<>();
+                BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
+                identity.setCode(relayState);
+                identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
+                identity.getContextData().put(SAML_ASSERTION, assertion);
+
+                identity.setUsername(subjectNameID.getValue());
+
+                //SAML Spec 2.2.2 Format is optional
+                if (subjectNameID.getFormat() != null && subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
+                    identity.setEmail(subjectNameID.getValue());
+                }
+
+                if (config.isStoreToken()) {
+                    identity.setToken(samlResponse);
+                }
+
+                AuthnStatementType authn = null;
+                for (Object statement : assertion.getStatements()) {
+                    if (statement instanceof AuthnStatementType) {
+                        authn = (AuthnStatementType)statement;
+                        identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
+                        break;
+                    }
+                }
+                if (assertion.getAttributeStatements() != null ) {
+                    for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
+                        for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
+                            AttributeType attribute = choice.getAttribute();
+                            if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
+                                    || X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
+                                if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
+                            }
+                        }
+
+                    }
+
+                }
+                String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
+                identity.setBrokerUserId(brokerUserId);
+                identity.setIdpConfig(config);
+                identity.setIdp(provider);
+                if (authn != null && authn.getSessionIndex() != null) {
+                    identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
+                 }
+
+
+                return callback.authenticated(identity);
+
+            } catch (Exception e) {
+                throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
+            }
+        }
+
+
+
+        private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
+            List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
+
+            if (assertions.isEmpty()) {
+                throw new IdentityBrokerException("No assertion from response.");
+            }
+
+            ResponseType.RTChoiceType rtChoiceType = assertions.get(0);
+            EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
+
+            if (encryptedAssertion != null) {
+                decryptAssertion(responseType, realm.getPrivateKey());
+
+            }
+            return responseType.getAssertions().get(0).getAssertion();
+        }
+
+        public Response handleSamlResponse(String samlResponse, String relayState) {
+            SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
+            StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
+            // validate destination
+            if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
+                event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
+                event.detail(Details.REASON, "invalid_destination");
+                event.error(Errors.INVALID_SAML_RESPONSE);
+                return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
+            }
+            if (config.isValidateSignature()) {
+                try {
+                    verifySignature(holder);
+                } catch (VerificationException e) {
+                    logger.error("validation failed", e);
+                    event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
+                    event.error(Errors.INVALID_SIGNATURE);
+                    return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
+                }
+            }
+            if (statusResponse instanceof ResponseType) {
+                return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
+
+            } else {
+                // todo need to check that it is actually a LogoutResponse
+                return handleLogoutResponse(holder, statusResponse, relayState);
+            }
+            //throw new RuntimeException("Unknown response type");
+
+        }
+
+        protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
+            if (relayState == null) {
+                logger.error("no valid user session");
+                event.event(EventType.LOGOUT);
+                event.error(Errors.USER_SESSION_NOT_FOUND);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+            }
+            UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
+            if (userSession == null) {
+                logger.error("no valid user session");
+                event.event(EventType.LOGOUT);
+                event.error(Errors.USER_SESSION_NOT_FOUND);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+            }
+            if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
+                logger.error("usersession in different state");
+                event.event(EventType.LOGOUT);
+                event.error(Errors.USER_SESSION_NOT_FOUND);
+                return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
+            }
+            return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
+        }
+
+
+        protected ResponseType decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ProcessingException {
+            SAML2Response saml2Response = new SAML2Response();
+
+            try {
+                Document doc = saml2Response.convert(responseType);
+                Element enc = DocumentUtil.getElement(doc, new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
+
+                if (enc == null) {
+                    throw new IdentityBrokerException("No encrypted assertion found.");
+                }
+
+                String oldID = enc.getAttribute(JBossSAMLConstants.ID.get());
+                Document newDoc = DocumentUtil.createDocument();
+                Node importedNode = newDoc.importNode(enc, true);
+                newDoc.appendChild(importedNode);
+
+                Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
+                SAMLParser parser = new SAMLParser();
+
+                JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
+                AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
+                        .getNodeAsStream(decryptedDocumentElement)));
+
+                responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
+
+                return responseType;
+            } catch (Exception e) {
+                throw new IdentityBrokerException("Could not decrypt assertion.", e);
+            }
+        }
+
+
+    }
+
+    protected class PostBinding extends Binding {
+        @Override
+        protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
+            SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
+        }
+
+        @Override
+        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
+            return SAMLRequestParser.parseRequestPostBinding(samlRequest);
+        }
+        @Override
+        protected SAMLDocumentHolder extractResponseDocument(String response) {
+            byte[] samlBytes = PostBindingUtil.base64Decode(response);
+            String xml = new String(samlBytes);
+            return SAMLRequestParser.parseResponseDocument(samlBytes);
+        }
+
+        @Override
+        protected String getBindingType() {
+            return SamlProtocol.SAML_POST_BINDING;
+        }
+    }
+
+    protected class RedirectBinding extends Binding {
+        @Override
+        protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
+            PublicKey publicKey = getIDPKey();
+            SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
+        }
+
+
+
+        @Override
+        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
+            return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
+        }
+
+        @Override
+        protected SAMLDocumentHolder extractResponseDocument(String response) {
+            return SAMLRequestParser.parseRequestRedirectBinding(response);
+        }
+
+        @Override
+        protected String getBindingType() {
+            return SamlProtocol.SAML_REDIRECT_BINDING;
+        }
+
+    }
+
+}
diff --git a/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
index 89cdf92..75cb4b0 100755
--- a/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
+++ b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
@@ -1,3 +1,3 @@
-org.keycloak.broker.saml.mappers.AttributeToRoleMapper
-org.keycloak.broker.saml.mappers.UserAttributeMapper
+org.keycloak.broker.saml.mappers.AttributeToRoleMapper
+org.keycloak.broker.saml.mappers.UserAttributeMapper
 org.keycloak.broker.saml.mappers.UsernameTemplateMapper
\ No newline at end of file
diff --git a/connections/file/src/main/java/org/keycloak/connections/file/Model.java b/connections/file/src/main/java/org/keycloak/connections/file/Model.java
index 7350c38..a609cea 100755
--- a/connections/file/src/main/java/org/keycloak/connections/file/Model.java
+++ b/connections/file/src/main/java/org/keycloak/connections/file/Model.java
@@ -1,30 +1,30 @@
-package org.keycloak.connections.file;
-
-import org.keycloak.representations.idm.RealmRepresentation;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class Model {
-    private String modelVersion;
-    private List<RealmRepresentation> realms;
-
-    public String getModelVersion() {
-        return modelVersion;
-    }
-
-    public void setModelVersion(String modelVersion) {
-        this.modelVersion = modelVersion;
-    }
-
-    public List<RealmRepresentation> getRealms() {
-        return realms;
-    }
-
-    public void setRealms(List<RealmRepresentation> realms) {
-        this.realms = realms;
-    }
-}
+package org.keycloak.connections.file;
+
+import org.keycloak.representations.idm.RealmRepresentation;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Model {
+    private String modelVersion;
+    private List<RealmRepresentation> realms;
+
+    public String getModelVersion() {
+        return modelVersion;
+    }
+
+    public void setModelVersion(String modelVersion) {
+        this.modelVersion = modelVersion;
+    }
+
+    public List<RealmRepresentation> getRealms() {
+        return realms;
+    }
+
+    public void setRealms(List<RealmRepresentation> realms) {
+        this.realms = realms;
+    }
+}
diff --git a/connections/http-client/pom.xml b/connections/http-client/pom.xml
index d580be5..6136d46 100755
--- a/connections/http-client/pom.xml
+++ b/connections/http-client/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-http-client</artifactId>
-    <name>Keycloak Connections Apache HttpClient</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-http-client</artifactId>
+    <name>Keycloak Connections Apache HttpClient</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java
index 7459f4d..0668382 100755
--- a/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java
+++ b/connections/http-client/src/main/java/org/keycloak/connections/httpclient/HttpClientBuilder.java
@@ -1,281 +1,281 @@
-package org.keycloak.connections.httpclient;
-
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLContexts;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import java.io.IOException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Abstraction for creating HttpClients. Allows SSL configuration.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HttpClientBuilder {
-    public static enum HostnameVerificationPolicy {
-        /**
-         * Hostname verification is not done on the server's certificate
-         */
-        ANY,
-        /**
-         * Allows wildcards in subdomain names i.e. *.foo.com
-         */
-        WILDCARD,
-        /**
-         * CN must match hostname connecting to
-         */
-        STRICT
-    }
-
-
-    /**
-     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-     * @version $Revision: 1 $
-     */
-    private static class PassthroughTrustManager implements X509TrustManager {
-        public void checkClientTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
-    }
-
-    protected KeyStore truststore;
-    protected KeyStore clientKeyStore;
-    protected String clientPrivateKeyPassword;
-    protected boolean disableTrustManager;
-    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
-    protected SSLContext sslContext;
-    protected int connectionPoolSize = 100;
-    protected int maxPooledPerRoute = 0;
-    protected long connectionTTL = -1;
-    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
-    protected HostnameVerifier verifier = null;
-    protected long socketTimeout = -1;
-    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
-    protected long establishConnectionTimeout = -1;
-    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
-    protected boolean disableCookies = false;
-
-
-    /**
-     * Socket inactivity timeout
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
-    {
-        this.socketTimeout = timeout;
-        this.socketTimeoutUnits = unit;
-        return this;
-    }
-
-    /**
-     * When trying to make an initial socket connection, what is the timeout?
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
-    {
-        this.establishConnectionTimeout = timeout;
-        this.establishConnectionTimeoutUnits = unit;
-        return this;
-    }
-
-    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
-        this.connectionTTL = ttl;
-        this.connectionTTLUnit = unit;
-        return this;
-    }
-
-    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
-        this.maxPooledPerRoute = maxPooledPerRoute;
-        return this;
-    }
-
-    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
-        this.connectionPoolSize = connectionPoolSize;
-        return this;
-    }
-
-    /**
-     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
-     * hole, so only set this option if you cannot or do not want to verify the identity of the
-     * host you are communicating with.
-     */
-    public HttpClientBuilder disableTrustManager() {
-        this.disableTrustManager = true;
-        return this;
-    }
-
-    /**
-     * Disable cookie management.
-     */
-    public HttpClientBuilder disableCookies(boolean disable) {
-        this.disableTrustManager = disable;
-        return this;
-    }
-
-    /**
-     * SSL policy used to verify hostnames
-     *
-     * @param policy
-     * @return
-     */
-    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
-        this.policy = policy;
-        return this;
-    }
-
-
-    public HttpClientBuilder sslContext(SSLContext sslContext) {
-        this.sslContext = sslContext;
-        return this;
-    }
-
-    public HttpClientBuilder trustStore(KeyStore truststore) {
-        this.truststore = truststore;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = password;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = new String(password);
-        return this;
-    }
-
-
-    static class VerifierWrapper implements X509HostnameVerifier {
-        protected HostnameVerifier verifier;
-
-        VerifierWrapper(HostnameVerifier verifier) {
-            this.verifier = verifier;
-        }
-
-        @Override
-        public void verify(String host, SSLSocket ssl) throws IOException {
-            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
-        }
-
-        @Override
-        public void verify(String host, X509Certificate cert) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public boolean verify(String s, SSLSession sslSession) {
-            return verifier.verify(s, sslSession);
-        }
-    }
-
-    public CloseableHttpClient build() {
-        X509HostnameVerifier verifier = null;
-        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
-        else {
-            switch (policy) {
-                case ANY:
-                    verifier = new AllowAllHostnameVerifier();
-                    break;
-                case WILDCARD:
-                    verifier = new BrowserCompatHostnameVerifier();
-                    break;
-                case STRICT:
-                    verifier = new StrictHostnameVerifier();
-                    break;
-            }
-        }
-        try {
-            SSLConnectionSocketFactory sslsf = null;
-            SSLContext theContext = sslContext;
-            if (disableTrustManager) {
-                theContext = SSLContext.getInstance("TLS");
-                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
-                        new SecureRandom());
-                verifier = new AllowAllHostnameVerifier();
-                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
-            } else if (theContext != null) {
-                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
-            } else if (clientKeyStore != null || truststore != null) {
-                theContext = createSslContext("TLS", clientKeyStore, clientPrivateKeyPassword, truststore, null);
-                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
-            } else {
-                final SSLContext tlsContext = SSLContext.getInstance("TLS");
-                tlsContext.init(null, null, null);
-                sslsf = new SSLConnectionSocketFactory(tlsContext, verifier);
-            }
-            RequestConfig requestConfig = RequestConfig.custom()
-                    .setConnectTimeout((int) establishConnectionTimeout)
-                    .setSocketTimeout((int) socketTimeout).build();
-
-            org.apache.http.impl.client.HttpClientBuilder builder = HttpClients.custom()
-                    .setDefaultRequestConfig(requestConfig)
-                    .setSSLSocketFactory(sslsf)
-                    .setMaxConnTotal(connectionPoolSize)
-                    .setMaxConnPerRoute(maxPooledPerRoute);
-            if (disableCookies) builder.disableCookieManagement();
-            return builder.build();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private SSLContext createSslContext(
-            final String algorithm,
-            final KeyStore keystore,
-            final String keyPassword,
-            final KeyStore truststore,
-            final SecureRandom random)
-            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
-        return SSLContexts.custom()
-                        .useProtocol(algorithm)
-                        .setSecureRandom(random)
-                        .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
-                        .loadTrustMaterial(truststore)
-                        .build();
-    }
-
+package org.keycloak.connections.httpclient;
+
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Abstraction for creating HttpClients. Allows SSL configuration.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HttpClientBuilder {
+    public static enum HostnameVerificationPolicy {
+        /**
+         * Hostname verification is not done on the server's certificate
+         */
+        ANY,
+        /**
+         * Allows wildcards in subdomain names i.e. *.foo.com
+         */
+        WILDCARD,
+        /**
+         * CN must match hostname connecting to
+         */
+        STRICT
+    }
+
+
+    /**
+     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+     * @version $Revision: 1 $
+     */
+    private static class PassthroughTrustManager implements X509TrustManager {
+        public void checkClientTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+
+    protected KeyStore truststore;
+    protected KeyStore clientKeyStore;
+    protected String clientPrivateKeyPassword;
+    protected boolean disableTrustManager;
+    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
+    protected SSLContext sslContext;
+    protected int connectionPoolSize = 100;
+    protected int maxPooledPerRoute = 0;
+    protected long connectionTTL = -1;
+    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
+    protected HostnameVerifier verifier = null;
+    protected long socketTimeout = -1;
+    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected long establishConnectionTimeout = -1;
+    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected boolean disableCookies = false;
+
+
+    /**
+     * Socket inactivity timeout
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
+    {
+        this.socketTimeout = timeout;
+        this.socketTimeoutUnits = unit;
+        return this;
+    }
+
+    /**
+     * When trying to make an initial socket connection, what is the timeout?
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
+    {
+        this.establishConnectionTimeout = timeout;
+        this.establishConnectionTimeoutUnits = unit;
+        return this;
+    }
+
+    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
+        this.connectionTTL = ttl;
+        this.connectionTTLUnit = unit;
+        return this;
+    }
+
+    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
+        this.maxPooledPerRoute = maxPooledPerRoute;
+        return this;
+    }
+
+    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+        return this;
+    }
+
+    /**
+     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
+     * hole, so only set this option if you cannot or do not want to verify the identity of the
+     * host you are communicating with.
+     */
+    public HttpClientBuilder disableTrustManager() {
+        this.disableTrustManager = true;
+        return this;
+    }
+
+    /**
+     * Disable cookie management.
+     */
+    public HttpClientBuilder disableCookies(boolean disable) {
+        this.disableTrustManager = disable;
+        return this;
+    }
+
+    /**
+     * SSL policy used to verify hostnames
+     *
+     * @param policy
+     * @return
+     */
+    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
+        this.policy = policy;
+        return this;
+    }
+
+
+    public HttpClientBuilder sslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+        return this;
+    }
+
+    public HttpClientBuilder trustStore(KeyStore truststore) {
+        this.truststore = truststore;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = password;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = new String(password);
+        return this;
+    }
+
+
+    static class VerifierWrapper implements X509HostnameVerifier {
+        protected HostnameVerifier verifier;
+
+        VerifierWrapper(HostnameVerifier verifier) {
+            this.verifier = verifier;
+        }
+
+        @Override
+        public void verify(String host, SSLSocket ssl) throws IOException {
+            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
+        }
+
+        @Override
+        public void verify(String host, X509Certificate cert) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public boolean verify(String s, SSLSession sslSession) {
+            return verifier.verify(s, sslSession);
+        }
+    }
+
+    public CloseableHttpClient build() {
+        X509HostnameVerifier verifier = null;
+        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
+        else {
+            switch (policy) {
+                case ANY:
+                    verifier = new AllowAllHostnameVerifier();
+                    break;
+                case WILDCARD:
+                    verifier = new BrowserCompatHostnameVerifier();
+                    break;
+                case STRICT:
+                    verifier = new StrictHostnameVerifier();
+                    break;
+            }
+        }
+        try {
+            SSLConnectionSocketFactory sslsf = null;
+            SSLContext theContext = sslContext;
+            if (disableTrustManager) {
+                theContext = SSLContext.getInstance("TLS");
+                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
+                        new SecureRandom());
+                verifier = new AllowAllHostnameVerifier();
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else if (theContext != null) {
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else if (clientKeyStore != null || truststore != null) {
+                theContext = createSslContext("TLS", clientKeyStore, clientPrivateKeyPassword, truststore, null);
+                sslsf = new SSLConnectionSocketFactory(theContext, verifier);
+            } else {
+                final SSLContext tlsContext = SSLContext.getInstance("TLS");
+                tlsContext.init(null, null, null);
+                sslsf = new SSLConnectionSocketFactory(tlsContext, verifier);
+            }
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setConnectTimeout((int) establishConnectionTimeout)
+                    .setSocketTimeout((int) socketTimeout).build();
+
+            org.apache.http.impl.client.HttpClientBuilder builder = HttpClients.custom()
+                    .setDefaultRequestConfig(requestConfig)
+                    .setSSLSocketFactory(sslsf)
+                    .setMaxConnTotal(connectionPoolSize)
+                    .setMaxConnPerRoute(maxPooledPerRoute);
+            if (disableCookies) builder.disableCookieManagement();
+            return builder.build();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private SSLContext createSslContext(
+            final String algorithm,
+            final KeyStore keystore,
+            final String keyPassword,
+            final KeyStore truststore,
+            final SecureRandom random)
+            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        return SSLContexts.custom()
+                        .useProtocol(algorithm)
+                        .setSecureRandom(random)
+                        .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
+                        .loadTrustMaterial(truststore)
+                        .build();
+    }
+
 }
\ No newline at end of file
diff --git a/connections/infinispan/pom.xml b/connections/infinispan/pom.xml
index a2b3791..907cc82 100755
--- a/connections/infinispan/pom.xml
+++ b/connections/infinispan/pom.xml
@@ -1,31 +1,31 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-infinispan</artifactId>
-    <name>Keycloak Connections Infinispan</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-infinispan</artifactId>
+    <name>Keycloak Connections Infinispan</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/connections/jpa/pom.xml b/connections/jpa/pom.xml
index 7dd5f3a..a21451e 100755
--- a/connections/jpa/pom.xml
+++ b/connections/jpa/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-jpa</artifactId>
-    <name>Keycloak Connections JPA</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-jpa</artifactId>
+    <name>Keycloak Connections JPA</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaKeycloakTransaction.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaKeycloakTransaction.java
index 4f42fe7..7aa5f05 100755
--- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaKeycloakTransaction.java
+++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaKeycloakTransaction.java
@@ -1,53 +1,53 @@
-package org.keycloak.connections.jpa;
-
-import org.keycloak.models.KeycloakTransaction;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaKeycloakTransaction implements KeycloakTransaction {
-
-    protected EntityManager em;
-
-    public JpaKeycloakTransaction(EntityManager em) {
-        this.em = em;
-    }
-
-    @Override
-    public void begin() {
-        em.getTransaction().begin();
-    }
-
-    @Override
-    public void commit() {
-        try {
-            em.getTransaction().commit();
-        } catch (PersistenceException e) {
-            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
-        }
-    }
-
-    @Override
-    public void rollback() {
-        em.getTransaction().rollback();
-    }
-
-    @Override
-    public void setRollbackOnly() {
-        em.getTransaction().setRollbackOnly();
-    }
-
-    @Override
-    public boolean getRollbackOnly() {
-        return  em.getTransaction().getRollbackOnly();
-    }
-
-    @Override
-    public boolean isActive() {
-        return em.getTransaction().isActive();
-    }
-}
+package org.keycloak.connections.jpa;
+
+import org.keycloak.models.KeycloakTransaction;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaKeycloakTransaction implements KeycloakTransaction {
+
+    protected EntityManager em;
+
+    public JpaKeycloakTransaction(EntityManager em) {
+        this.em = em;
+    }
+
+    @Override
+    public void begin() {
+        em.getTransaction().begin();
+    }
+
+    @Override
+    public void commit() {
+        try {
+            em.getTransaction().commit();
+        } catch (PersistenceException e) {
+            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
+        }
+    }
+
+    @Override
+    public void rollback() {
+        em.getTransaction().rollback();
+    }
+
+    @Override
+    public void setRollbackOnly() {
+        em.getTransaction().setRollbackOnly();
+    }
+
+    @Override
+    public boolean getRollbackOnly() {
+        return  em.getTransaction().getRollbackOnly();
+    }
+
+    @Override
+    public boolean isActive() {
+        return em.getTransaction().isActive();
+    }
+}
diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index 3fac88c..7b7a893 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -1,54 +1,54 @@
-<persistence xmlns="http://java.sun.com/xml/ns/persistence"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
-    version="1.0">
-    <persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
-        <class>org.keycloak.models.jpa.entities.ClientEntity</class>
-        <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmEntity</class>
-        <class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
-        <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserFederationProviderEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserFederationMapperEntity</class>
-        <class>org.keycloak.models.jpa.entities.RoleEntity</class>
-        <class>org.keycloak.models.jpa.entities.FederatedIdentityEntity</class>
-        <class>org.keycloak.models.jpa.entities.MigrationModelEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserAttributeEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class>
-        <class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
-        <class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
-        <class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
-        <class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
-        <class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
-        <class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
-        <class>org.keycloak.models.jpa.entities.AuthenticatorConfigEntity</class>
-        <class>org.keycloak.models.jpa.entities.RequiredActionProviderEntity</class>
-
-        <!-- JpaUserSessionProvider -->
-        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionAuthStatusEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.ClientUserSessionNoteEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
-        <class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
-
-        <!-- JpaAuditProviders -->
-        <class>org.keycloak.events.jpa.EventEntity</class>
-        <class>org.keycloak.events.jpa.AdminEventEntity</class>
-        
-        <exclude-unlisted-classes>true</exclude-unlisted-classes>
-
-        <properties>
-            <property name="jboss.as.jpa.managed" value="false"/>
-        </properties>
-    </persistence-unit>
-</persistence>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+    version="1.0">
+    <persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
+        <class>org.keycloak.models.jpa.entities.ClientEntity</class>
+        <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
+        <class>org.keycloak.models.jpa.entities.RealmEntity</class>
+        <class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
+        <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserFederationProviderEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserFederationMapperEntity</class>
+        <class>org.keycloak.models.jpa.entities.RoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.FederatedIdentityEntity</class>
+        <class>org.keycloak.models.jpa.entities.MigrationModelEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserAttributeEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class>
+        <class>org.keycloak.models.jpa.entities.IdentityProviderMapperEntity</class>
+        <class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
+        <class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
+        <class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
+        <class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
+        <class>org.keycloak.models.jpa.entities.AuthenticatorConfigEntity</class>
+        <class>org.keycloak.models.jpa.entities.RequiredActionProviderEntity</class>
+
+        <!-- JpaUserSessionProvider -->
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionAuthStatusEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientUserSessionNoteEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
+
+        <!-- JpaAuditProviders -->
+        <class>org.keycloak.events.jpa.EventEntity</class>
+        <class>org.keycloak.events.jpa.AdminEventEntity</class>
+        
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+
+        <properties>
+            <property name="jboss.as.jpa.managed" value="false"/>
+        </properties>
+    </persistence-unit>
+</persistence>
diff --git a/connections/jpa-liquibase/pom.xml b/connections/jpa-liquibase/pom.xml
index 01a090b..dadf9ef 100755
--- a/connections/jpa-liquibase/pom.xml
+++ b/connections/jpa-liquibase/pom.xml
@@ -1,76 +1,76 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-jpa-liquibase</artifactId>
-    <name>Keycloak Connections JPA Liquibase Updater</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.liquibase</groupId>
-            <artifactId>liquibase-core</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.yaml</groupId>
-                    <artifactId>snakeyaml</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.liquibase</groupId>
-                <artifactId>liquibase-maven-plugin</artifactId>
-                <configuration>
-                    <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                    <url>${project.url}</url>
-                    <driver>${driver}</driver>
-                    <username>${username}</username>
-                    <password>${password}</password>
-
-                    <referenceUrl>${referenceUrl}</referenceUrl>
-                    <referenceDriver>${driver}</referenceDriver>
-                    <referenceUsername>${username}</referenceUsername>
-                    <referencePassword>${password}</referencePassword>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <properties>
-        <username>sa</username>
-        <password></password>
-        <driver>org.h2.Driver</driver>
-    </properties>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-jpa-liquibase</artifactId>
+    <name>Keycloak Connections JPA Liquibase Updater</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.liquibase</groupId>
+            <artifactId>liquibase-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.yaml</groupId>
+                    <artifactId>snakeyaml</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.liquibase</groupId>
+                <artifactId>liquibase-maven-plugin</artifactId>
+                <configuration>
+                    <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                    <url>${project.url}</url>
+                    <driver>${driver}</driver>
+                    <username>${username}</username>
+                    <password>${password}</password>
+
+                    <referenceUrl>${referenceUrl}</referenceUrl>
+                    <referenceDriver>${driver}</referenceDriver>
+                    <referenceUsername>${username}</referenceUsername>
+                    <referencePassword>${password}</referencePassword>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <username>sa</username>
+        <password></password>
+        <driver>org.h2.Driver</driver>
+    </properties>
+</project>
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
index 1ca78d5..cad6241 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
@@ -1,139 +1,139 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
-    <changeSet author="bburke@redhat.com" id="1.4.0">
-        <delete tableName="CLIENT_SESSION_AUTH_STATUS"/>
-        <delete tableName="CLIENT_SESSION_ROLE"/>
-        <delete tableName="CLIENT_SESSION_PROT_MAPPER"/>
-        <delete tableName="CLIENT_SESSION_NOTE"/>
-        <delete tableName="CLIENT_SESSION"/>
-        <delete tableName="USER_SESSION_NOTE"/>
-        <delete tableName="USER_SESSION"/>
-        <addColumn tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" type="VARCHAR(36)">
-                <constraints nullable="true"/>
-            </column>
-        </addColumn>
-        <addColumn tableName="AUTHENTICATION_FLOW">
-            <column name="PROVIDER_ID" type="VARCHAR(36)" defaultValue="basic-flow">
-                <constraints nullable="false"/>
-            </column>
-            <column name="TOP_LEVEL" type="BOOLEAN" defaultValueBoolean="false">
-                <constraints nullable="false"/>
-            </column>
-            <column name="BUILT_IN" type="BOOLEAN" defaultValueBoolean="false">
-                <constraints nullable="false"/>
-            </column>
-        </addColumn>
-        <addColumn tableName="AUTHENTICATION_EXECUTION">
-            <column name="AUTH_FLOW_ID" type="VARCHAR(36)">
-                <constraints nullable="true"/>
-            </column>
-            <column name="AUTH_CONFIG" type="VARCHAR(36)">
-                <constraints nullable="true"/>
-            </column>
-        </addColumn>
-        <addColumn tableName="USER_ATTRIBUTE">
-            <column name="ID" type="VARCHAR(36)">
-                <constraints nullable="false"/>
-            </column>
-        </addColumn>
-
-        <dropColumn tableName="AUTHENTICATOR"  columnName="PROVIDER_ID"/>
-        <renameTable oldTableName="AUTHENTICATOR_CONFIG" newTableName="AUTHENTICATOR_CONFIG_ENTRY"/>
-        <renameTable oldTableName="AUTHENTICATOR" newTableName="AUTHENTICATOR_CONFIG"/>
-        <!-- OAUTH_GRANT,
-        CODE_TO_TOKEN,
-        VERIFY_EMAIL,
-        UPDATE_PROFILE,
-        CONFIGURE_TOTP,
-        UPDATE_PASSWORD,
-        RECOVER_PASSWORD,
-        AUTHENTICATE,
-        SOCIAL_CALLBACK,
-        LOGGED_OUT -->
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="OAUTH_GRANT"/>
-            <where>ACTION = 0</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="CODE_TO_TOKEN"/>
-            <where>ACTION = 1</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="VERIFY_EMAIL"/>
-            <where>ACTION = 2</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="UPDATE_PROFILE"/>
-            <where>ACTION = 3</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="CONFIGURE_TOTP"/>
-            <where>ACTION = 4</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="UPDATE_PASSWORD"/>
-            <where>ACTION = 5</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="RECOVER_PASSWORD"/>
-            <where>ACTION = 6</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="AUTHENTICATE"/>
-            <where>ACTION = 7</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="SOCIAL_CALLBACK"/>
-            <where>ACTION = 8</where>
-        </update>
-        <update tableName="CLIENT_SESSION">
-            <column name="CURRENT_ACTION" value="LOGGED_OUT"/>
-            <where>ACTION = 9</where>
-        </update>
-
-        <createTable tableName="CLIENT_USER_SESSION_NOTE">
-            <column name="NAME" type="VARCHAR(255)">
-                <constraints nullable="false"/>
-            </column>
-            <column name="VALUE" type="VARCHAR(255)"/>
-            <column name="CLIENT_SESSION" type="VARCHAR(36)">
-                <constraints nullable="false"/>
-            </column>
-        </createTable>
-        <createTable tableName="REQUIRED_ACTION_PROVIDER">
-            <column name="ID" type="VARCHAR(36)">
-                <constraints nullable="false"/>
-            </column>
-            <column name="ALIAS" type="VARCHAR(255)"/>
-            <column name="NAME" type="VARCHAR(255)"/>
-            <column name="REALM_ID" type="VARCHAR(36)"/>
-            <column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
-                <constraints nullable="false"/>
-            </column>
-            <column name="DEFAULT_ACTION" type="BOOLEAN" defaultValueBoolean="false">
-                <constraints nullable="false"/>
-            </column>
-            <column name="PROVIDER_ID" type="VARCHAR(255)"/>
-        </createTable>
-        <createTable tableName="REQUIRED_ACTION_CONFIG">
-            <column name="REQUIRED_ACTION_ID" type="VARCHAR(36)">
-                <constraints nullable="false"/>
-            </column>
-            <column name="VALUE" type="CLOB"/>
-            <column name="NAME" type="VARCHAR(255)">
-                <constraints nullable="false"/>
-            </column>
-        </createTable>
-
-        <dropPrimaryKey constraintName="CONSTRAINT_6" tableName="USER_ATTRIBUTE"/>
-        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_USER_ATTRIBUTE_PK" tableName="USER_ATTRIBUTE"/>
-        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_REQ_ACT_PRV_PK" tableName="REQUIRED_ACTION_PROVIDER"/>
-        <addPrimaryKey columnNames="REQUIRED_ACTION_ID, NAME" constraintName="CONSTRAINT_REQ_ACT_CFG_PK" tableName="REQUIRED_ACTION_CONFIG"/>
-        <addPrimaryKey columnNames="CLIENT_SESSION, NAME" constraintName="CONSTR_CL_USR_SES_NOTE" tableName="CLIENT_USER_SESSION_NOTE"/>
-        <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REQUIRED_ACTION_PROVIDER" constraintName="FK_REQ_ACT_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
-        <addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_USER_SESSION_NOTE" constraintName="FK_CL_USR_SES_NOTE" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
-        <dropColumn tableName="CLIENT_SESSION" columnName="ACTION"/>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
+    <changeSet author="bburke@redhat.com" id="1.4.0">
+        <delete tableName="CLIENT_SESSION_AUTH_STATUS"/>
+        <delete tableName="CLIENT_SESSION_ROLE"/>
+        <delete tableName="CLIENT_SESSION_PROT_MAPPER"/>
+        <delete tableName="CLIENT_SESSION_NOTE"/>
+        <delete tableName="CLIENT_SESSION"/>
+        <delete tableName="USER_SESSION_NOTE"/>
+        <delete tableName="USER_SESSION"/>
+        <addColumn tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" type="VARCHAR(36)">
+                <constraints nullable="true"/>
+            </column>
+        </addColumn>
+        <addColumn tableName="AUTHENTICATION_FLOW">
+            <column name="PROVIDER_ID" type="VARCHAR(36)" defaultValue="basic-flow">
+                <constraints nullable="false"/>
+            </column>
+            <column name="TOP_LEVEL" type="BOOLEAN" defaultValueBoolean="false">
+                <constraints nullable="false"/>
+            </column>
+            <column name="BUILT_IN" type="BOOLEAN" defaultValueBoolean="false">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+        <addColumn tableName="AUTHENTICATION_EXECUTION">
+            <column name="AUTH_FLOW_ID" type="VARCHAR(36)">
+                <constraints nullable="true"/>
+            </column>
+            <column name="AUTH_CONFIG" type="VARCHAR(36)">
+                <constraints nullable="true"/>
+            </column>
+        </addColumn>
+        <addColumn tableName="USER_ATTRIBUTE">
+            <column name="ID" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+
+        <dropColumn tableName="AUTHENTICATOR"  columnName="PROVIDER_ID"/>
+        <renameTable oldTableName="AUTHENTICATOR_CONFIG" newTableName="AUTHENTICATOR_CONFIG_ENTRY"/>
+        <renameTable oldTableName="AUTHENTICATOR" newTableName="AUTHENTICATOR_CONFIG"/>
+        <!-- OAUTH_GRANT,
+        CODE_TO_TOKEN,
+        VERIFY_EMAIL,
+        UPDATE_PROFILE,
+        CONFIGURE_TOTP,
+        UPDATE_PASSWORD,
+        RECOVER_PASSWORD,
+        AUTHENTICATE,
+        SOCIAL_CALLBACK,
+        LOGGED_OUT -->
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="OAUTH_GRANT"/>
+            <where>ACTION = 0</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="CODE_TO_TOKEN"/>
+            <where>ACTION = 1</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="VERIFY_EMAIL"/>
+            <where>ACTION = 2</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="UPDATE_PROFILE"/>
+            <where>ACTION = 3</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="CONFIGURE_TOTP"/>
+            <where>ACTION = 4</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="UPDATE_PASSWORD"/>
+            <where>ACTION = 5</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="RECOVER_PASSWORD"/>
+            <where>ACTION = 6</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="AUTHENTICATE"/>
+            <where>ACTION = 7</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="SOCIAL_CALLBACK"/>
+            <where>ACTION = 8</where>
+        </update>
+        <update tableName="CLIENT_SESSION">
+            <column name="CURRENT_ACTION" value="LOGGED_OUT"/>
+            <where>ACTION = 9</where>
+        </update>
+
+        <createTable tableName="CLIENT_USER_SESSION_NOTE">
+            <column name="NAME" type="VARCHAR(255)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="VALUE" type="VARCHAR(255)"/>
+            <column name="CLIENT_SESSION" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+        </createTable>
+        <createTable tableName="REQUIRED_ACTION_PROVIDER">
+            <column name="ID" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="ALIAS" type="VARCHAR(255)"/>
+            <column name="NAME" type="VARCHAR(255)"/>
+            <column name="REALM_ID" type="VARCHAR(36)"/>
+            <column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
+                <constraints nullable="false"/>
+            </column>
+            <column name="DEFAULT_ACTION" type="BOOLEAN" defaultValueBoolean="false">
+                <constraints nullable="false"/>
+            </column>
+            <column name="PROVIDER_ID" type="VARCHAR(255)"/>
+        </createTable>
+        <createTable tableName="REQUIRED_ACTION_CONFIG">
+            <column name="REQUIRED_ACTION_ID" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="VALUE" type="CLOB"/>
+            <column name="NAME" type="VARCHAR(255)">
+                <constraints nullable="false"/>
+            </column>
+        </createTable>
+
+        <dropPrimaryKey constraintName="CONSTRAINT_6" tableName="USER_ATTRIBUTE"/>
+        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_USER_ATTRIBUTE_PK" tableName="USER_ATTRIBUTE"/>
+        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_REQ_ACT_PRV_PK" tableName="REQUIRED_ACTION_PROVIDER"/>
+        <addPrimaryKey columnNames="REQUIRED_ACTION_ID, NAME" constraintName="CONSTRAINT_REQ_ACT_CFG_PK" tableName="REQUIRED_ACTION_CONFIG"/>
+        <addPrimaryKey columnNames="CLIENT_SESSION, NAME" constraintName="CONSTR_CL_USR_SES_NOTE" tableName="CLIENT_USER_SESSION_NOTE"/>
+        <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REQUIRED_ACTION_PROVIDER" constraintName="FK_REQ_ACT_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
+        <addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_USER_SESSION_NOTE" constraintName="FK_CL_USR_SES_NOTE" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
+        <dropColumn tableName="CLIENT_SESSION" columnName="ACTION"/>
         <addColumn tableName="USER_ENTITY">
             <column name="CREATED_TIMESTAMP" type="BIGINT"/>
         </addColumn>
diff --git a/connections/mongo/pom.xml b/connections/mongo/pom.xml
index af87da8..4bb1519 100755
--- a/connections/mongo/pom.xml
+++ b/connections/mongo/pom.xml
@@ -1,35 +1,35 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-mongo</artifactId>
-    <name>Keycloak Connections Mongo</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-mongo</artifactId>
+    <name>Keycloak Connections Mongo</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
index 397c307..eebfcd1 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/MongoStore.java
@@ -1,79 +1,79 @@
-package org.keycloak.connections.mongo.api;
-
-import com.mongodb.DBObject;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public interface MongoStore {
-
-    /**
-     * Insert new entity
-     *
-     * @param entity to insert
-     */
-    void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
-
-    /**
-     * Update existing entity
-     *
-     * @param entity to update
-     */
-    void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
-
-    /**
-     * Bulk  update of more entities of some type
-     *
-     * @param type
-     * @param query
-     * @param update
-     * @param context
-     * @return count of updated entities
-     */
-    <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context);
-
-    <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
-
-    <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
-
-    /**
-     * @param type
-     * @param query
-     * @param context
-     * @return query result or empty list if no results available for the query. Doesn't return null
-     */
-    <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
-
-    /**
-     * @param type
-     * @param query
-     * @param context
-     * @return query result or empty list if no results available for the query. Doesn't return null
-     */
-    <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context);
-
-    <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
-
-    boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
-
-    boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
-
-    /**
-     *
-     * @param type
-     * @param query
-     * @param callback if true, then store will first load all entities, then call "afterRemove" for every entity. If false, the entities are removed directly without load and calling "afterRemove" callback
-     *                 false has better performance (especially if we are going to remove big number of entities)
-     * @param context
-     * @return count of removed entities
-     */
-    int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context);
-
-    <S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
-
-    <S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
-
-}
+package org.keycloak.connections.mongo.api;
+
+import com.mongodb.DBObject;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface MongoStore {
+
+    /**
+     * Insert new entity
+     *
+     * @param entity to insert
+     */
+    void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
+
+    /**
+     * Update existing entity
+     *
+     * @param entity to update
+     */
+    void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
+
+    /**
+     * Bulk  update of more entities of some type
+     *
+     * @param type
+     * @param query
+     * @param update
+     * @param context
+     * @return count of updated entities
+     */
+    <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context);
+
+    <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
+
+    <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+
+    /**
+     * @param type
+     * @param query
+     * @param context
+     * @return query result or empty list if no results available for the query. Doesn't return null
+     */
+    <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+
+    /**
+     * @param type
+     * @param query
+     * @param context
+     * @return query result or empty list if no results available for the query. Doesn't return null
+     */
+    <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context);
+
+    <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+
+    boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
+
+    boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
+
+    /**
+     *
+     * @param type
+     * @param query
+     * @param callback if true, then store will first load all entities, then call "afterRemove" for every entity. If false, the entities are removed directly without load and calling "afterRemove" callback
+     *                 false has better performance (especially if we are going to remove big number of entities)
+     * @param context
+     * @return count of removed entities
+     */
+    int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context);
+
+    <S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
+
+    <S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
+
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java
index affa060..bafda1e 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java
@@ -1,111 +1,111 @@
-package org.keycloak.connections.mongo.api.types;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
- * Application can create instance of MapperRegistry and then register required Mapper objects.
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MapperRegistry {
-
-    // TODO: Thread-safety support (maybe...)
-    // Mappers of Application objects to DB objects
-    private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
-
-    // Mappers of DB objects to Application objects
-    private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
-
-
-    /**
-     * Add mapper for converting application objects to DB objects
-     *
-     * @param mapper
-     */
-    public void addAppObjectMapper(Mapper<?, ?> mapper) {
-        appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
-    }
-
-
-    /**
-     * Add mapper for converting DB objects to application objects
-     *
-     * @param mapper
-     */
-    public void addDBObjectMapper(Mapper<?, ?> mapper) {
-        Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
-        Class<?> appObjectType = mapper.getExpectedReturnType();
-        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
-        if (appObjects == null) {
-            appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
-            dbObjectMappers.put(dbObjectType, appObjects);
-        }
-        appObjects.put(appObjectType, mapper);
-    }
-
-
-    public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
-        Object dbObject = context.getObjectToConvert();
-        Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
-
-        Class<?> dbObjectType = dbObject.getClass();
-        Mapper<Object, S> mapper;
-
-        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
-        if (appObjects == null) {
-            throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
-        } else {
-            if (appObjects.size() == 1) {
-                mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
-            } else {
-                // Try to find converter for requested application type
-                mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
-            }
-        }
-
-        if (mapper == null) {
-            throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
-        }
-
-        return mapper.convertObject(context);
-    }
-
-
-    public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
-        Class<?> appObjectType = applicationObject.getClass();
-        Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
-        if (mapper == null) {
-            throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
-        }
-        if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
-            throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
-                    " but we need type " + expectedDBObjectType);
-        }
-        return mapper.convertObject(new MapperContext<Object, S>(applicationObject, expectedDBObjectType, null));
-    }
-
-    // Try to find converter for given type or all it's supertypes
-    private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
-        Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
-        if (mapper != null) {
-            return mapper;
-        } else {
-            Class<?>[] interfaces = appObjectType.getInterfaces();
-            for (Class<?> interface1 : interfaces) {
-                mapper = getAppConverterForType(interface1, appObjectConverters);
-                if (mapper != null) {
-                    return mapper;
-                }
-            }
-
-            Class<?> superType = appObjectType.getSuperclass();
-            if (superType != null) {
-                return getAppConverterForType(superType, appObjectConverters);
-            } else {
-                return null;
-            }
-        }
-    }
-}
+package org.keycloak.connections.mongo.api.types;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
+ * Application can create instance of MapperRegistry and then register required Mapper objects.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MapperRegistry {
+
+    // TODO: Thread-safety support (maybe...)
+    // Mappers of Application objects to DB objects
+    private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
+
+    // Mappers of DB objects to Application objects
+    private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
+
+
+    /**
+     * Add mapper for converting application objects to DB objects
+     *
+     * @param mapper
+     */
+    public void addAppObjectMapper(Mapper<?, ?> mapper) {
+        appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
+    }
+
+
+    /**
+     * Add mapper for converting DB objects to application objects
+     *
+     * @param mapper
+     */
+    public void addDBObjectMapper(Mapper<?, ?> mapper) {
+        Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
+        Class<?> appObjectType = mapper.getExpectedReturnType();
+        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
+        if (appObjects == null) {
+            appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
+            dbObjectMappers.put(dbObjectType, appObjects);
+        }
+        appObjects.put(appObjectType, mapper);
+    }
+
+
+    public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
+        Object dbObject = context.getObjectToConvert();
+        Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
+
+        Class<?> dbObjectType = dbObject.getClass();
+        Mapper<Object, S> mapper;
+
+        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
+        if (appObjects == null) {
+            throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
+        } else {
+            if (appObjects.size() == 1) {
+                mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
+            } else {
+                // Try to find converter for requested application type
+                mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
+            }
+        }
+
+        if (mapper == null) {
+            throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
+        }
+
+        return mapper.convertObject(context);
+    }
+
+
+    public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
+        Class<?> appObjectType = applicationObject.getClass();
+        Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
+        if (mapper == null) {
+            throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
+        }
+        if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
+            throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
+                    " but we need type " + expectedDBObjectType);
+        }
+        return mapper.convertObject(new MapperContext<Object, S>(applicationObject, expectedDBObjectType, null));
+    }
+
+    // Try to find converter for given type or all it's supertypes
+    private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
+        Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
+        if (mapper != null) {
+            return mapper;
+        } else {
+            Class<?>[] interfaces = appObjectType.getInterfaces();
+            for (Class<?> interface1 : interfaces) {
+                mapper = getAppConverterForType(interface1, appObjectConverters);
+                if (mapper != null) {
+                    return mapper;
+                }
+            }
+
+            Class<?> superType = appObjectType.getSuperclass();
+            if (superType != null) {
+                return getAppConverterForType(superType, appObjectConverters);
+            } else {
+                return null;
+            }
+        }
+    }
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/EntityInfo.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/EntityInfo.java
index 95f32d3..e39957c 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/EntityInfo.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/EntityInfo.java
@@ -1,40 +1,40 @@
-package org.keycloak.connections.mongo.impl;
-
-import org.keycloak.models.utils.reflection.Property;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class EntityInfo {
-
-    private final Class<?> entityClass;
-
-    private final String dbCollectionName;
-
-    private final Map<String, Property<Object>> properties;
-
-    public EntityInfo(Class<?> entityClass, String dbCollectionName, Map<String, Property<Object>> properties) {
-        this.entityClass = entityClass;
-        this.dbCollectionName = dbCollectionName;
-        this.properties = properties;
-    }
-
-    public Class<?> getEntityClass() {
-        return entityClass;
-    }
-
-    public String getDbCollectionName() {
-        return dbCollectionName;
-    }
-
-    public Collection<Property<Object>> getProperties() {
-        return properties.values();
-    }
-
-    public Property<Object> getPropertyByName(String propertyName) {
-        return properties.get(propertyName);
-    }
-}
+package org.keycloak.connections.mongo.impl;
+
+import org.keycloak.models.utils.reflection.Property;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class EntityInfo {
+
+    private final Class<?> entityClass;
+
+    private final String dbCollectionName;
+
+    private final Map<String, Property<Object>> properties;
+
+    public EntityInfo(Class<?> entityClass, String dbCollectionName, Map<String, Property<Object>> properties) {
+        this.entityClass = entityClass;
+        this.dbCollectionName = dbCollectionName;
+        this.properties = properties;
+    }
+
+    public Class<?> getEntityClass() {
+        return entityClass;
+    }
+
+    public String getDbCollectionName() {
+        return dbCollectionName;
+    }
+
+    public Collection<Property<Object>> getProperties() {
+        return properties.values();
+    }
+
+    public Property<Object> getPropertyByName(String propertyName) {
+        return properties.get(propertyName);
+    }
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
index 1696b65..a496c0b 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java
@@ -1,473 +1,473 @@
-package org.keycloak.connections.mongo.impl;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.MongoException;
-import com.mongodb.WriteResult;
-import org.jboss.logging.Logger;
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoEntity;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.MongoStore;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.connections.mongo.api.context.MongoTask;
-import org.keycloak.connections.mongo.api.types.Mapper;
-import org.keycloak.connections.mongo.api.types.MapperContext;
-import org.keycloak.connections.mongo.api.types.MapperRegistry;
-import org.keycloak.connections.mongo.impl.types.BasicDBListMapper;
-import org.keycloak.connections.mongo.impl.types.BasicDBListToSetMapper;
-import org.keycloak.connections.mongo.impl.types.BasicDBObjectMapper;
-import org.keycloak.connections.mongo.impl.types.BasicDBObjectToMapMapper;
-import org.keycloak.connections.mongo.impl.types.EnumToStringMapper;
-import org.keycloak.connections.mongo.impl.types.ListMapper;
-import org.keycloak.connections.mongo.impl.types.MapMapper;
-import org.keycloak.connections.mongo.impl.types.MongoEntityMapper;
-import org.keycloak.connections.mongo.impl.types.SimpleMapper;
-import org.keycloak.connections.mongo.impl.types.StringToEnumMapper;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.reflection.Property;
-import org.keycloak.models.utils.reflection.PropertyQueries;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoStoreImpl implements MongoStore {
-
-    private static final Class<?>[] SIMPLE_TYPES = { String.class, Integer.class, Boolean.class, Long.class, Double.class, Character.class, Date.class, byte[].class };
-
-    private final DB database;
-    private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
-
-    private final MapperRegistry mapperRegistry;
-    private ConcurrentMap<Class<?>, EntityInfo> entityInfoCache =
-            new ConcurrentHashMap<Class<?>, EntityInfo>();
-
-
-    public MongoStoreImpl(DB database, Class<?>[] managedEntityTypes) {
-        this.database = database;
-
-        mapperRegistry = new MapperRegistry();
-
-        for (Class<?> simpleMapperClass : SIMPLE_TYPES) {
-            SimpleMapper mapper = new SimpleMapper(simpleMapperClass);
-            mapperRegistry.addAppObjectMapper(mapper);
-            mapperRegistry.addDBObjectMapper(mapper);
-        }
-
-        // Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list idm will be ArrayList)
-        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
-        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
-        mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
-
-        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, HashSet.class));
-        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, Set.class));
-        mapperRegistry.addDBObjectMapper(new BasicDBListToSetMapper(mapperRegistry));
-
-        mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
-        mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
-        mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
-
-        // Enum converters
-        mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
-        mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
-
-        for (Class<?> type : managedEntityTypes) {
-            getEntityInfo(type);
-            mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
-            mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
-        }
-    }
-
-    protected void dropDatabase() {
-        this.database.dropDatabase();
-        logger.info("Database " + this.database.getName() + " dropped in MongoDB");
-    }
-
-    @Override
-    public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
-        Class<? extends MongoEntity> clazz = entity.getClass();
-
-        // Find annotations for ID, for all the properties and for the name of the collection.
-        EntityInfo entityInfo = getEntityInfo(clazz);
-
-        // Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
-        BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
-
-        DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
-
-        String currentId = entity.getId();
-
-        // Generate random ID if not set already
-        if (currentId == null) {
-            currentId = KeycloakModelUtils.generateId();
-            entity.setId(currentId);
-        }
-
-        // Adding "_id"
-        dbObject.put("_id", currentId);
-
-        try {
-            dbCollection.insert(dbObject);
-        } catch (MongoException e) {
-            throw convertException(e);
-        }
-
-        // Treat object as created in this transaction (It is already submitted to transaction)
-        context.addCreatedEntity(entity);
-    }
-
-    public static ModelException convertException(MongoException e) {
-        if (e instanceof MongoException.DuplicateKey) {
-            return new ModelDuplicateException(e);
-        } else {
-            return new ModelException(e);
-        }
-    }
-
-    @Override
-    public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
-        MongoTask fullUpdateTask = new MongoTask() {
-
-            @Override
-            public void execute() {
-                Class<? extends MongoEntity> clazz = entity.getClass();
-                EntityInfo entityInfo = getEntityInfo(clazz);
-                BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
-                DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
-
-                String currentId = entity.getId();
-
-                if (currentId == null) {
-                    throw new IllegalStateException("Can't update entity without id: " + entity);
-                } else {
-                    BasicDBObject query = new BasicDBObject("_id", currentId);
-                    dbCollection.update(query, dbObject);
-                }
-            }
-
-            @Override
-            public boolean isFullUpdate() {
-                return true;
-            }
-        };
-
-        // update is just added to context and postponed
-        context.addUpdateTask(entity, fullUpdateTask);
-    }
-
-    @Override
-    public <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context) {
-        context.beforeDBBulkUpdateOrRemove(type);
-
-        DBCollection collection = getDBCollectionForType(type);
-        WriteResult wr = collection.update(query, update, false, true);
-
-        logger.debugf("Updated %d collections of type %s", wr.getN(), type);
-        return wr.getN();
-    }
-
-    @Override
-    public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
-        // First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
-        T cached = context.getLoadedEntity(type, id);
-        if (cached != null && type.isAssignableFrom(cached.getClass())) return cached;
-
-        DBCollection dbCollection = getDBCollectionForType(type);
-
-        BasicDBObject idQuery = new BasicDBObject("_id", id);
-        DBObject dbObject = dbCollection.findOne(idQuery);
-
-        if (dbObject == null) return null;
-
-        MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
-        T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
-
-        // Now add it to loaded objects
-        context.addLoadedEntity(converted);
-
-        return converted;
-    }
-
-
-    @Override
-    public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
-        // First we should execute all pending tasks before searching DB
-        context.beforeDBSearch(type);
-
-        DBCollection dbCollection = getDBCollectionForType(type);
-        DBObject dbObject = dbCollection.findOne(query);
-
-        if (dbObject == null) {
-            return null;
-        } else {
-            return convertDBObjectToEntity(type, dbObject, context);
-        }
-    }
-
-
-    @Override
-    public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
-        // First we should execute all pending tasks before searching DB
-        context.beforeDBSearch(type);
-
-        DBCollection dbCollection = getDBCollectionForType(type);
-        DBCursor cursor = dbCollection.find(query);
-
-        return convertCursor(type, cursor, context);
-    }
-
-    @Override
-    public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context) {
-        // First we should execute all pending tasks before searching DB
-        context.beforeDBSearch(type);
-
-        DBCollection dbCollection = getDBCollectionForType(type);
-        DBCursor cursor = dbCollection.find(query);
-        if (firstResult != -1) {
-            cursor.skip(firstResult);
-        }
-        if (maxResults != -1) {
-            cursor.limit(maxResults);
-        }
-        if (sort != null) {
-            cursor.sort(sort);
-        }
-
-        return convertCursor(type, cursor, context);
-    }
-
-    public <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
-        context.beforeDBSearch(type);
-
-        DBCollection dbCollection = getDBCollectionForType(type);
-        Long count = dbCollection.count(query);
-
-        // For now, assume that int is sufficient
-        return count.intValue();
-    }
-
-    @Override
-    public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
-        return removeEntity(entity.getClass(), entity.getId(), context);
-    }
-
-
-    @Override
-    public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
-        MongoIdentifiableEntity found = loadEntity(type, id, context);
-        if (found == null) {
-            return false;
-        } else {
-            DBCollection dbCollection = getDBCollectionForType(type);
-            BasicDBObject dbQuery = new BasicDBObject("_id", id);
-            dbCollection.remove(dbQuery);
-            //logger.debugf("Entity of type: %s , id: %s removed from MongoDB.", type,  id);
-
-            context.addRemovedEntity(found);
-            return true;
-        }
-    }
-
-
-    @Override
-    public int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context) {
-        if (callback) {
-            List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
-            if (foundObjects.size() == 0) {
-                return 0;
-            } else {
-                DBCollection dbCollection = getDBCollectionForType(type);
-                dbCollection.remove(query);
-
-                logger.debugf("Removed %d entities of type: %s, query: %s", foundObjects.size(), type, query);
-
-                for (MongoIdentifiableEntity found : foundObjects) {
-                    context.addRemovedEntity(found);;
-                }
-                return foundObjects.size();
-            }
-        } else {
-
-            context.beforeDBBulkUpdateOrRemove(type);
-
-            DBCollection dbCollection = getDBCollectionForType(type);
-            WriteResult writeResult = dbCollection.remove(query);
-            int removedCount = writeResult.getN();
-
-            logger.debugf("Removed directly %d entities of type: %s, query: %s", removedCount, type, query);
-            return removedCount;
-        }
-    }
-
-    @Override
-    public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
-        final Class<? extends MongoEntity> type = entity.getClass();
-        EntityInfo entityInfo = getEntityInfo(type);
-
-        // Add item to list directly in this object
-        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
-        if (listProperty == null) {
-            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
-        }
-
-        List<S> list = (List<S>)listProperty.getValue(entity);
-        if (list == null) {
-            list = new ArrayList<S>();
-            listProperty.setValue(entity, list);
-        }
-
-        // Skip if item is already in list
-        if (skipIfAlreadyPresent && list.contains(itemToPush)) {
-            return false;
-        }
-
-        // Update java object
-        list.add(itemToPush);
-
-        // Add update of list to pending tasks
-        final List<S> listt = list;
-        context.addUpdateTask(entity, new MongoTask() {
-
-            @Override
-            public void execute() {
-                // Now DB update of new list with usage of $set
-                BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
-
-                BasicDBObject query = new BasicDBObject("_id", entity.getId());
-                BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
-                BasicDBObject setCommand = new BasicDBObject("$set", listObject);
-                getDBCollectionForType(type).update(query, setCommand);
-            }
-
-            @Override
-            public boolean isFullUpdate() {
-                return false;
-            }
-        });
-
-        return true;
-    }
-
-
-    @Override
-    public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
-        final Class<? extends MongoEntity> type = entity.getClass();
-        EntityInfo entityInfo = getEntityInfo(type);
-
-        // Remove item from list directly in this object
-        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
-        if (listProperty == null) {
-            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
-        }
-        List<S> list = (List<S>)listProperty.getValue(entity);
-
-        // If list is null, we skip both object and DB update
-        if (list == null || !list.contains(itemToPull)) {
-            return false;
-        } else {
-
-            // Update java object
-            list.remove(itemToPull);
-
-            // Add update of list to pending tasks
-            context.addUpdateTask(entity, new MongoTask() {
-
-                @Override
-                public void execute() {
-                    // Pull item from DB
-                    Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
-                    BasicDBObject query = new BasicDBObject("_id", entity.getId());
-                    BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
-                    BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
-                    getDBCollectionForType(type).update(query, pullCommand);
-                }
-
-                @Override
-                public boolean isFullUpdate() {
-                    return false;
-                }
-            });
-
-            return true;
-        }
-    }
-
-    // Possibility to add user-defined mappers
-    public void addAppObjectConverter(Mapper<?, ?> mapper) {
-        mapperRegistry.addAppObjectMapper(mapper);
-    }
-
-    public void addDBObjectConverter(Mapper<?, ?> mapper) {
-        mapperRegistry.addDBObjectMapper(mapper);
-    }
-
-    public EntityInfo getEntityInfo(Class<?> entityClass) {
-        EntityInfo entityInfo = entityInfoCache.get(entityClass);
-        if (entityInfo == null) {
-            Map<String, Property<Object>> properties = PropertyQueries.createQuery(entityClass).getWritableResultList();
-
-            MongoCollection classAnnotation = entityClass.getAnnotation(MongoCollection.class);
-
-            String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
-            entityInfo = new EntityInfo(entityClass, dbCollectionName, properties);
-
-            EntityInfo existing = entityInfoCache.putIfAbsent(entityClass, entityInfo);
-            if (existing != null) {
-                entityInfo = existing;
-            }
-        }
-
-        return entityInfo;
-    }
-
-    protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
-        List<T> result = new ArrayList<T>();
-
-        try {
-            for (DBObject dbObject : cursor) {
-                T entity = convertDBObjectToEntity(type, dbObject, context);
-                result.add(entity);
-            }
-        } finally {
-            cursor.close();
-        }
-
-        return result;
-    }
-
-    protected <T extends MongoIdentifiableEntity> T convertDBObjectToEntity(Class<T> type, DBObject dbObject, MongoStoreInvocationContext context) {
-        // First look if we already have loaded object cached. If yes, we will use cached instance
-        String id = dbObject.get("_id").toString();
-        T object = context.getLoadedEntity(type, id);
-
-        if (object == null) {
-            // So convert and use fresh instance from DB
-            MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
-            object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
-            context.addLoadedEntity(object);
-        }
-        return object;
-    }
-
-    protected DBCollection getDBCollectionForType(Class<?> type) {
-        EntityInfo entityInfo = getEntityInfo(type);
-        String dbCollectionName = entityInfo.getDbCollectionName();
-        return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
-    }
-}
+package org.keycloak.connections.mongo.impl;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import com.mongodb.MongoException;
+import com.mongodb.WriteResult;
+import org.jboss.logging.Logger;
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoEntity;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.MongoStore;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.connections.mongo.api.context.MongoTask;
+import org.keycloak.connections.mongo.api.types.Mapper;
+import org.keycloak.connections.mongo.api.types.MapperContext;
+import org.keycloak.connections.mongo.api.types.MapperRegistry;
+import org.keycloak.connections.mongo.impl.types.BasicDBListMapper;
+import org.keycloak.connections.mongo.impl.types.BasicDBListToSetMapper;
+import org.keycloak.connections.mongo.impl.types.BasicDBObjectMapper;
+import org.keycloak.connections.mongo.impl.types.BasicDBObjectToMapMapper;
+import org.keycloak.connections.mongo.impl.types.EnumToStringMapper;
+import org.keycloak.connections.mongo.impl.types.ListMapper;
+import org.keycloak.connections.mongo.impl.types.MapMapper;
+import org.keycloak.connections.mongo.impl.types.MongoEntityMapper;
+import org.keycloak.connections.mongo.impl.types.SimpleMapper;
+import org.keycloak.connections.mongo.impl.types.StringToEnumMapper;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.reflection.Property;
+import org.keycloak.models.utils.reflection.PropertyQueries;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoStoreImpl implements MongoStore {
+
+    private static final Class<?>[] SIMPLE_TYPES = { String.class, Integer.class, Boolean.class, Long.class, Double.class, Character.class, Date.class, byte[].class };
+
+    private final DB database;
+    private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
+
+    private final MapperRegistry mapperRegistry;
+    private ConcurrentMap<Class<?>, EntityInfo> entityInfoCache =
+            new ConcurrentHashMap<Class<?>, EntityInfo>();
+
+
+    public MongoStoreImpl(DB database, Class<?>[] managedEntityTypes) {
+        this.database = database;
+
+        mapperRegistry = new MapperRegistry();
+
+        for (Class<?> simpleMapperClass : SIMPLE_TYPES) {
+            SimpleMapper mapper = new SimpleMapper(simpleMapperClass);
+            mapperRegistry.addAppObjectMapper(mapper);
+            mapperRegistry.addDBObjectMapper(mapper);
+        }
+
+        // Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list idm will be ArrayList)
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
+        mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
+
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, HashSet.class));
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, Set.class));
+        mapperRegistry.addDBObjectMapper(new BasicDBListToSetMapper(mapperRegistry));
+
+        mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
+        mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
+        mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
+
+        // Enum converters
+        mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
+        mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
+
+        for (Class<?> type : managedEntityTypes) {
+            getEntityInfo(type);
+            mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
+            mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
+        }
+    }
+
+    protected void dropDatabase() {
+        this.database.dropDatabase();
+        logger.info("Database " + this.database.getName() + " dropped in MongoDB");
+    }
+
+    @Override
+    public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
+        Class<? extends MongoEntity> clazz = entity.getClass();
+
+        // Find annotations for ID, for all the properties and for the name of the collection.
+        EntityInfo entityInfo = getEntityInfo(clazz);
+
+        // Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
+        BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
+
+        DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
+
+        String currentId = entity.getId();
+
+        // Generate random ID if not set already
+        if (currentId == null) {
+            currentId = KeycloakModelUtils.generateId();
+            entity.setId(currentId);
+        }
+
+        // Adding "_id"
+        dbObject.put("_id", currentId);
+
+        try {
+            dbCollection.insert(dbObject);
+        } catch (MongoException e) {
+            throw convertException(e);
+        }
+
+        // Treat object as created in this transaction (It is already submitted to transaction)
+        context.addCreatedEntity(entity);
+    }
+
+    public static ModelException convertException(MongoException e) {
+        if (e instanceof MongoException.DuplicateKey) {
+            return new ModelDuplicateException(e);
+        } else {
+            return new ModelException(e);
+        }
+    }
+
+    @Override
+    public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
+        MongoTask fullUpdateTask = new MongoTask() {
+
+            @Override
+            public void execute() {
+                Class<? extends MongoEntity> clazz = entity.getClass();
+                EntityInfo entityInfo = getEntityInfo(clazz);
+                BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
+                DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
+
+                String currentId = entity.getId();
+
+                if (currentId == null) {
+                    throw new IllegalStateException("Can't update entity without id: " + entity);
+                } else {
+                    BasicDBObject query = new BasicDBObject("_id", currentId);
+                    dbCollection.update(query, dbObject);
+                }
+            }
+
+            @Override
+            public boolean isFullUpdate() {
+                return true;
+            }
+        };
+
+        // update is just added to context and postponed
+        context.addUpdateTask(entity, fullUpdateTask);
+    }
+
+    @Override
+    public <T extends MongoIdentifiableEntity> int updateEntities(Class<T> type, DBObject query, DBObject update, MongoStoreInvocationContext context) {
+        context.beforeDBBulkUpdateOrRemove(type);
+
+        DBCollection collection = getDBCollectionForType(type);
+        WriteResult wr = collection.update(query, update, false, true);
+
+        logger.debugf("Updated %d collections of type %s", wr.getN(), type);
+        return wr.getN();
+    }
+
+    @Override
+    public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
+        // First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
+        T cached = context.getLoadedEntity(type, id);
+        if (cached != null && type.isAssignableFrom(cached.getClass())) return cached;
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+
+        BasicDBObject idQuery = new BasicDBObject("_id", id);
+        DBObject dbObject = dbCollection.findOne(idQuery);
+
+        if (dbObject == null) return null;
+
+        MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
+        T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
+
+        // Now add it to loaded objects
+        context.addLoadedEntity(converted);
+
+        return converted;
+    }
+
+
+    @Override
+    public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
+        // First we should execute all pending tasks before searching DB
+        context.beforeDBSearch(type);
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+        DBObject dbObject = dbCollection.findOne(query);
+
+        if (dbObject == null) {
+            return null;
+        } else {
+            return convertDBObjectToEntity(type, dbObject, context);
+        }
+    }
+
+
+    @Override
+    public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
+        // First we should execute all pending tasks before searching DB
+        context.beforeDBSearch(type);
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+        DBCursor cursor = dbCollection.find(query);
+
+        return convertCursor(type, cursor, context);
+    }
+
+    @Override
+    public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context) {
+        // First we should execute all pending tasks before searching DB
+        context.beforeDBSearch(type);
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+        DBCursor cursor = dbCollection.find(query);
+        if (firstResult != -1) {
+            cursor.skip(firstResult);
+        }
+        if (maxResults != -1) {
+            cursor.limit(maxResults);
+        }
+        if (sort != null) {
+            cursor.sort(sort);
+        }
+
+        return convertCursor(type, cursor, context);
+    }
+
+    public <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
+        context.beforeDBSearch(type);
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+        Long count = dbCollection.count(query);
+
+        // For now, assume that int is sufficient
+        return count.intValue();
+    }
+
+    @Override
+    public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
+        return removeEntity(entity.getClass(), entity.getId(), context);
+    }
+
+
+    @Override
+    public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
+        MongoIdentifiableEntity found = loadEntity(type, id, context);
+        if (found == null) {
+            return false;
+        } else {
+            DBCollection dbCollection = getDBCollectionForType(type);
+            BasicDBObject dbQuery = new BasicDBObject("_id", id);
+            dbCollection.remove(dbQuery);
+            //logger.debugf("Entity of type: %s , id: %s removed from MongoDB.", type,  id);
+
+            context.addRemovedEntity(found);
+            return true;
+        }
+    }
+
+
+    @Override
+    public int removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, boolean callback, MongoStoreInvocationContext context) {
+        if (callback) {
+            List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
+            if (foundObjects.size() == 0) {
+                return 0;
+            } else {
+                DBCollection dbCollection = getDBCollectionForType(type);
+                dbCollection.remove(query);
+
+                logger.debugf("Removed %d entities of type: %s, query: %s", foundObjects.size(), type, query);
+
+                for (MongoIdentifiableEntity found : foundObjects) {
+                    context.addRemovedEntity(found);;
+                }
+                return foundObjects.size();
+            }
+        } else {
+
+            context.beforeDBBulkUpdateOrRemove(type);
+
+            DBCollection dbCollection = getDBCollectionForType(type);
+            WriteResult writeResult = dbCollection.remove(query);
+            int removedCount = writeResult.getN();
+
+            logger.debugf("Removed directly %d entities of type: %s, query: %s", removedCount, type, query);
+            return removedCount;
+        }
+    }
+
+    @Override
+    public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
+        final Class<? extends MongoEntity> type = entity.getClass();
+        EntityInfo entityInfo = getEntityInfo(type);
+
+        // Add item to list directly in this object
+        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
+        if (listProperty == null) {
+            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
+        }
+
+        List<S> list = (List<S>)listProperty.getValue(entity);
+        if (list == null) {
+            list = new ArrayList<S>();
+            listProperty.setValue(entity, list);
+        }
+
+        // Skip if item is already in list
+        if (skipIfAlreadyPresent && list.contains(itemToPush)) {
+            return false;
+        }
+
+        // Update java object
+        list.add(itemToPush);
+
+        // Add update of list to pending tasks
+        final List<S> listt = list;
+        context.addUpdateTask(entity, new MongoTask() {
+
+            @Override
+            public void execute() {
+                // Now DB update of new list with usage of $set
+                BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
+
+                BasicDBObject query = new BasicDBObject("_id", entity.getId());
+                BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
+                BasicDBObject setCommand = new BasicDBObject("$set", listObject);
+                getDBCollectionForType(type).update(query, setCommand);
+            }
+
+            @Override
+            public boolean isFullUpdate() {
+                return false;
+            }
+        });
+
+        return true;
+    }
+
+
+    @Override
+    public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
+        final Class<? extends MongoEntity> type = entity.getClass();
+        EntityInfo entityInfo = getEntityInfo(type);
+
+        // Remove item from list directly in this object
+        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
+        if (listProperty == null) {
+            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
+        }
+        List<S> list = (List<S>)listProperty.getValue(entity);
+
+        // If list is null, we skip both object and DB update
+        if (list == null || !list.contains(itemToPull)) {
+            return false;
+        } else {
+
+            // Update java object
+            list.remove(itemToPull);
+
+            // Add update of list to pending tasks
+            context.addUpdateTask(entity, new MongoTask() {
+
+                @Override
+                public void execute() {
+                    // Pull item from DB
+                    Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
+                    BasicDBObject query = new BasicDBObject("_id", entity.getId());
+                    BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
+                    BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
+                    getDBCollectionForType(type).update(query, pullCommand);
+                }
+
+                @Override
+                public boolean isFullUpdate() {
+                    return false;
+                }
+            });
+
+            return true;
+        }
+    }
+
+    // Possibility to add user-defined mappers
+    public void addAppObjectConverter(Mapper<?, ?> mapper) {
+        mapperRegistry.addAppObjectMapper(mapper);
+    }
+
+    public void addDBObjectConverter(Mapper<?, ?> mapper) {
+        mapperRegistry.addDBObjectMapper(mapper);
+    }
+
+    public EntityInfo getEntityInfo(Class<?> entityClass) {
+        EntityInfo entityInfo = entityInfoCache.get(entityClass);
+        if (entityInfo == null) {
+            Map<String, Property<Object>> properties = PropertyQueries.createQuery(entityClass).getWritableResultList();
+
+            MongoCollection classAnnotation = entityClass.getAnnotation(MongoCollection.class);
+
+            String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
+            entityInfo = new EntityInfo(entityClass, dbCollectionName, properties);
+
+            EntityInfo existing = entityInfoCache.putIfAbsent(entityClass, entityInfo);
+            if (existing != null) {
+                entityInfo = existing;
+            }
+        }
+
+        return entityInfo;
+    }
+
+    protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
+        List<T> result = new ArrayList<T>();
+
+        try {
+            for (DBObject dbObject : cursor) {
+                T entity = convertDBObjectToEntity(type, dbObject, context);
+                result.add(entity);
+            }
+        } finally {
+            cursor.close();
+        }
+
+        return result;
+    }
+
+    protected <T extends MongoIdentifiableEntity> T convertDBObjectToEntity(Class<T> type, DBObject dbObject, MongoStoreInvocationContext context) {
+        // First look if we already have loaded object cached. If yes, we will use cached instance
+        String id = dbObject.get("_id").toString();
+        T object = context.getLoadedEntity(type, id);
+
+        if (object == null) {
+            // So convert and use fresh instance from DB
+            MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
+            object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
+            context.addLoadedEntity(object);
+        }
+        return object;
+    }
+
+    protected DBCollection getDBCollectionForType(Class<?> type) {
+        EntityInfo entityInfo = getEntityInfo(type);
+        String dbCollectionName = entityInfo.getDbCollectionName();
+        return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
+    }
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBListMapper.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBListMapper.java
index d435e1e..5406c2f 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBListMapper.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBListMapper.java
@@ -1,45 +1,45 @@
-package org.keycloak.connections.mongo.impl.types;
-
-import com.mongodb.BasicDBList;
-import org.keycloak.connections.mongo.api.types.Mapper;
-import org.keycloak.connections.mongo.api.types.MapperContext;
-import org.keycloak.connections.mongo.api.types.MapperRegistry;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class BasicDBListMapper implements Mapper<BasicDBList, List> {
-
-    private final MapperRegistry mapperRegistry;
-
-    public BasicDBListMapper(MapperRegistry mapperRegistry) {
-        this.mapperRegistry = mapperRegistry;
-    }
-
-    @Override
-    public List convertObject(MapperContext<BasicDBList, List> context) {
-        BasicDBList dbList = context.getObjectToConvert();
-        ArrayList<Object> appObjects = new ArrayList<Object>();
-        Class<?> expectedListElementType = (Class<?>) context.getGenericTypes().get(0);
-
-        for (Object dbObject : dbList) {
-            MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
-            appObjects.add(mapperRegistry.convertDBObjectToApplicationObject(newContext));
-        }
-        return appObjects;
-    }
-
-    @Override
-    public Class<? extends BasicDBList> getTypeOfObjectToConvert() {
-        return BasicDBList.class;
-    }
-
-    @Override
-    public Class<List> getExpectedReturnType() {
-        return List.class;
-    }
-}
+package org.keycloak.connections.mongo.impl.types;
+
+import com.mongodb.BasicDBList;
+import org.keycloak.connections.mongo.api.types.Mapper;
+import org.keycloak.connections.mongo.api.types.MapperContext;
+import org.keycloak.connections.mongo.api.types.MapperRegistry;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class BasicDBListMapper implements Mapper<BasicDBList, List> {
+
+    private final MapperRegistry mapperRegistry;
+
+    public BasicDBListMapper(MapperRegistry mapperRegistry) {
+        this.mapperRegistry = mapperRegistry;
+    }
+
+    @Override
+    public List convertObject(MapperContext<BasicDBList, List> context) {
+        BasicDBList dbList = context.getObjectToConvert();
+        ArrayList<Object> appObjects = new ArrayList<Object>();
+        Class<?> expectedListElementType = (Class<?>) context.getGenericTypes().get(0);
+
+        for (Object dbObject : dbList) {
+            MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
+            appObjects.add(mapperRegistry.convertDBObjectToApplicationObject(newContext));
+        }
+        return appObjects;
+    }
+
+    @Override
+    public Class<? extends BasicDBList> getTypeOfObjectToConvert() {
+        return BasicDBList.class;
+    }
+
+    @Override
+    public Class<List> getExpectedReturnType() {
+        return List.class;
+    }
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/ListMapper.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/ListMapper.java
index dc649d6..54bc8ee 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/ListMapper.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/ListMapper.java
@@ -1,45 +1,45 @@
-package org.keycloak.connections.mongo.impl.types;
-
-import com.mongodb.BasicDBList;
-import org.keycloak.connections.mongo.api.types.Mapper;
-import org.keycloak.connections.mongo.api.types.MapperContext;
-import org.keycloak.connections.mongo.api.types.MapperRegistry;
-
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ListMapper<T extends Collection> implements Mapper<T, BasicDBList> {
-
-    private final MapperRegistry mapperRegistry;
-    private final Class<T> listType;
-
-    public ListMapper(MapperRegistry mapperRegistry, Class<T> listType) {
-        this.mapperRegistry = mapperRegistry;
-        this.listType = listType;
-    }
-
-    @Override
-    public BasicDBList convertObject(MapperContext<T, BasicDBList> context) {
-        T appObjectsList = context.getObjectToConvert();
-
-        BasicDBList dbObjects = new BasicDBList();
-        for (Object appObject : appObjectsList) {
-            Object dbObject = mapperRegistry.convertApplicationObjectToDBObject(appObject, Object.class);
-
-            dbObjects.add(dbObject);
-        }
-        return dbObjects;
-    }
-
-    @Override
-    public Class<? extends T> getTypeOfObjectToConvert() {
-        return listType;
-    }
-
-    @Override
-    public Class<BasicDBList> getExpectedReturnType() {
-        return BasicDBList.class;
-    }
-}
+package org.keycloak.connections.mongo.impl.types;
+
+import com.mongodb.BasicDBList;
+import org.keycloak.connections.mongo.api.types.Mapper;
+import org.keycloak.connections.mongo.api.types.MapperContext;
+import org.keycloak.connections.mongo.api.types.MapperRegistry;
+
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ListMapper<T extends Collection> implements Mapper<T, BasicDBList> {
+
+    private final MapperRegistry mapperRegistry;
+    private final Class<T> listType;
+
+    public ListMapper(MapperRegistry mapperRegistry, Class<T> listType) {
+        this.mapperRegistry = mapperRegistry;
+        this.listType = listType;
+    }
+
+    @Override
+    public BasicDBList convertObject(MapperContext<T, BasicDBList> context) {
+        T appObjectsList = context.getObjectToConvert();
+
+        BasicDBList dbObjects = new BasicDBList();
+        for (Object appObject : appObjectsList) {
+            Object dbObject = mapperRegistry.convertApplicationObjectToDBObject(appObject, Object.class);
+
+            dbObjects.add(dbObject);
+        }
+        return dbObjects;
+    }
+
+    @Override
+    public Class<? extends T> getTypeOfObjectToConvert() {
+        return listType;
+    }
+
+    @Override
+    public Class<BasicDBList> getExpectedReturnType() {
+        return BasicDBList.class;
+    }
+}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MongoEntityMapper.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MongoEntityMapper.java
index 513a7fc..1c85ae8 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MongoEntityMapper.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MongoEntityMapper.java
@@ -1,63 +1,63 @@
-package org.keycloak.connections.mongo.impl.types;
-
-import com.mongodb.BasicDBObject;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.types.Mapper;
-import org.keycloak.connections.mongo.api.types.MapperContext;
-import org.keycloak.connections.mongo.api.types.MapperRegistry;
-import org.keycloak.connections.mongo.impl.EntityInfo;
-import org.keycloak.connections.mongo.impl.MongoStoreImpl;
-import org.keycloak.models.utils.reflection.Property;
-
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoEntityMapper<T> implements Mapper<T, BasicDBObject> {
-
-    private final MongoStoreImpl mongoStoreImpl;
-    private final MapperRegistry mapperRegistry;
-    private final Class<T> expectedMongoEntityType;
-
-    public MongoEntityMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<T> expectedMongoEntityType) {
-        this.mongoStoreImpl = mongoStoreImpl;
-        this.mapperRegistry = mapperRegistry;
-        this.expectedMongoEntityType = expectedMongoEntityType;
-    }
-
-    @Override
-    public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
-        T applicationObject = context.getObjectToConvert();
-
-        EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(applicationObject.getClass());
-
-        // Create instance of BasicDBObject and add all declared properties to it
-        BasicDBObject dbObject = new BasicDBObject();
-        Collection<Property<Object>> props = entityInfo.getProperties();
-        for (Property<Object> property : props) {
-            String propName = property.getName();
-
-            // Ignore "id" property
-            if (!"id".equals(propName) || !(applicationObject instanceof MongoIdentifiableEntity)) {
-                Object propValue = property.getValue(applicationObject);
-                if (propValue != null) {
-                    Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
-                    dbObject.put(propName, dbValue);
-                }
-            }
-        }
-
-        return dbObject;
-    }
-
-    @Override
-    public Class<? extends T> getTypeOfObjectToConvert() {
-        return expectedMongoEntityType;
-    }
-
-    @Override
-    public Class<BasicDBObject> getExpectedReturnType() {
-        return BasicDBObject.class;
-    }
-}
+package org.keycloak.connections.mongo.impl.types;
+
+import com.mongodb.BasicDBObject;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.types.Mapper;
+import org.keycloak.connections.mongo.api.types.MapperContext;
+import org.keycloak.connections.mongo.api.types.MapperRegistry;
+import org.keycloak.connections.mongo.impl.EntityInfo;
+import org.keycloak.connections.mongo.impl.MongoStoreImpl;
+import org.keycloak.models.utils.reflection.Property;
+
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoEntityMapper<T> implements Mapper<T, BasicDBObject> {
+
+    private final MongoStoreImpl mongoStoreImpl;
+    private final MapperRegistry mapperRegistry;
+    private final Class<T> expectedMongoEntityType;
+
+    public MongoEntityMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<T> expectedMongoEntityType) {
+        this.mongoStoreImpl = mongoStoreImpl;
+        this.mapperRegistry = mapperRegistry;
+        this.expectedMongoEntityType = expectedMongoEntityType;
+    }
+
+    @Override
+    public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
+        T applicationObject = context.getObjectToConvert();
+
+        EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(applicationObject.getClass());
+
+        // Create instance of BasicDBObject and add all declared properties to it
+        BasicDBObject dbObject = new BasicDBObject();
+        Collection<Property<Object>> props = entityInfo.getProperties();
+        for (Property<Object> property : props) {
+            String propName = property.getName();
+
+            // Ignore "id" property
+            if (!"id".equals(propName) || !(applicationObject instanceof MongoIdentifiableEntity)) {
+                Object propValue = property.getValue(applicationObject);
+                if (propValue != null) {
+                    Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
+                    dbObject.put(propName, dbValue);
+                }
+            }
+        }
+
+        return dbObject;
+    }
+
+    @Override
+    public Class<? extends T> getTypeOfObjectToConvert() {
+        return expectedMongoEntityType;
+    }
+
+    @Override
+    public Class<BasicDBObject> getExpectedReturnType() {
+        return BasicDBObject.class;
+    }
+}

connections/pom.xml 72(+36 -36)

diff --git a/connections/pom.xml b/connections/pom.xml
index a300c30..66ddaf2 100755
--- a/connections/pom.xml
+++ b/connections/pom.xml
@@ -1,36 +1,36 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-    <name>Connections Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-connections-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>jpa</module>
-        <module>jpa-liquibase</module>
-        <module>infinispan</module>
-        <module>mongo</module>
-        <module>file</module>
-        <module>mongo-update</module>
-        <module>http-client</module>
-    </modules>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+    <name>Connections Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-connections-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>jpa</module>
+        <module>jpa-liquibase</module>
+        <module>infinispan</module>
+        <module>mongo</module>
+        <module>file</module>
+        <module>mongo-update</module>
+        <module>http-client</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

core/pom.xml 224(+112 -112)

diff --git a/core/pom.xml b/core/pom.xml
index 5a12d1b..a405bf8 100755
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,112 +1,112 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-core</artifactId>
-    <name>Keycloak Core</name>
-    <packaging>jar</packaging>
-    <description/>
-
-    <properties>
-        <timestamp>${maven.build.timestamp}</timestamp>
-        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
-        <keycloak.osgi.export>
-            org.keycloak.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            net.iharder;version=${base64.version},
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-core</artifactId>
+    <name>Keycloak Core</name>
+    <packaging>jar</packaging>
+    <description/>
+
+    <properties>
+        <timestamp>${maven.build.timestamp}</timestamp>
+        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
+        <keycloak.osgi.export>
+            org.keycloak.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            net.iharder;version=${base64.version},
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/core/src/main/java/org/keycloak/AbstractOAuthClient.java b/core/src/main/java/org/keycloak/AbstractOAuthClient.java
index 3b29907..2a95905 100755
--- a/core/src/main/java/org/keycloak/AbstractOAuthClient.java
+++ b/core/src/main/java/org/keycloak/AbstractOAuthClient.java
@@ -1,111 +1,111 @@
-package org.keycloak;
-
-import org.keycloak.enums.RelativeUrlsUsed;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AbstractOAuthClient {
-    private static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
-    private final AtomicLong counter = new AtomicLong();
-
-    protected String clientId;
-    protected Map<String, String> credentials;
-    protected String authUrl;
-    protected String tokenUrl;
-    protected RelativeUrlsUsed relativeUrlsUsed;
-    protected String scope;
-    protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
-    protected String stateCookiePath;
-    protected boolean isSecure;
-    protected boolean publicClient;
-    protected String getStateCode() {
-        return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public Map<String, String> getCredentials() {
-        return credentials;
-    }
-
-    public void setCredentials(Map<String, String> credentials) {
-        this.credentials = credentials;
-    }
-
-    public String getAuthUrl() {
-        return authUrl;
-    }
-
-    public void setAuthUrl(String authUrl) {
-        this.authUrl = authUrl;
-    }
-
-    public String getTokenUrl() {
-        return tokenUrl;
-    }
-
-    public void setTokenUrl(String tokenUrl) {
-        this.tokenUrl = tokenUrl;
-    }
-
-    public String getScope() {
-        return scope;
-    }
-
-    public void setScope(String scope) {
-        this.scope = scope;
-    }
-
-    public String getStateCookieName() {
-        return stateCookieName;
-    }
-
-    public void setStateCookieName(String stateCookieName) {
-        this.stateCookieName = stateCookieName;
-    }
-
-    public String getStateCookiePath() {
-        return stateCookiePath;
-    }
-
-    public void setStateCookiePath(String stateCookiePath) {
-        this.stateCookiePath = stateCookiePath;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public RelativeUrlsUsed getRelativeUrlsUsed() {
-        return relativeUrlsUsed;
-    }
-
-    public void setRelativeUrlsUsed(RelativeUrlsUsed relativeUrlsUsed) {
-        this.relativeUrlsUsed = relativeUrlsUsed;
-    }
-
-    protected String stripOauthParametersFromRedirect(String uri) {
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
-                .replaceQueryParam(OAuth2Constants.CODE, null)
-                .replaceQueryParam(OAuth2Constants.STATE, null);
-        return builder.build().toString();
-    }
-
-}
+package org.keycloak;
+
+import org.keycloak.enums.RelativeUrlsUsed;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AbstractOAuthClient {
+    private static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
+    private final AtomicLong counter = new AtomicLong();
+
+    protected String clientId;
+    protected Map<String, String> credentials;
+    protected String authUrl;
+    protected String tokenUrl;
+    protected RelativeUrlsUsed relativeUrlsUsed;
+    protected String scope;
+    protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
+    protected String stateCookiePath;
+    protected boolean isSecure;
+    protected boolean publicClient;
+    protected String getStateCode() {
+        return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public Map<String, String> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(Map<String, String> credentials) {
+        this.credentials = credentials;
+    }
+
+    public String getAuthUrl() {
+        return authUrl;
+    }
+
+    public void setAuthUrl(String authUrl) {
+        this.authUrl = authUrl;
+    }
+
+    public String getTokenUrl() {
+        return tokenUrl;
+    }
+
+    public void setTokenUrl(String tokenUrl) {
+        this.tokenUrl = tokenUrl;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+    public String getStateCookieName() {
+        return stateCookieName;
+    }
+
+    public void setStateCookieName(String stateCookieName) {
+        this.stateCookieName = stateCookieName;
+    }
+
+    public String getStateCookiePath() {
+        return stateCookiePath;
+    }
+
+    public void setStateCookiePath(String stateCookiePath) {
+        this.stateCookiePath = stateCookiePath;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public RelativeUrlsUsed getRelativeUrlsUsed() {
+        return relativeUrlsUsed;
+    }
+
+    public void setRelativeUrlsUsed(RelativeUrlsUsed relativeUrlsUsed) {
+        this.relativeUrlsUsed = relativeUrlsUsed;
+    }
+
+    protected String stripOauthParametersFromRedirect(String uri) {
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
+                .replaceQueryParam(OAuth2Constants.CODE, null)
+                .replaceQueryParam(OAuth2Constants.STATE, null);
+        return builder.build().toString();
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/ClientConnection.java b/core/src/main/java/org/keycloak/ClientConnection.java
index 23dc3a5..a9e95c5 100755
--- a/core/src/main/java/org/keycloak/ClientConnection.java
+++ b/core/src/main/java/org/keycloak/ClientConnection.java
@@ -1,13 +1,13 @@
-package org.keycloak;
-
-/**
- * Information about the client connection
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ClientConnection {
-    String getRemoteAddr();
-    String getRemoteHost();
-    int getReportPort();
-}
+package org.keycloak;
+
+/**
+ * Information about the client connection
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientConnection {
+    String getRemoteAddr();
+    String getRemoteHost();
+    int getReportPort();
+}
diff --git a/core/src/main/java/org/keycloak/Config.java b/core/src/main/java/org/keycloak/Config.java
index 1ce8fd0..757bed3 100755
--- a/core/src/main/java/org/keycloak/Config.java
+++ b/core/src/main/java/org/keycloak/Config.java
@@ -1,163 +1,163 @@
-package org.keycloak;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class Config {
-
-    private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
-
-    public static void init(ConfigProvider configProvider) {
-        Config.configProvider = configProvider;
-    }
-
-    public static String getAdminRealm() {
-        return configProvider.scope("admin").get("realm", "master");
-    }
-
-    public static String getProvider(String spi) {
-        String provider = configProvider.getProvider(spi);
-        if (provider == null || provider.trim().equals("")) {
-            return null;
-        } else {
-            return provider;
-        }
-    }
-
-    public static Scope scope(String... scope) {
-         return configProvider.scope(scope);
-    }
-
-    public static interface ConfigProvider {
-
-        String getProvider(String spi);
-
-        Scope scope(String... scope);
-
-    }
-
-    public static class SystemPropertiesConfigProvider implements ConfigProvider {
-
-        @Override
-        public String getProvider(String spi) {
-            return System.getProperties().getProperty("keycloak." + spi + ".provider");
-        }
-
-        @Override
-        public Scope scope(String... scope) {
-            StringBuilder sb = new StringBuilder();
-            sb.append("keycloak.");
-            for (String s : scope) {
-                sb.append(s);
-                sb.append(".");
-            }
-            return new SystemPropertiesScope(sb.toString());
-        }
-
-    }
-
-    public static class SystemPropertiesScope implements Scope {
-
-        private String prefix;
-
-        public SystemPropertiesScope(String prefix) {
-            this.prefix = prefix;
-        }
-
-        @Override
-        public String get(String key) {
-            return get(key, null);
-        }
-
-        @Override
-        public String get(String key, String defaultValue) {
-            return System.getProperty(prefix + key, defaultValue);
-        }
-
-        @Override
-        public String[] getArray(String key) {
-            String value = get(key);
-            if (value != null) {
-                String[] a = value.split(",");
-                for (int i = 0; i < a.length; i++) {
-                    a[i] = a[i].trim();
-                }
-                return a;
-            } else {
-                return null;
-            }
-        }
-
-        @Override
-        public Integer getInt(String key) {
-            return getInt(key, null);
-        }
-
-        @Override
-        public Integer getInt(String key, Integer defaultValue) {
-            String v = get(key, null);
-            return v != null ? Integer.parseInt(v) : defaultValue;
-        }
-
-        @Override
-        public Long getLong(String key) {
-            return getLong(key, null);
-        }
-
-        @Override
-        public Long getLong(String key, Long defaultValue) {
-            String v = get(key, null);
-            return v != null ? Long.parseLong(v) : defaultValue;
-        }
-
-        @Override
-        public Boolean getBoolean(String key) {
-            return getBoolean(key, null);
-        }
-
-        @Override
-        public Boolean getBoolean(String key, Boolean defaultValue) {
-            String v = get(key, null);
-            return v != null ? Boolean.parseBoolean(v) : defaultValue;
-        }
-
-        @Override
-        public Scope scope(String... scope) {
-            StringBuilder sb = new StringBuilder();
-            sb.append(prefix + ".");
-            for (String s : scope) {
-                sb.append(s);
-                sb.append(".");
-            }
-            return new SystemPropertiesScope(sb.toString());
-        }
-
-    }
-
-    /**
-     * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
-     */
-    public static interface Scope {
-
-        String get(String key);
-
-        String get(String key, String defaultValue);
-
-        String[] getArray(String key);
-
-        Integer getInt(String key);
-
-        Integer getInt(String key, Integer defaultValue);
-
-        Long getLong(String key);
-
-        Long getLong(String key, Long defaultValue);
-
-        Boolean getBoolean(String key);
-
-        Boolean getBoolean(String key, Boolean defaultValue);
-
-        Scope scope(String... scope);
-
-    }
-}
+package org.keycloak;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class Config {
+
+    private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
+
+    public static void init(ConfigProvider configProvider) {
+        Config.configProvider = configProvider;
+    }
+
+    public static String getAdminRealm() {
+        return configProvider.scope("admin").get("realm", "master");
+    }
+
+    public static String getProvider(String spi) {
+        String provider = configProvider.getProvider(spi);
+        if (provider == null || provider.trim().equals("")) {
+            return null;
+        } else {
+            return provider;
+        }
+    }
+
+    public static Scope scope(String... scope) {
+         return configProvider.scope(scope);
+    }
+
+    public static interface ConfigProvider {
+
+        String getProvider(String spi);
+
+        Scope scope(String... scope);
+
+    }
+
+    public static class SystemPropertiesConfigProvider implements ConfigProvider {
+
+        @Override
+        public String getProvider(String spi) {
+            return System.getProperties().getProperty("keycloak." + spi + ".provider");
+        }
+
+        @Override
+        public Scope scope(String... scope) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("keycloak.");
+            for (String s : scope) {
+                sb.append(s);
+                sb.append(".");
+            }
+            return new SystemPropertiesScope(sb.toString());
+        }
+
+    }
+
+    public static class SystemPropertiesScope implements Scope {
+
+        private String prefix;
+
+        public SystemPropertiesScope(String prefix) {
+            this.prefix = prefix;
+        }
+
+        @Override
+        public String get(String key) {
+            return get(key, null);
+        }
+
+        @Override
+        public String get(String key, String defaultValue) {
+            return System.getProperty(prefix + key, defaultValue);
+        }
+
+        @Override
+        public String[] getArray(String key) {
+            String value = get(key);
+            if (value != null) {
+                String[] a = value.split(",");
+                for (int i = 0; i < a.length; i++) {
+                    a[i] = a[i].trim();
+                }
+                return a;
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public Integer getInt(String key) {
+            return getInt(key, null);
+        }
+
+        @Override
+        public Integer getInt(String key, Integer defaultValue) {
+            String v = get(key, null);
+            return v != null ? Integer.parseInt(v) : defaultValue;
+        }
+
+        @Override
+        public Long getLong(String key) {
+            return getLong(key, null);
+        }
+
+        @Override
+        public Long getLong(String key, Long defaultValue) {
+            String v = get(key, null);
+            return v != null ? Long.parseLong(v) : defaultValue;
+        }
+
+        @Override
+        public Boolean getBoolean(String key) {
+            return getBoolean(key, null);
+        }
+
+        @Override
+        public Boolean getBoolean(String key, Boolean defaultValue) {
+            String v = get(key, null);
+            return v != null ? Boolean.parseBoolean(v) : defaultValue;
+        }
+
+        @Override
+        public Scope scope(String... scope) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(prefix + ".");
+            for (String s : scope) {
+                sb.append(s);
+                sb.append(".");
+            }
+            return new SystemPropertiesScope(sb.toString());
+        }
+
+    }
+
+    /**
+     * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+     */
+    public static interface Scope {
+
+        String get(String key);
+
+        String get(String key, String defaultValue);
+
+        String[] getArray(String key);
+
+        Integer getInt(String key);
+
+        Integer getInt(String key, Integer defaultValue);
+
+        Long getLong(String key);
+
+        Long getLong(String key, Long defaultValue);
+
+        Boolean getBoolean(String key);
+
+        Boolean getBoolean(String key, Boolean defaultValue);
+
+        Scope scope(String... scope);
+
+    }
+}
diff --git a/core/src/main/java/org/keycloak/constants/AdapterConstants.java b/core/src/main/java/org/keycloak/constants/AdapterConstants.java
index aa22395..1316e99 100755
--- a/core/src/main/java/org/keycloak/constants/AdapterConstants.java
+++ b/core/src/main/java/org/keycloak/constants/AdapterConstants.java
@@ -1,35 +1,35 @@
-package org.keycloak.constants;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface AdapterConstants {
-
-    // URL endpoints
-    public static final String K_LOGOUT = "k_logout";
-    public static final String K_VERSION = "k_version";
-    public static final String K_PUSH_NOT_BEFORE = "k_push_not_before";
-    public static final String K_TEST_AVAILABLE = "k_test_available";
-    public static final String K_QUERY_BEARER_TOKEN = "k_query_bearer_token";
-
-    // This param name is defined again in Keycloak Subsystem class
-    // org.keycloak.subsystem.extensionKeycloakAdapterConfigDeploymentProcessor.  We have this value in
-    // two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
-    String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
-
-    // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains ID of HttpSession on adapter
-    public static final String CLIENT_SESSION_STATE = "client_session_state";
-
-    // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains hostname of adapter where HttpSession is served
-    public static final String CLIENT_SESSION_HOST = "client_session_host";
-
-    // Attribute passed in registerNode request for register new application cluster node once he joined cluster
-    public static final String CLIENT_CLUSTER_HOST = "client_cluster_host";
-
-    // Cookie used on adapter side to store token info. Used only when tokenStore is 'COOKIE'
-    public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE";
-
-    // Request parameter used to specify the identifier of the identity provider that should be used to authenticate an user
-    String KC_IDP_HINT = "kc_idp_hint";
-}
+package org.keycloak.constants;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AdapterConstants {
+
+    // URL endpoints
+    public static final String K_LOGOUT = "k_logout";
+    public static final String K_VERSION = "k_version";
+    public static final String K_PUSH_NOT_BEFORE = "k_push_not_before";
+    public static final String K_TEST_AVAILABLE = "k_test_available";
+    public static final String K_QUERY_BEARER_TOKEN = "k_query_bearer_token";
+
+    // This param name is defined again in Keycloak Subsystem class
+    // org.keycloak.subsystem.extensionKeycloakAdapterConfigDeploymentProcessor.  We have this value in
+    // two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
+    String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
+
+    // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains ID of HttpSession on adapter
+    public static final String CLIENT_SESSION_STATE = "client_session_state";
+
+    // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains hostname of adapter where HttpSession is served
+    public static final String CLIENT_SESSION_HOST = "client_session_host";
+
+    // Attribute passed in registerNode request for register new application cluster node once he joined cluster
+    public static final String CLIENT_CLUSTER_HOST = "client_cluster_host";
+
+    // Cookie used on adapter side to store token info. Used only when tokenStore is 'COOKIE'
+    public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE";
+
+    // Request parameter used to specify the identifier of the identity provider that should be used to authenticate an user
+    String KC_IDP_HINT = "kc_idp_hint";
+}
diff --git a/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java b/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
index ae0b686..aaa9c82 100755
--- a/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
+++ b/core/src/main/java/org/keycloak/constants/ServiceUrlConstants.java
@@ -1,17 +1,17 @@
-package org.keycloak.constants;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ServiceUrlConstants {
-
-    public static final String AUTH_PATH = "/realms/{realm-name}/protocol/openid-connect/auth";
-    public static final String TOKEN_PATH = "/realms/{realm-name}/protocol/openid-connect/token";
-    public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/protocol/openid-connect/logout";
-    public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
-    public static final String REALM_INFO_PATH = "/realms/{realm-name}";
-    public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/register-node";
-    public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/unregister-node";
-
-}
+package org.keycloak.constants;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ServiceUrlConstants {
+
+    public static final String AUTH_PATH = "/realms/{realm-name}/protocol/openid-connect/auth";
+    public static final String TOKEN_PATH = "/realms/{realm-name}/protocol/openid-connect/token";
+    public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/protocol/openid-connect/logout";
+    public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
+    public static final String REALM_INFO_PATH = "/realms/{realm-name}";
+    public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/register-node";
+    public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/unregister-node";
+
+}
diff --git a/core/src/main/java/org/keycloak/jose/jws/Algorithm.java b/core/src/main/java/org/keycloak/jose/jws/Algorithm.java
index 4e0f47f..a829a58 100755
--- a/core/src/main/java/org/keycloak/jose/jws/Algorithm.java
+++ b/core/src/main/java/org/keycloak/jose/jws/Algorithm.java
@@ -1,32 +1,32 @@
-package org.keycloak.jose.jws;
-
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.jose.jws.crypto.SignatureProvider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public enum Algorithm {
-
-    none(null),
-    HS256(null),
-    HS384(null),
-    HS512(null),
-    RS256(new RSAProvider()),
-    RS384(new RSAProvider()),
-    RS512(new RSAProvider()),
-    ES256(null),
-    ES384(null),
-    ES512(null)
-    ;
-    private SignatureProvider provider;
-
-    Algorithm(SignatureProvider provider) {
-        this.provider = provider;
-    }
-
-    public SignatureProvider getProvider() {
-        return provider;
-    }
-}
+package org.keycloak.jose.jws;
+
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.jose.jws.crypto.SignatureProvider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public enum Algorithm {
+
+    none(null),
+    HS256(null),
+    HS384(null),
+    HS512(null),
+    RS256(new RSAProvider()),
+    RS384(new RSAProvider()),
+    RS512(new RSAProvider()),
+    ES256(null),
+    ES384(null),
+    ES512(null)
+    ;
+    private SignatureProvider provider;
+
+    Algorithm(SignatureProvider provider) {
+        this.provider = provider;
+    }
+
+    public SignatureProvider getProvider() {
+        return provider;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java b/core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java
index fef959d..fc63fd6 100755
--- a/core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java
+++ b/core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java
@@ -1,89 +1,89 @@
-package org.keycloak.jose.jws.crypto;
-
-
-import org.keycloak.jose.jws.Algorithm;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.util.Base64Url;
-
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import java.security.NoSuchAlgorithmException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HMACProvider implements SignatureProvider {
-    private static String getJavaAlgorithm(Algorithm alg) {
-        switch (alg) {
-            case HS256:
-                return "HMACSHA256";
-            case HS384:
-                return "HMACSHA384";
-            case HS512:
-                return "HMACSHA512";
-            default:
-                throw new IllegalArgumentException("Not a MAC Algorithm");
-        }
-    }
-
-    private static Mac getMAC(final Algorithm alg) {
-
-        try {
-            return Mac.getInstance(getJavaAlgorithm(alg));
-
-        } catch (NoSuchAlgorithmException e) {
-
-            throw new RuntimeException("Unsupported HMAC algorithm: " + e.getMessage(), e);
-        }
-    }
-
-    public static byte[] sign(byte[] data, Algorithm algorithm, byte[] sharedSecret) {
-        try {
-            Mac mac = getMAC(algorithm);
-            mac.init(new SecretKeySpec(sharedSecret, mac.getAlgorithm()));
-            mac.update(data);
-            return mac.doFinal();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static byte[] sign(byte[] data, Algorithm algorithm, SecretKey key) {
-        try {
-            Mac mac = getMAC(algorithm);
-            mac.init(key);
-            mac.update(data);
-            return mac.doFinal();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static boolean verify(JWSInput input, SecretKey key) {
-        try {
-            byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), key);
-            String x = Base64Url.encode(signature);
-            return x.equals(input.getEncodedSignature());
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    public static boolean verify(JWSInput input, byte[] sharedSecret) {
-        try {
-            byte[] signature = sign(input.getEncodedSignatureInput().getBytes("UTF-8"), input.getHeader().getAlgorithm(), sharedSecret);
-            String x = Base64Url.encode(signature);
-            return x.equals(input.getEncodedSignature());
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public boolean verify(JWSInput input, String key) {
-        return false;
-    }
-}
+package org.keycloak.jose.jws.crypto;
+
+
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.util.Base64Url;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HMACProvider implements SignatureProvider {
+    private static String getJavaAlgorithm(Algorithm alg) {
+        switch (alg) {
+            case HS256:
+                return "HMACSHA256";
+            case HS384:
+                return "HMACSHA384";
+            case HS512:
+                return "HMACSHA512";
+            default:
+                throw new IllegalArgumentException("Not a MAC Algorithm");
+        }
+    }
+
+    private static Mac getMAC(final Algorithm alg) {
+
+        try {
+            return Mac.getInstance(getJavaAlgorithm(alg));
+
+        } catch (NoSuchAlgorithmException e) {
+
+            throw new RuntimeException("Unsupported HMAC algorithm: " + e.getMessage(), e);
+        }
+    }
+
+    public static byte[] sign(byte[] data, Algorithm algorithm, byte[] sharedSecret) {
+        try {
+            Mac mac = getMAC(algorithm);
+            mac.init(new SecretKeySpec(sharedSecret, mac.getAlgorithm()));
+            mac.update(data);
+            return mac.doFinal();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static byte[] sign(byte[] data, Algorithm algorithm, SecretKey key) {
+        try {
+            Mac mac = getMAC(algorithm);
+            mac.init(key);
+            mac.update(data);
+            return mac.doFinal();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static boolean verify(JWSInput input, SecretKey key) {
+        try {
+            byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), key);
+            String x = Base64Url.encode(signature);
+            return x.equals(input.getEncodedSignature());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    public static boolean verify(JWSInput input, byte[] sharedSecret) {
+        try {
+            byte[] signature = sign(input.getEncodedSignatureInput().getBytes("UTF-8"), input.getHeader().getAlgorithm(), sharedSecret);
+            String x = Base64Url.encode(signature);
+            return x.equals(input.getEncodedSignature());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public boolean verify(JWSInput input, String key) {
+        return false;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/jose/jws/crypto/SignatureProvider.java b/core/src/main/java/org/keycloak/jose/jws/crypto/SignatureProvider.java
index 8480b46..f0d26b6 100755
--- a/core/src/main/java/org/keycloak/jose/jws/crypto/SignatureProvider.java
+++ b/core/src/main/java/org/keycloak/jose/jws/crypto/SignatureProvider.java
@@ -1,11 +1,11 @@
-package org.keycloak.jose.jws.crypto;
-
-import org.keycloak.jose.jws.JWSInput;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface SignatureProvider {
-    boolean verify(JWSInput input, String key);
-}
+package org.keycloak.jose.jws.crypto;
+
+import org.keycloak.jose.jws.JWSInput;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface SignatureProvider {
+    boolean verify(JWSInput input, String key);
+}
diff --git a/core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java b/core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java
index 3ef2d83..5c057e1 100755
--- a/core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java
+++ b/core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java
@@ -1,205 +1,205 @@
-package org.keycloak.jose.jws;
-
-import org.keycloak.jose.jws.crypto.HMACProvider;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.util.Base64Url;
-import org.keycloak.util.JsonSerialization;
-
-import javax.crypto.SecretKey;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.PrivateKey;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JWSBuilder {
-    String type;
-    String contentType;
-    byte[] contentBytes;
-
-    public JWSBuilder type(String type) {
-        this.type = type;
-        return this;
-    }
-
-    public JWSBuilder contentType(String type) {
-        this.contentType = type;
-        return this;
-    }
-
-    public EncodingBuilder content(byte[] bytes) {
-        this.contentBytes = bytes;
-        return new EncodingBuilder();
-    }
-
-    public EncodingBuilder jsonContent(Object object) {
-        try {
-            this.contentBytes = JsonSerialization.writeValueAsBytes(object);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return new EncodingBuilder();
-    }
-
-
-    protected String encodeHeader(Algorithm alg) {
-        StringBuilder builder = new StringBuilder("{");
-        builder.append("\"alg\":\"").append(alg.toString()).append("\"");
-
-        if (type != null) builder.append(",\"typ\" : \"").append(type).append("\"");
-        if (contentType != null) builder.append(",\"cty\":\"").append(contentType).append("\"");
-        builder.append("}");
-        try {
-            return Base64Url.encode(builder.toString().getBytes("UTF-8"));
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected String encodeAll(StringBuffer encoding, byte[] signature) {
-        encoding.append('.');
-        if (signature != null) {
-            encoding.append(Base64Url.encode(signature));
-        }
-        return encoding.toString();
-    }
-
-    protected void encode(Algorithm alg, byte[] data, StringBuffer encoding) {
-        encoding.append(encodeHeader(alg));
-        encoding.append('.');
-        encoding.append(Base64Url.encode(data));
-    }
-
-    protected byte[] marshalContent() {
-        return contentBytes;
-    }
-
-    public class EncodingBuilder {
-        public String none() {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.none, data, buffer);
-            return encodeAll(buffer, null);
-        }
-
-        public String rsa256(PrivateKey privateKey) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.RS256, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS256, privateKey);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String rsa384(PrivateKey privateKey) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.RS384, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS384, privateKey);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String rsa512(PrivateKey privateKey) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.RS512, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS512, privateKey);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-
-        public String hmac256(byte[] sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS256, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String hmac384(byte[] sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS384, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String hmac512(byte[] sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS512, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String hmac256(SecretKey sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS256, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String hmac384(SecretKey sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS384, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-
-        public String hmac512(SecretKey sharedSecret) {
-            StringBuffer buffer = new StringBuffer();
-            byte[] data = marshalContent();
-            encode(Algorithm.HS512, data, buffer);
-            byte[] signature = null;
-            try {
-                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            return encodeAll(buffer, signature);
-        }
-    }
-}
+package org.keycloak.jose.jws;
+
+import org.keycloak.jose.jws.crypto.HMACProvider;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.util.Base64Url;
+import org.keycloak.util.JsonSerialization;
+
+import javax.crypto.SecretKey;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.PrivateKey;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JWSBuilder {
+    String type;
+    String contentType;
+    byte[] contentBytes;
+
+    public JWSBuilder type(String type) {
+        this.type = type;
+        return this;
+    }
+
+    public JWSBuilder contentType(String type) {
+        this.contentType = type;
+        return this;
+    }
+
+    public EncodingBuilder content(byte[] bytes) {
+        this.contentBytes = bytes;
+        return new EncodingBuilder();
+    }
+
+    public EncodingBuilder jsonContent(Object object) {
+        try {
+            this.contentBytes = JsonSerialization.writeValueAsBytes(object);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return new EncodingBuilder();
+    }
+
+
+    protected String encodeHeader(Algorithm alg) {
+        StringBuilder builder = new StringBuilder("{");
+        builder.append("\"alg\":\"").append(alg.toString()).append("\"");
+
+        if (type != null) builder.append(",\"typ\" : \"").append(type).append("\"");
+        if (contentType != null) builder.append(",\"cty\":\"").append(contentType).append("\"");
+        builder.append("}");
+        try {
+            return Base64Url.encode(builder.toString().getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected String encodeAll(StringBuffer encoding, byte[] signature) {
+        encoding.append('.');
+        if (signature != null) {
+            encoding.append(Base64Url.encode(signature));
+        }
+        return encoding.toString();
+    }
+
+    protected void encode(Algorithm alg, byte[] data, StringBuffer encoding) {
+        encoding.append(encodeHeader(alg));
+        encoding.append('.');
+        encoding.append(Base64Url.encode(data));
+    }
+
+    protected byte[] marshalContent() {
+        return contentBytes;
+    }
+
+    public class EncodingBuilder {
+        public String none() {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.none, data, buffer);
+            return encodeAll(buffer, null);
+        }
+
+        public String rsa256(PrivateKey privateKey) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.RS256, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS256, privateKey);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String rsa384(PrivateKey privateKey) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.RS384, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS384, privateKey);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String rsa512(PrivateKey privateKey) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.RS512, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS512, privateKey);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+
+        public String hmac256(byte[] sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS256, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String hmac384(byte[] sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS384, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String hmac512(byte[] sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS512, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String hmac256(SecretKey sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS256, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String hmac384(SecretKey sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS384, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+
+        public String hmac512(SecretKey sharedSecret) {
+            StringBuffer buffer = new StringBuffer();
+            byte[] data = marshalContent();
+            encode(Algorithm.HS512, data, buffer);
+            byte[] signature = null;
+            try {
+                signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+            return encodeAll(buffer, signature);
+        }
+    }
+}
diff --git a/core/src/main/java/org/keycloak/jose/jws/JWSHeader.java b/core/src/main/java/org/keycloak/jose/jws/JWSHeader.java
index 1d0f8ea..e1bbd99 100755
--- a/core/src/main/java/org/keycloak/jose/jws/JWSHeader.java
+++ b/core/src/main/java/org/keycloak/jose/jws/JWSHeader.java
@@ -1,69 +1,69 @@
-package org.keycloak.jose.jws;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JWSHeader implements Serializable {
-    @JsonProperty("alg")
-    private Algorithm algorithm;
-
-    @JsonProperty("typ")
-    private String type;
-
-    @JsonProperty("cty")
-    private String contentType;
-
-    @JsonProperty("kid")
-    private String keyId;
-
-    public JWSHeader() {
-    }
-
-    public JWSHeader(Algorithm algorithm, String type, String contentType) {
-        this.algorithm = algorithm;
-        this.type = type;
-        this.contentType = contentType;
-    }
-
-    public Algorithm getAlgorithm() {
-        return algorithm;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public String getContentType() {
-        return contentType;
-    }
-
-    public String getKeyId() {
-        return keyId;
-    }
-
-    private static final ObjectMapper mapper = new ObjectMapper();
-
-    static {
-        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
-
-    }
-
-    public String toString() {
-        try {
-            return mapper.writeValueAsString(this);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-
-
-    }
-
-}
+package org.keycloak.jose.jws;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JWSHeader implements Serializable {
+    @JsonProperty("alg")
+    private Algorithm algorithm;
+
+    @JsonProperty("typ")
+    private String type;
+
+    @JsonProperty("cty")
+    private String contentType;
+
+    @JsonProperty("kid")
+    private String keyId;
+
+    public JWSHeader() {
+    }
+
+    public JWSHeader(Algorithm algorithm, String type, String contentType) {
+        this.algorithm = algorithm;
+        this.type = type;
+        this.contentType = contentType;
+    }
+
+    public Algorithm getAlgorithm() {
+        return algorithm;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+
+    public String getKeyId() {
+        return keyId;
+    }
+
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    static {
+        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
+
+    }
+
+    public String toString() {
+        try {
+            return mapper.writeValueAsString(this);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/KeycloakPrincipal.java b/core/src/main/java/org/keycloak/KeycloakPrincipal.java
index e2819ea..c8a9815 100755
--- a/core/src/main/java/org/keycloak/KeycloakPrincipal.java
+++ b/core/src/main/java/org/keycloak/KeycloakPrincipal.java
@@ -1,49 +1,49 @@
-package org.keycloak;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakPrincipal<T extends KeycloakSecurityContext> implements Principal, Serializable {
-    protected final String name;
-    protected final T context;
-
-    public KeycloakPrincipal(String name, T context) {
-        this.name = name;
-        this.context = context;
-    }
-
-    public T getKeycloakSecurityContext() {
-        return context;
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        KeycloakPrincipal that = (KeycloakPrincipal) o;
-
-        if (!name.equals(that.name)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return name.hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-}
+package org.keycloak;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakPrincipal<T extends KeycloakSecurityContext> implements Principal, Serializable {
+    protected final String name;
+    protected final T context;
+
+    public KeycloakPrincipal(String name, T context) {
+        this.name = name;
+        this.context = context;
+    }
+
+    public T getKeycloakSecurityContext() {
+        return context;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        KeycloakPrincipal that = (KeycloakPrincipal) o;
+
+        if (!name.equals(that.name)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/KeycloakSecurityContext.java b/core/src/main/java/org/keycloak/KeycloakSecurityContext.java
index ec5706f..e480d87 100755
--- a/core/src/main/java/org/keycloak/KeycloakSecurityContext.java
+++ b/core/src/main/java/org/keycloak/KeycloakSecurityContext.java
@@ -1,82 +1,82 @@
-package org.keycloak;
-
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-import org.keycloak.util.Base64Url;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakSecurityContext implements Serializable {
-    protected String tokenString;
-    protected String idTokenString;
-
-    // Don't store parsed tokens into HTTP session
-    protected transient AccessToken token;
-    protected transient IDToken idToken;
-
-    public KeycloakSecurityContext() {
-    }
-
-    public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken) {
-        this.tokenString = tokenString;
-        this.token = token;
-        this.idToken = idToken;
-        this.idTokenString = idTokenString;
-    }
-
-    public AccessToken getToken() {
-        return token;
-    }
-
-    public String getTokenString() {
-        return tokenString;
-    }
-
-    public IDToken getIdToken() {
-        return idToken;
-    }
-
-    public String getIdTokenString() {
-        return idTokenString;
-    }
-
-    public String getRealm() {
-        // Assumption that issuer contains realm name
-        return token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
-    }
-
-    // SERIALIZATION
-
-    private void writeObject(ObjectOutputStream out) throws IOException {
-        out.defaultWriteObject();
-    }
-
-    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-        in.defaultReadObject();
-
-        token = parseToken(tokenString, AccessToken.class);
-        idToken = parseToken(idTokenString, IDToken.class);
-    }
-
-    // Just decode token without any verifications
-    private <T> T parseToken(String encoded, Class<T> clazz) throws IOException {
-        if (encoded == null)
-            return null;
-
-        String[] parts = encoded.split("\\.");
-        if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
-
-        byte[] bytes = Base64Url.decode(parts[1]);
-        return JsonSerialization.readValue(bytes, clazz);
-    }
-
-
-}
+package org.keycloak;
+
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+import org.keycloak.util.Base64Url;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakSecurityContext implements Serializable {
+    protected String tokenString;
+    protected String idTokenString;
+
+    // Don't store parsed tokens into HTTP session
+    protected transient AccessToken token;
+    protected transient IDToken idToken;
+
+    public KeycloakSecurityContext() {
+    }
+
+    public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken) {
+        this.tokenString = tokenString;
+        this.token = token;
+        this.idToken = idToken;
+        this.idTokenString = idTokenString;
+    }
+
+    public AccessToken getToken() {
+        return token;
+    }
+
+    public String getTokenString() {
+        return tokenString;
+    }
+
+    public IDToken getIdToken() {
+        return idToken;
+    }
+
+    public String getIdTokenString() {
+        return idTokenString;
+    }
+
+    public String getRealm() {
+        // Assumption that issuer contains realm name
+        return token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
+    }
+
+    // SERIALIZATION
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+
+        token = parseToken(tokenString, AccessToken.class);
+        idToken = parseToken(idTokenString, IDToken.class);
+    }
+
+    // Just decode token without any verifications
+    private <T> T parseToken(String encoded, Class<T> clazz) throws IOException {
+        if (encoded == null)
+            return null;
+
+        String[] parts = encoded.split("\\.");
+        if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
+
+        byte[] bytes = Base64Url.decode(parts[1]);
+        return JsonSerialization.readValue(bytes, clazz);
+    }
+
+
+}
diff --git a/core/src/main/java/org/keycloak/OAuthErrorException.java b/core/src/main/java/org/keycloak/OAuthErrorException.java
index 4eff35f..16805af 100755
--- a/core/src/main/java/org/keycloak/OAuthErrorException.java
+++ b/core/src/main/java/org/keycloak/OAuthErrorException.java
@@ -1,64 +1,64 @@
-package org.keycloak;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OAuthErrorException extends Exception {
-    public static final String INVALID_REQUEST = "invalid_request";
-    public static final String INVALID_CLIENT = "invalid_client";
-    public static final String INVALID_GRANT = "invalid_grant";
-    public static final String INVALID_SCOPE = "invalid_grant";
-    public static final String UNAUTHORIZED_CLIENT = "unauthorized_client";
-    public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type";
-
-    public OAuthErrorException(String error, String description, String message, Throwable cause) {
-        super(message, cause);
-        this.error = error;
-        this.description = description;
-    }
-    public OAuthErrorException(String error, String description, String message) {
-        super(message);
-        this.error = error;
-        this.description = description;
-    }
-    public OAuthErrorException(String error, String description) {
-        super(description);
-        this.error = error;
-        this.description = description;
-    }
-    public OAuthErrorException(String error, String description, Throwable cause) {
-        super(description, cause);
-        this.error = error;
-        this.description = description;
-    }
-
-    public OAuthErrorException(String error) {
-        super(error);
-        this.error = error;
-    }
-    public OAuthErrorException(String error, Throwable cause) {
-        super(error, cause);
-        this.error = error;
-    }
-
-
-    protected String error;
-    protected String description;
-
-    public String getError() {
-        return error;
-    }
-
-    public void setError(String error) {
-        this.error = error;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-}
+package org.keycloak;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OAuthErrorException extends Exception {
+    public static final String INVALID_REQUEST = "invalid_request";
+    public static final String INVALID_CLIENT = "invalid_client";
+    public static final String INVALID_GRANT = "invalid_grant";
+    public static final String INVALID_SCOPE = "invalid_grant";
+    public static final String UNAUTHORIZED_CLIENT = "unauthorized_client";
+    public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type";
+
+    public OAuthErrorException(String error, String description, String message, Throwable cause) {
+        super(message, cause);
+        this.error = error;
+        this.description = description;
+    }
+    public OAuthErrorException(String error, String description, String message) {
+        super(message);
+        this.error = error;
+        this.description = description;
+    }
+    public OAuthErrorException(String error, String description) {
+        super(description);
+        this.error = error;
+        this.description = description;
+    }
+    public OAuthErrorException(String error, String description, Throwable cause) {
+        super(description, cause);
+        this.error = error;
+        this.description = description;
+    }
+
+    public OAuthErrorException(String error) {
+        super(error);
+        this.error = error;
+    }
+    public OAuthErrorException(String error, Throwable cause) {
+        super(error, cause);
+        this.error = error;
+    }
+
+
+    protected String error;
+    protected String description;
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/AccessToken.java b/core/src/main/java/org/keycloak/representations/AccessToken.java
index 81d3615..1380c2f 100755
--- a/core/src/main/java/org/keycloak/representations/AccessToken.java
+++ b/core/src/main/java/org/keycloak/representations/AccessToken.java
@@ -1,211 +1,211 @@
-package org.keycloak.representations;
-
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AccessToken extends IDToken {
-    public static class Access implements Serializable {
-        @JsonProperty("roles")
-        protected Set<String> roles;
-        @JsonProperty("verify_caller")
-        protected Boolean verifyCaller;
-
-        public Access() {
-        }
-
-        public Access clone() {
-            Access access = new Access();
-            access.verifyCaller = verifyCaller;
-            if (roles != null) {
-                access.roles = new HashSet<String>();
-                access.roles.addAll(roles);
-            }
-            return access;
-        }
-
-        public Set<String> getRoles() {
-            return roles;
-        }
-
-        public Access roles(Set<String> roles) {
-            this.roles = roles;
-            return this;
-        }
-
-        @JsonIgnore
-        public boolean isUserInRole(String role) {
-            if (roles == null) return false;
-            return roles.contains(role);
-        }
-
-        public Access addRole(String role) {
-            if (roles == null) roles = new HashSet<String>();
-            roles.add(role);
-            return this;
-        }
-
-        public Boolean getVerifyCaller() {
-            return verifyCaller;
-        }
-
-        public Access verifyCaller(Boolean required) {
-            this.verifyCaller = required;
-            return this;
-        }
-    }
-
-    @JsonProperty("client_session")
-    protected String clientSession;
-
-    @JsonProperty("trusted-certs")
-    protected Set<String> trustedCertificates;
-
-    @JsonProperty("allowed-origins")
-    protected Set<String> allowedOrigins;
-
-    @JsonProperty("realm_access")
-    protected Access realmAccess;
-
-    @JsonProperty("resource_access")
-    protected Map<String, Access> resourceAccess = new HashMap<String, Access>();
-
-    public Map<String, Access> getResourceAccess() {
-        return resourceAccess;
-    }
-
-    public void setResourceAccess(Map<String, Access> resourceAccess) {
-        this.resourceAccess = resourceAccess;
-    }
-
-
-
-
-    /**
-     * Does the realm require verifying the caller?
-     *
-     * @return
-     */
-    @JsonIgnore
-    public boolean isVerifyCaller() {
-        if (getRealmAccess() != null && getRealmAccess().getVerifyCaller() != null)
-            return getRealmAccess().getVerifyCaller().booleanValue();
-        return false;
-    }
-
-    /**
-     * Does the resource override the requirement of verifying the caller?
-     *
-     * @param resource
-     * @return
-     */
-    @JsonIgnore
-    public boolean isVerifyCaller(String resource) {
-        Access access = getResourceAccess(resource);
-        if (access != null && access.getVerifyCaller() != null) return access.getVerifyCaller().booleanValue();
-        return false;
-    }
-
-    @JsonIgnore
-    public Access getResourceAccess(String resource) {
-        return resourceAccess.get(resource);
-    }
-
-    public String getClientSession() {
-        return clientSession;
-    }
-
-    public Access addAccess(String service) {
-        Access access = resourceAccess.get(service);
-        if (access != null) return access;
-        access = new Access();
-        resourceAccess.put(service, access);
-        return access;
-    }
-
-    public AccessToken clientSession(String session) {
-        this.clientSession = session;
-        return this;
-    }
-
-    @Override
-    public AccessToken id(String id) {
-        return (AccessToken) super.id(id);
-    }
-
-    @Override
-    public AccessToken expiration(int expiration) {
-        return (AccessToken) super.expiration(expiration);
-    }
-
-    @Override
-    public AccessToken notBefore(int notBefore) {
-        return (AccessToken) super.notBefore(notBefore);
-    }
-
-
-    @Override
-    public AccessToken issuedAt(int issuedAt) {
-        return (AccessToken) super.issuedAt(issuedAt);
-    }
-
-    @Override
-    public AccessToken issuer(String issuer) {
-        return (AccessToken) super.issuer(issuer);
-    }
-
-    @Override
-    public AccessToken audience(String audience) {
-        return (AccessToken) super.audience(audience);
-    }
-
-    @Override
-    public AccessToken subject(String subject) {
-        return (AccessToken) super.subject(subject);
-    }
-
-    @Override
-    public AccessToken type(String type) {
-        return (AccessToken) super.type(type);
-    }
-
-    public Set<String> getAllowedOrigins() {
-        return allowedOrigins;
-    }
-
-    public void setAllowedOrigins(Set<String> allowedOrigins) {
-        this.allowedOrigins = allowedOrigins;
-    }
-
-    public Access getRealmAccess() {
-        return realmAccess;
-    }
-
-    public void setRealmAccess(Access realmAccess) {
-        this.realmAccess = realmAccess;
-    }
-
-    public Set<String> getTrustedCertificates() {
-        return trustedCertificates;
-    }
-
-    public void setTrustedCertificates(Set<String> trustedCertificates) {
-        this.trustedCertificates = trustedCertificates;
-    }
-
-    @Override
-    public AccessToken issuedFor(String issuedFor) {
-        return (AccessToken)super.issuedFor(issuedFor);
-    }
-
-
-}
+package org.keycloak.representations;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AccessToken extends IDToken {
+    public static class Access implements Serializable {
+        @JsonProperty("roles")
+        protected Set<String> roles;
+        @JsonProperty("verify_caller")
+        protected Boolean verifyCaller;
+
+        public Access() {
+        }
+
+        public Access clone() {
+            Access access = new Access();
+            access.verifyCaller = verifyCaller;
+            if (roles != null) {
+                access.roles = new HashSet<String>();
+                access.roles.addAll(roles);
+            }
+            return access;
+        }
+
+        public Set<String> getRoles() {
+            return roles;
+        }
+
+        public Access roles(Set<String> roles) {
+            this.roles = roles;
+            return this;
+        }
+
+        @JsonIgnore
+        public boolean isUserInRole(String role) {
+            if (roles == null) return false;
+            return roles.contains(role);
+        }
+
+        public Access addRole(String role) {
+            if (roles == null) roles = new HashSet<String>();
+            roles.add(role);
+            return this;
+        }
+
+        public Boolean getVerifyCaller() {
+            return verifyCaller;
+        }
+
+        public Access verifyCaller(Boolean required) {
+            this.verifyCaller = required;
+            return this;
+        }
+    }
+
+    @JsonProperty("client_session")
+    protected String clientSession;
+
+    @JsonProperty("trusted-certs")
+    protected Set<String> trustedCertificates;
+
+    @JsonProperty("allowed-origins")
+    protected Set<String> allowedOrigins;
+
+    @JsonProperty("realm_access")
+    protected Access realmAccess;
+
+    @JsonProperty("resource_access")
+    protected Map<String, Access> resourceAccess = new HashMap<String, Access>();
+
+    public Map<String, Access> getResourceAccess() {
+        return resourceAccess;
+    }
+
+    public void setResourceAccess(Map<String, Access> resourceAccess) {
+        this.resourceAccess = resourceAccess;
+    }
+
+
+
+
+    /**
+     * Does the realm require verifying the caller?
+     *
+     * @return
+     */
+    @JsonIgnore
+    public boolean isVerifyCaller() {
+        if (getRealmAccess() != null && getRealmAccess().getVerifyCaller() != null)
+            return getRealmAccess().getVerifyCaller().booleanValue();
+        return false;
+    }
+
+    /**
+     * Does the resource override the requirement of verifying the caller?
+     *
+     * @param resource
+     * @return
+     */
+    @JsonIgnore
+    public boolean isVerifyCaller(String resource) {
+        Access access = getResourceAccess(resource);
+        if (access != null && access.getVerifyCaller() != null) return access.getVerifyCaller().booleanValue();
+        return false;
+    }
+
+    @JsonIgnore
+    public Access getResourceAccess(String resource) {
+        return resourceAccess.get(resource);
+    }
+
+    public String getClientSession() {
+        return clientSession;
+    }
+
+    public Access addAccess(String service) {
+        Access access = resourceAccess.get(service);
+        if (access != null) return access;
+        access = new Access();
+        resourceAccess.put(service, access);
+        return access;
+    }
+
+    public AccessToken clientSession(String session) {
+        this.clientSession = session;
+        return this;
+    }
+
+    @Override
+    public AccessToken id(String id) {
+        return (AccessToken) super.id(id);
+    }
+
+    @Override
+    public AccessToken expiration(int expiration) {
+        return (AccessToken) super.expiration(expiration);
+    }
+
+    @Override
+    public AccessToken notBefore(int notBefore) {
+        return (AccessToken) super.notBefore(notBefore);
+    }
+
+
+    @Override
+    public AccessToken issuedAt(int issuedAt) {
+        return (AccessToken) super.issuedAt(issuedAt);
+    }
+
+    @Override
+    public AccessToken issuer(String issuer) {
+        return (AccessToken) super.issuer(issuer);
+    }
+
+    @Override
+    public AccessToken audience(String audience) {
+        return (AccessToken) super.audience(audience);
+    }
+
+    @Override
+    public AccessToken subject(String subject) {
+        return (AccessToken) super.subject(subject);
+    }
+
+    @Override
+    public AccessToken type(String type) {
+        return (AccessToken) super.type(type);
+    }
+
+    public Set<String> getAllowedOrigins() {
+        return allowedOrigins;
+    }
+
+    public void setAllowedOrigins(Set<String> allowedOrigins) {
+        this.allowedOrigins = allowedOrigins;
+    }
+
+    public Access getRealmAccess() {
+        return realmAccess;
+    }
+
+    public void setRealmAccess(Access realmAccess) {
+        this.realmAccess = realmAccess;
+    }
+
+    public Set<String> getTrustedCertificates() {
+        return trustedCertificates;
+    }
+
+    public void setTrustedCertificates(Set<String> trustedCertificates) {
+        this.trustedCertificates = trustedCertificates;
+    }
+
+    @Override
+    public AccessToken issuedFor(String issuedFor) {
+        return (AccessToken)super.issuedFor(issuedFor);
+    }
+
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/action/AdminAction.java b/core/src/main/java/org/keycloak/representations/adapters/action/AdminAction.java
index 1708594..fd9dad0 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/action/AdminAction.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/action/AdminAction.java
@@ -1,71 +1,71 @@
-package org.keycloak.representations.adapters.action;
-
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.keycloak.util.Time;
-
-/**
- * Posted to managed client from admin server.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AdminAction {
-    protected String id;
-    protected int expiration;
-    protected String resource;
-    protected String action;
-
-    public AdminAction() {
-    }
-
-    public AdminAction(String id, int expiration, String resource, String action) {
-        this.id = id;
-        this.expiration = expiration;
-        this.resource = resource;
-        this.action = action;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    @JsonIgnore
-    public boolean isExpired() {
-        return Time.currentTime() > expiration;
-    }
-
-    /**
-     * Time in seconds since epoc
-     *
-     * @return
-     */
-    public int getExpiration() {
-        return expiration;
-    }
-
-    public void setExpiration(int expiration) {
-        this.expiration = expiration;
-    }
-
-    public String getResource() {
-        return resource;
-    }
-
-    public void setResource(String resource) {
-        this.resource = resource;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public abstract boolean validate();
-}
+package org.keycloak.representations.adapters.action;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.keycloak.util.Time;
+
+/**
+ * Posted to managed client from admin server.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AdminAction {
+    protected String id;
+    protected int expiration;
+    protected String resource;
+    protected String action;
+
+    public AdminAction() {
+    }
+
+    public AdminAction(String id, int expiration, String resource, String action) {
+        this.id = id;
+        this.expiration = expiration;
+        this.resource = resource;
+        this.action = action;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @JsonIgnore
+    public boolean isExpired() {
+        return Time.currentTime() > expiration;
+    }
+
+    /**
+     * Time in seconds since epoc
+     *
+     * @return
+     */
+    public int getExpiration() {
+        return expiration;
+    }
+
+    public void setExpiration(int expiration) {
+        this.expiration = expiration;
+    }
+
+    public String getResource() {
+        return resource;
+    }
+
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public abstract boolean validate();
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/action/LogoutAction.java b/core/src/main/java/org/keycloak/representations/adapters/action/LogoutAction.java
index f85020e..bd82fdc 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/action/LogoutAction.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/action/LogoutAction.java
@@ -1,50 +1,50 @@
-package org.keycloak.representations.adapters.action;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class LogoutAction extends AdminAction {
-    public static final String LOGOUT = "LOGOUT";
-    protected List<String> adapterSessionIds;
-    protected int notBefore;
-    protected List<String> keycloakSessionIds;
-
-    public LogoutAction() {
-    }
-
-    public LogoutAction(String id, int expiration, String resource, List<String> adapterSessionIds, int notBefore, List<String> keycloakSessionIds) {
-        super(id, expiration, resource, LOGOUT);
-        this.adapterSessionIds = adapterSessionIds;
-        this.notBefore = notBefore;
-        this.keycloakSessionIds = keycloakSessionIds;
-    }
-
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public List<String> getAdapterSessionIds() {
-        return adapterSessionIds;
-    }
-
-    public List<String> getKeycloakSessionIds() {
-        return keycloakSessionIds;
-    }
-
-    public void setKeycloakSessionIds(List<String> keycloakSessionIds) {
-        this.keycloakSessionIds = keycloakSessionIds;
-    }
-
-    @Override
-    public boolean validate() {
-        return LOGOUT.equals(action);
-    }
-}
+package org.keycloak.representations.adapters.action;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class LogoutAction extends AdminAction {
+    public static final String LOGOUT = "LOGOUT";
+    protected List<String> adapterSessionIds;
+    protected int notBefore;
+    protected List<String> keycloakSessionIds;
+
+    public LogoutAction() {
+    }
+
+    public LogoutAction(String id, int expiration, String resource, List<String> adapterSessionIds, int notBefore, List<String> keycloakSessionIds) {
+        super(id, expiration, resource, LOGOUT);
+        this.adapterSessionIds = adapterSessionIds;
+        this.notBefore = notBefore;
+        this.keycloakSessionIds = keycloakSessionIds;
+    }
+
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public List<String> getAdapterSessionIds() {
+        return adapterSessionIds;
+    }
+
+    public List<String> getKeycloakSessionIds() {
+        return keycloakSessionIds;
+    }
+
+    public void setKeycloakSessionIds(List<String> keycloakSessionIds) {
+        this.keycloakSessionIds = keycloakSessionIds;
+    }
+
+    @Override
+    public boolean validate() {
+        return LOGOUT.equals(action);
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/action/PushNotBeforeAction.java b/core/src/main/java/org/keycloak/representations/adapters/action/PushNotBeforeAction.java
index d11a624..9035182 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/action/PushNotBeforeAction.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/action/PushNotBeforeAction.java
@@ -1,33 +1,33 @@
-package org.keycloak.representations.adapters.action;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class PushNotBeforeAction extends AdminAction {
-
-    public static final String PUSH_NOT_BEFORE = "PUSH_NOT_BEFORE";
-    protected int notBefore;
-
-    public PushNotBeforeAction() {
-    }
-
-    public PushNotBeforeAction(String id, int expiration, String resource, int notBefore) {
-        super(id, expiration, resource, PUSH_NOT_BEFORE);
-        this.notBefore = notBefore;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    @Override
-    public boolean validate() {
-        return PUSH_NOT_BEFORE.equals(action);
-    }
-
-}
+package org.keycloak.representations.adapters.action;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class PushNotBeforeAction extends AdminAction {
+
+    public static final String PUSH_NOT_BEFORE = "PUSH_NOT_BEFORE";
+    protected int notBefore;
+
+    public PushNotBeforeAction() {
+    }
+
+    public PushNotBeforeAction(String id, int expiration, String resource, int notBefore) {
+        super(id, expiration, resource, PUSH_NOT_BEFORE);
+        this.notBefore = notBefore;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    @Override
+    public boolean validate() {
+        return PUSH_NOT_BEFORE.equals(action);
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
index c165161..f0afddf 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
@@ -1,165 +1,165 @@
-package org.keycloak.representations.adapters.config;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonPropertyOrder;
-
-/**
- * Configuration for Java based adapters
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
-        "resource", "public-client", "credentials",
-        "use-resource-role-mappings",
-        "enable-cors", "cors-max-age", "cors-allowed-methods",
-        "expose-token", "bearer-only",
-        "connection-pool-size",
-        "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
-        "client-keystore", "client-keystore-password", "client-key-password",
-        "auth-server-url-for-backend-requests", "always-refresh-token",
-        "register-node-at-startup", "register-node-period", "token-store", "principal-attribute"
-})
-public class AdapterConfig extends BaseAdapterConfig {
-
-    @JsonProperty("allow-any-hostname")
-    protected boolean allowAnyHostname;
-    @JsonProperty("disable-trust-manager")
-    protected boolean disableTrustManager;
-    @JsonProperty("truststore")
-    protected String truststore;
-    @JsonProperty("truststore-password")
-    protected String truststorePassword;
-    @JsonProperty("client-keystore")
-    protected String clientKeystore;
-    @JsonProperty("client-keystore-password")
-    protected String clientKeystorePassword;
-    @JsonProperty("client-key-password")
-    protected String clientKeyPassword;
-    @JsonProperty("connection-pool-size")
-    protected int connectionPoolSize = 20;
-    @JsonProperty("auth-server-url-for-backend-requests")
-    protected String authServerUrlForBackendRequests;
-    @JsonProperty("always-refresh-token")
-    protected boolean alwaysRefreshToken = false;
-    @JsonProperty("register-node-at-startup")
-    protected boolean registerNodeAtStartup = false;
-    @JsonProperty("register-node-period")
-    protected int registerNodePeriod = -1;
-    @JsonProperty("token-store")
-    protected String tokenStore;
-    @JsonProperty("principal-attribute")
-    protected String principalAttribute;
-
-    public boolean isAllowAnyHostname() {
-        return allowAnyHostname;
-    }
-
-    public void setAllowAnyHostname(boolean allowAnyHostname) {
-        this.allowAnyHostname = allowAnyHostname;
-    }
-
-    public boolean isDisableTrustManager() {
-        return disableTrustManager;
-    }
-
-    public void setDisableTrustManager(boolean disableTrustManager) {
-        this.disableTrustManager = disableTrustManager;
-    }
-
-    public String getTruststore() {
-        return truststore;
-    }
-
-    public void setTruststore(String truststore) {
-        this.truststore = truststore;
-    }
-
-    public String getTruststorePassword() {
-        return truststorePassword;
-    }
-
-    public void setTruststorePassword(String truststorePassword) {
-        this.truststorePassword = truststorePassword;
-    }
-
-    public String getClientKeystore() {
-        return clientKeystore;
-    }
-
-    public void setClientKeystore(String clientKeystore) {
-        this.clientKeystore = clientKeystore;
-    }
-
-    public String getClientKeystorePassword() {
-        return clientKeystorePassword;
-    }
-
-    public void setClientKeystorePassword(String clientKeystorePassword) {
-        this.clientKeystorePassword = clientKeystorePassword;
-    }
-
-    public String getClientKeyPassword() {
-        return clientKeyPassword;
-    }
-
-    public void setClientKeyPassword(String clientKeyPassword) {
-        this.clientKeyPassword = clientKeyPassword;
-    }
-
-    public int getConnectionPoolSize() {
-        return connectionPoolSize;
-    }
-
-    public void setConnectionPoolSize(int connectionPoolSize) {
-        this.connectionPoolSize = connectionPoolSize;
-    }
-
-    public String getAuthServerUrlForBackendRequests() {
-        return authServerUrlForBackendRequests;
-    }
-
-    public void setAuthServerUrlForBackendRequests(String authServerUrlForBackendRequests) {
-        this.authServerUrlForBackendRequests = authServerUrlForBackendRequests;
-    }
-
-    public boolean isAlwaysRefreshToken() {
-        return alwaysRefreshToken;
-    }
-
-    public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
-        this.alwaysRefreshToken = alwaysRefreshToken;
-    }
-
-    public boolean isRegisterNodeAtStartup() {
-        return registerNodeAtStartup;
-    }
-
-    public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
-        this.registerNodeAtStartup = registerNodeAtStartup;
-    }
-
-    public int getRegisterNodePeriod() {
-        return registerNodePeriod;
-    }
-
-    public void setRegisterNodePeriod(int registerNodePeriod) {
-        this.registerNodePeriod = registerNodePeriod;
-    }
-
-    public String getTokenStore() {
-        return tokenStore;
-    }
-
-    public void setTokenStore(String tokenStore) {
-        this.tokenStore = tokenStore;
-    }
-
-    public String getPrincipalAttribute() {
-        return principalAttribute;
-    }
-
-    public void setPrincipalAttribute(String principalAttribute) {
-        this.principalAttribute = principalAttribute;
-    }
-}
+package org.keycloak.representations.adapters.config;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonPropertyOrder;
+
+/**
+ * Configuration for Java based adapters
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
+        "resource", "public-client", "credentials",
+        "use-resource-role-mappings",
+        "enable-cors", "cors-max-age", "cors-allowed-methods",
+        "expose-token", "bearer-only",
+        "connection-pool-size",
+        "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
+        "client-keystore", "client-keystore-password", "client-key-password",
+        "auth-server-url-for-backend-requests", "always-refresh-token",
+        "register-node-at-startup", "register-node-period", "token-store", "principal-attribute"
+})
+public class AdapterConfig extends BaseAdapterConfig {
+
+    @JsonProperty("allow-any-hostname")
+    protected boolean allowAnyHostname;
+    @JsonProperty("disable-trust-manager")
+    protected boolean disableTrustManager;
+    @JsonProperty("truststore")
+    protected String truststore;
+    @JsonProperty("truststore-password")
+    protected String truststorePassword;
+    @JsonProperty("client-keystore")
+    protected String clientKeystore;
+    @JsonProperty("client-keystore-password")
+    protected String clientKeystorePassword;
+    @JsonProperty("client-key-password")
+    protected String clientKeyPassword;
+    @JsonProperty("connection-pool-size")
+    protected int connectionPoolSize = 20;
+    @JsonProperty("auth-server-url-for-backend-requests")
+    protected String authServerUrlForBackendRequests;
+    @JsonProperty("always-refresh-token")
+    protected boolean alwaysRefreshToken = false;
+    @JsonProperty("register-node-at-startup")
+    protected boolean registerNodeAtStartup = false;
+    @JsonProperty("register-node-period")
+    protected int registerNodePeriod = -1;
+    @JsonProperty("token-store")
+    protected String tokenStore;
+    @JsonProperty("principal-attribute")
+    protected String principalAttribute;
+
+    public boolean isAllowAnyHostname() {
+        return allowAnyHostname;
+    }
+
+    public void setAllowAnyHostname(boolean allowAnyHostname) {
+        this.allowAnyHostname = allowAnyHostname;
+    }
+
+    public boolean isDisableTrustManager() {
+        return disableTrustManager;
+    }
+
+    public void setDisableTrustManager(boolean disableTrustManager) {
+        this.disableTrustManager = disableTrustManager;
+    }
+
+    public String getTruststore() {
+        return truststore;
+    }
+
+    public void setTruststore(String truststore) {
+        this.truststore = truststore;
+    }
+
+    public String getTruststorePassword() {
+        return truststorePassword;
+    }
+
+    public void setTruststorePassword(String truststorePassword) {
+        this.truststorePassword = truststorePassword;
+    }
+
+    public String getClientKeystore() {
+        return clientKeystore;
+    }
+
+    public void setClientKeystore(String clientKeystore) {
+        this.clientKeystore = clientKeystore;
+    }
+
+    public String getClientKeystorePassword() {
+        return clientKeystorePassword;
+    }
+
+    public void setClientKeystorePassword(String clientKeystorePassword) {
+        this.clientKeystorePassword = clientKeystorePassword;
+    }
+
+    public String getClientKeyPassword() {
+        return clientKeyPassword;
+    }
+
+    public void setClientKeyPassword(String clientKeyPassword) {
+        this.clientKeyPassword = clientKeyPassword;
+    }
+
+    public int getConnectionPoolSize() {
+        return connectionPoolSize;
+    }
+
+    public void setConnectionPoolSize(int connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+    }
+
+    public String getAuthServerUrlForBackendRequests() {
+        return authServerUrlForBackendRequests;
+    }
+
+    public void setAuthServerUrlForBackendRequests(String authServerUrlForBackendRequests) {
+        this.authServerUrlForBackendRequests = authServerUrlForBackendRequests;
+    }
+
+    public boolean isAlwaysRefreshToken() {
+        return alwaysRefreshToken;
+    }
+
+    public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
+        this.alwaysRefreshToken = alwaysRefreshToken;
+    }
+
+    public boolean isRegisterNodeAtStartup() {
+        return registerNodeAtStartup;
+    }
+
+    public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
+        this.registerNodeAtStartup = registerNodeAtStartup;
+    }
+
+    public int getRegisterNodePeriod() {
+        return registerNodePeriod;
+    }
+
+    public void setRegisterNodePeriod(int registerNodePeriod) {
+        this.registerNodePeriod = registerNodePeriod;
+    }
+
+    public String getTokenStore() {
+        return tokenStore;
+    }
+
+    public void setTokenStore(String tokenStore) {
+        this.tokenStore = tokenStore;
+    }
+
+    public String getPrincipalAttribute() {
+        return principalAttribute;
+    }
+
+    public void setPrincipalAttribute(String principalAttribute) {
+        this.principalAttribute = principalAttribute;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
index 676a103..608cbaa 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java
@@ -1,132 +1,132 @@
-package org.keycloak.representations.adapters.config;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonPropertyOrder;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Common Adapter configuration
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
-        "resource", "public-client", "credentials",
-        "use-resource-role-mappings",
-        "enable-cors", "cors-max-age", "cors-allowed-methods",
-        "expose-token", "bearer-only", "enable-basic-auth"})
-public class BaseAdapterConfig extends BaseRealmConfig {
-    @JsonProperty("resource")
-    protected String resource;
-    @JsonProperty("use-resource-role-mappings")
-    protected boolean useResourceRoleMappings;
-    @JsonProperty("enable-cors")
-    protected boolean cors;
-    @JsonProperty("cors-max-age")
-    protected int corsMaxAge = -1;
-    @JsonProperty("cors-allowed-headers")
-    protected String corsAllowedHeaders;
-    @JsonProperty("cors-allowed-methods")
-    protected String corsAllowedMethods;
-    @JsonProperty("expose-token")
-    protected boolean exposeToken;
-    @JsonProperty("bearer-only")
-    protected boolean bearerOnly;
-    @JsonProperty("enable-basic-auth")
-    protected boolean enableBasicAuth;
-    @JsonProperty("public-client")
-    protected boolean publicClient;
-    @JsonProperty("credentials")
-    protected Map<String, String> credentials = new HashMap<String, String>();
-
-
-    public boolean isUseResourceRoleMappings() {
-        return useResourceRoleMappings;
-    }
-
-    public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
-        this.useResourceRoleMappings = useResourceRoleMappings;
-    }
-
-    public String getResource() {
-        return resource;
-    }
-
-    public void setResource(String resource) {
-        this.resource = resource;
-    }
-
-    public boolean isCors() {
-         return cors;
-     }
-
-    public void setCors(boolean cors) {
-         this.cors = cors;
-     }
-
-    public int getCorsMaxAge() {
-         return corsMaxAge;
-     }
-
-    public void setCorsMaxAge(int corsMaxAge) {
-         this.corsMaxAge = corsMaxAge;
-     }
-
-    public String getCorsAllowedHeaders() {
-         return corsAllowedHeaders;
-     }
-
-    public void setCorsAllowedHeaders(String corsAllowedHeaders) {
-         this.corsAllowedHeaders = corsAllowedHeaders;
-     }
-
-    public String getCorsAllowedMethods() {
-         return corsAllowedMethods;
-     }
-
-    public void setCorsAllowedMethods(String corsAllowedMethods) {
-         this.corsAllowedMethods = corsAllowedMethods;
-     }
-
-    public boolean isExposeToken() {
-         return exposeToken;
-     }
-
-    public void setExposeToken(boolean exposeToken) {
-         this.exposeToken = exposeToken;
-     }
-
-    public boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public void setBearerOnly(boolean bearerOnly) {
-        this.bearerOnly = bearerOnly;
-    }
-
-    public boolean isEnableBasicAuth() {
-        return enableBasicAuth;
-    }
-
-    public void setEnableBasicAuth(boolean enableBasicAuth) {
-        this.enableBasicAuth = enableBasicAuth;
-    }
-
-    public Map<String, String> getCredentials() {
-        return credentials;
-    }
-
-    public void setCredentials(Map<String, String> credentials) {
-        this.credentials = credentials;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-}
+package org.keycloak.representations.adapters.config;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonPropertyOrder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Common Adapter configuration
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
+        "resource", "public-client", "credentials",
+        "use-resource-role-mappings",
+        "enable-cors", "cors-max-age", "cors-allowed-methods",
+        "expose-token", "bearer-only", "enable-basic-auth"})
+public class BaseAdapterConfig extends BaseRealmConfig {
+    @JsonProperty("resource")
+    protected String resource;
+    @JsonProperty("use-resource-role-mappings")
+    protected boolean useResourceRoleMappings;
+    @JsonProperty("enable-cors")
+    protected boolean cors;
+    @JsonProperty("cors-max-age")
+    protected int corsMaxAge = -1;
+    @JsonProperty("cors-allowed-headers")
+    protected String corsAllowedHeaders;
+    @JsonProperty("cors-allowed-methods")
+    protected String corsAllowedMethods;
+    @JsonProperty("expose-token")
+    protected boolean exposeToken;
+    @JsonProperty("bearer-only")
+    protected boolean bearerOnly;
+    @JsonProperty("enable-basic-auth")
+    protected boolean enableBasicAuth;
+    @JsonProperty("public-client")
+    protected boolean publicClient;
+    @JsonProperty("credentials")
+    protected Map<String, String> credentials = new HashMap<String, String>();
+
+
+    public boolean isUseResourceRoleMappings() {
+        return useResourceRoleMappings;
+    }
+
+    public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
+        this.useResourceRoleMappings = useResourceRoleMappings;
+    }
+
+    public String getResource() {
+        return resource;
+    }
+
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
+
+    public boolean isCors() {
+         return cors;
+     }
+
+    public void setCors(boolean cors) {
+         this.cors = cors;
+     }
+
+    public int getCorsMaxAge() {
+         return corsMaxAge;
+     }
+
+    public void setCorsMaxAge(int corsMaxAge) {
+         this.corsMaxAge = corsMaxAge;
+     }
+
+    public String getCorsAllowedHeaders() {
+         return corsAllowedHeaders;
+     }
+
+    public void setCorsAllowedHeaders(String corsAllowedHeaders) {
+         this.corsAllowedHeaders = corsAllowedHeaders;
+     }
+
+    public String getCorsAllowedMethods() {
+         return corsAllowedMethods;
+     }
+
+    public void setCorsAllowedMethods(String corsAllowedMethods) {
+         this.corsAllowedMethods = corsAllowedMethods;
+     }
+
+    public boolean isExposeToken() {
+         return exposeToken;
+     }
+
+    public void setExposeToken(boolean exposeToken) {
+         this.exposeToken = exposeToken;
+     }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isEnableBasicAuth() {
+        return enableBasicAuth;
+    }
+
+    public void setEnableBasicAuth(boolean enableBasicAuth) {
+        this.enableBasicAuth = enableBasicAuth;
+    }
+
+    public Map<String, String> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(Map<String, String> credentials) {
+        this.credentials = credentials;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java
index 4fe3905..ae8b482 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java
@@ -1,54 +1,54 @@
-package org.keycloak.representations.adapters.config;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonPropertyOrder;
-
-/**
- * Common Realm Configuration
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required"})
-public class BaseRealmConfig {
-    @JsonProperty("realm")
-    protected String realm;
-    @JsonProperty("realm-public-key")
-    protected String realmKey;
-    @JsonProperty("auth-server-url")
-    protected String authServerUrl;
-    @JsonProperty("ssl-required")
-    protected String sslRequired;
-
-    public String getSslRequired() {
-        return sslRequired;
-    }
-
-    public void setSslRequired(String sslRequired) {
-        this.sslRequired = sslRequired;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public void setRealm(String realm) {
-        this.realm = realm;
-    }
-
-    public String getRealmKey() {
-        return realmKey;
-    }
-
-    public void setRealmKey(String realmKey) {
-        this.realmKey = realmKey;
-    }
-
-    public String getAuthServerUrl() {
-        return authServerUrl;
-    }
-
-    public void setAuthServerUrl(String authServerUrl) {
-        this.authServerUrl = authServerUrl;
-    }
-}
+package org.keycloak.representations.adapters.config;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonPropertyOrder;
+
+/**
+ * Common Realm Configuration
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required"})
+public class BaseRealmConfig {
+    @JsonProperty("realm")
+    protected String realm;
+    @JsonProperty("realm-public-key")
+    protected String realmKey;
+    @JsonProperty("auth-server-url")
+    protected String authServerUrl;
+    @JsonProperty("ssl-required")
+    protected String sslRequired;
+
+    public String getSslRequired() {
+        return sslRequired;
+    }
+
+    public void setSslRequired(String sslRequired) {
+        this.sslRequired = sslRequired;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+
+    public String getRealmKey() {
+        return realmKey;
+    }
+
+    public void setRealmKey(String realmKey) {
+        this.realmKey = realmKey;
+    }
+
+    public String getAuthServerUrl() {
+        return authServerUrl;
+    }
+
+    public void setAuthServerUrl(String authServerUrl) {
+        this.authServerUrl = authServerUrl;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/AddressClaimSet.java b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java
index 3805f6e..2c09c73 100755
--- a/core/src/main/java/org/keycloak/representations/AddressClaimSet.java
+++ b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java
@@ -1,83 +1,83 @@
-package org.keycloak.representations;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class AddressClaimSet {
-    public static final String FORMATTED = "formatted";
-    public static final String STREET_ADDRESS = "street_address";
-    public static final String LOCALITY = "locality";
-    public static final String REGION = "region";
-    public static final String POSTAL_CODE = "postal_code";
-    public static final String COUNTRY = "country";
-
-    @JsonProperty(FORMATTED)
-    protected String formattedAddress;
-
-    @JsonProperty(STREET_ADDRESS)
-    protected String streetAddress;
-
-    @JsonProperty(LOCALITY)
-    protected String locality;
-
-    @JsonProperty(REGION)
-    protected String region;
-
-    @JsonProperty(POSTAL_CODE)
-    protected String postalCode;
-
-    @JsonProperty(COUNTRY)
-    protected String country;
-
-    public String getFormattedAddress() {
-        return this.formattedAddress;
-    }
-
-    public void setFormattedAddress(String formattedAddress) {
-        this.formattedAddress = formattedAddress;
-    }
-
-    public String getStreetAddress() {
-        return this.streetAddress;
-    }
-
-    public void setStreetAddress(String streetAddress) {
-        this.streetAddress = streetAddress;
-    }
-
-    public String getLocality() {
-        return this.locality;
-    }
-
-    public void setLocality(String locality) {
-        this.locality = locality;
-    }
-
-    public String getRegion() {
-        return this.region;
-    }
-
-    public void setRegion(String region) {
-        this.region = region;
-    }
-
-    public String getPostalCode() {
-        return this.postalCode;
-    }
-
-    public void setPostalCode(String postalCode) {
-        this.postalCode = postalCode;
-    }
-
-    public String getCountry() {
-        return this.country;
-    }
-
-    public void setCountry(String country) {
-        this.country = country;
-    }
-
-}
+package org.keycloak.representations;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class AddressClaimSet {
+    public static final String FORMATTED = "formatted";
+    public static final String STREET_ADDRESS = "street_address";
+    public static final String LOCALITY = "locality";
+    public static final String REGION = "region";
+    public static final String POSTAL_CODE = "postal_code";
+    public static final String COUNTRY = "country";
+
+    @JsonProperty(FORMATTED)
+    protected String formattedAddress;
+
+    @JsonProperty(STREET_ADDRESS)
+    protected String streetAddress;
+
+    @JsonProperty(LOCALITY)
+    protected String locality;
+
+    @JsonProperty(REGION)
+    protected String region;
+
+    @JsonProperty(POSTAL_CODE)
+    protected String postalCode;
+
+    @JsonProperty(COUNTRY)
+    protected String country;
+
+    public String getFormattedAddress() {
+        return this.formattedAddress;
+    }
+
+    public void setFormattedAddress(String formattedAddress) {
+        this.formattedAddress = formattedAddress;
+    }
+
+    public String getStreetAddress() {
+        return this.streetAddress;
+    }
+
+    public void setStreetAddress(String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getLocality() {
+        return this.locality;
+    }
+
+    public void setLocality(String locality) {
+        this.locality = locality;
+    }
+
+    public String getRegion() {
+        return this.region;
+    }
+
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    public String getPostalCode() {
+        return this.postalCode;
+    }
+
+    public void setPostalCode(String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return this.country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java
index 89b2c41..643170f 100755
--- a/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java
@@ -1,87 +1,87 @@
-package org.keycloak.representations.idm;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class AuthenticationExecutionRepresentation implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String authenticatorConfig;
-    private String authenticator;
-    private String flowAlias;
-    private boolean autheticatorFlow;
-    private String requirement;
-    private boolean userSetupAllowed;
-    private int priority;
-
-    public String getAuthenticatorConfig() {
-        return authenticatorConfig;
-    }
-
-    public void setAuthenticatorConfig(String authenticatorConfig) {
-        this.authenticatorConfig = authenticatorConfig;
-    }
-
-    public String getAuthenticator() {
-        return authenticator;
-    }
-
-    public void setAuthenticator(String authenticator) {
-        this.authenticator = authenticator;
-    }
-
-    public String getRequirement() {
-        return requirement;
-    }
-
-    public void setRequirement(String requirement) {
-        this.requirement = requirement;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public boolean isUserSetupAllowed() {
-        return userSetupAllowed;
-    }
-
-    public void setUserSetupAllowed(boolean userSetupAllowed) {
-        this.userSetupAllowed = userSetupAllowed;
-    }
-
-    /**
-     * If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel
-     *
-     * @return
-     */
-    public String getFlowAlias() {
-        return flowAlias;
-    }
-
-    public void setFlowAlias(String flowId) {
-        this.flowAlias = flowId;
-    }
-
-    /**
-     * Is the referenced authenticator a flow?
-     *
-     * @return
-     */
-    public boolean isAutheticatorFlow() {
-        return autheticatorFlow;
-    }
-
-    public void setAutheticatorFlow(boolean autheticatorFlow) {
-        this.autheticatorFlow = autheticatorFlow;
-    }
-
-}
+package org.keycloak.representations.idm;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class AuthenticationExecutionRepresentation implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String authenticatorConfig;
+    private String authenticator;
+    private String flowAlias;
+    private boolean autheticatorFlow;
+    private String requirement;
+    private boolean userSetupAllowed;
+    private int priority;
+
+    public String getAuthenticatorConfig() {
+        return authenticatorConfig;
+    }
+
+    public void setAuthenticatorConfig(String authenticatorConfig) {
+        this.authenticatorConfig = authenticatorConfig;
+    }
+
+    public String getAuthenticator() {
+        return authenticator;
+    }
+
+    public void setAuthenticator(String authenticator) {
+        this.authenticator = authenticator;
+    }
+
+    public String getRequirement() {
+        return requirement;
+    }
+
+    public void setRequirement(String requirement) {
+        this.requirement = requirement;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public boolean isUserSetupAllowed() {
+        return userSetupAllowed;
+    }
+
+    public void setUserSetupAllowed(boolean userSetupAllowed) {
+        this.userSetupAllowed = userSetupAllowed;
+    }
+
+    /**
+     * If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel
+     *
+     * @return
+     */
+    public String getFlowAlias() {
+        return flowAlias;
+    }
+
+    public void setFlowAlias(String flowId) {
+        this.flowAlias = flowId;
+    }
+
+    /**
+     * Is the referenced authenticator a flow?
+     *
+     * @return
+     */
+    public boolean isAutheticatorFlow() {
+        return autheticatorFlow;
+    }
+
+    public void setAutheticatorFlow(boolean autheticatorFlow) {
+        this.autheticatorFlow = autheticatorFlow;
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java
index e7bd3a0..f8ba6a8 100755
--- a/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java
@@ -1,67 +1,67 @@
-package org.keycloak.representations.idm;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationFlowRepresentation implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String alias;
-    private String description;
-    private String providerId;
-    private boolean topLevel;
-    private boolean builtIn;
-    protected List<AuthenticationExecutionRepresentation> authenticationExecutions;
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public boolean isTopLevel() {
-        return topLevel;
-    }
-
-    public void setTopLevel(boolean topLevel) {
-        this.topLevel = topLevel;
-    }
-
-    public boolean isBuiltIn() {
-        return builtIn;
-    }
-
-    public void setBuiltIn(boolean builtIn) {
-        this.builtIn = builtIn;
-    }
-
-    public List<AuthenticationExecutionRepresentation> getAuthenticationExecutions() {
-        return authenticationExecutions;
-    }
-
-    public void setAuthenticationExecutions(List<AuthenticationExecutionRepresentation> authenticationExecutions) {
-        this.authenticationExecutions = authenticationExecutions;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationFlowRepresentation implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String alias;
+    private String description;
+    private String providerId;
+    private boolean topLevel;
+    private boolean builtIn;
+    protected List<AuthenticationExecutionRepresentation> authenticationExecutions;
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public boolean isTopLevel() {
+        return topLevel;
+    }
+
+    public void setTopLevel(boolean topLevel) {
+        this.topLevel = topLevel;
+    }
+
+    public boolean isBuiltIn() {
+        return builtIn;
+    }
+
+    public void setBuiltIn(boolean builtIn) {
+        this.builtIn = builtIn;
+    }
+
+    public List<AuthenticationExecutionRepresentation> getAuthenticationExecutions() {
+        return authenticationExecutions;
+    }
+
+    public void setAuthenticationExecutions(List<AuthenticationExecutionRepresentation> authenticationExecutions) {
+        this.authenticationExecutions = authenticationExecutions;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java
index e3e292b..1f0b3ad 100755
--- a/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java
@@ -1,35 +1,35 @@
-package org.keycloak.representations.idm;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class AuthenticatorConfigRepresentation implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String alias;
-    private Map<String, String> config = new HashMap<String, String>();
-
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class AuthenticatorConfigRepresentation implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String alias;
+    private Map<String, String> config = new HashMap<String, String>();
+
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java
index 9d3aed1..14e651e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java
@@ -1,134 +1,134 @@
-package org.keycloak.representations.idm;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClaimRepresentation {
-    protected boolean name;
-    protected boolean username;
-    protected boolean profile;
-    protected boolean picture;
-    protected boolean website;
-    protected boolean email;
-    protected boolean gender;
-    protected boolean locale;
-    protected boolean address;
-    protected boolean phone;
-
-    public boolean getName() {
-        return name;
-    }
-
-    public void setName(boolean name) {
-        this.name = name;
-    }
-
-    public boolean getUsername() {
-        return username;
-    }
-
-    public void setUsername(boolean username) {
-        this.username = username;
-    }
-
-    public boolean getProfile() {
-        return profile;
-    }
-
-    public void setProfile(boolean profile) {
-        this.profile = profile;
-    }
-
-    public boolean getPicture() {
-        return picture;
-    }
-
-    public void setPicture(boolean picture) {
-        this.picture = picture;
-    }
-
-    public boolean getWebsite() {
-        return website;
-    }
-
-    public void setWebsite(boolean website) {
-        this.website = website;
-    }
-
-    public boolean getEmail() {
-        return email;
-    }
-
-    public void setEmail(boolean email) {
-        this.email = email;
-    }
-
-    public boolean getGender() {
-        return gender;
-    }
-
-    public void setGender(boolean gender) {
-        this.gender = gender;
-    }
-
-    public boolean getLocale() {
-        return locale;
-    }
-
-    public void setLocale(boolean locale) {
-        this.locale = locale;
-    }
-
-    public boolean getAddress() {
-        return address;
-    }
-
-    public void setAddress(boolean address) {
-        this.address = address;
-    }
-
-    public boolean getPhone() {
-        return phone;
-    }
-
-    public void setPhone(boolean phone) {
-        this.phone = phone;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ClaimRepresentation that = (ClaimRepresentation) o;
-
-        if (address != that.address) return false;
-        if (email != that.email) return false;
-        if (gender != that.gender) return false;
-        if (locale != that.locale) return false;
-        if (name != that.name) return false;
-        if (phone != that.phone) return false;
-        if (picture != that.picture) return false;
-        if (profile != that.profile) return false;
-        if (username != that.username) return false;
-        if (website != that.website) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = (name ? 1 : 0);
-        result = 31 * result + (username ? 1 : 0);
-        result = 31 * result + (profile ? 1 : 0);
-        result = 31 * result + (picture ? 1 : 0);
-        result = 31 * result + (website ? 1 : 0);
-        result = 31 * result + (email ? 1 : 0);
-        result = 31 * result + (gender ? 1 : 0);
-        result = 31 * result + (locale ? 1 : 0);
-        result = 31 * result + (address ? 1 : 0);
-        result = 31 * result + (phone ? 1 : 0);
-        return result;
-    }
-}
+package org.keycloak.representations.idm;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClaimRepresentation {
+    protected boolean name;
+    protected boolean username;
+    protected boolean profile;
+    protected boolean picture;
+    protected boolean website;
+    protected boolean email;
+    protected boolean gender;
+    protected boolean locale;
+    protected boolean address;
+    protected boolean phone;
+
+    public boolean getName() {
+        return name;
+    }
+
+    public void setName(boolean name) {
+        this.name = name;
+    }
+
+    public boolean getUsername() {
+        return username;
+    }
+
+    public void setUsername(boolean username) {
+        this.username = username;
+    }
+
+    public boolean getProfile() {
+        return profile;
+    }
+
+    public void setProfile(boolean profile) {
+        this.profile = profile;
+    }
+
+    public boolean getPicture() {
+        return picture;
+    }
+
+    public void setPicture(boolean picture) {
+        this.picture = picture;
+    }
+
+    public boolean getWebsite() {
+        return website;
+    }
+
+    public void setWebsite(boolean website) {
+        this.website = website;
+    }
+
+    public boolean getEmail() {
+        return email;
+    }
+
+    public void setEmail(boolean email) {
+        this.email = email;
+    }
+
+    public boolean getGender() {
+        return gender;
+    }
+
+    public void setGender(boolean gender) {
+        this.gender = gender;
+    }
+
+    public boolean getLocale() {
+        return locale;
+    }
+
+    public void setLocale(boolean locale) {
+        this.locale = locale;
+    }
+
+    public boolean getAddress() {
+        return address;
+    }
+
+    public void setAddress(boolean address) {
+        this.address = address;
+    }
+
+    public boolean getPhone() {
+        return phone;
+    }
+
+    public void setPhone(boolean phone) {
+        this.phone = phone;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClaimRepresentation that = (ClaimRepresentation) o;
+
+        if (address != that.address) return false;
+        if (email != that.email) return false;
+        if (gender != that.gender) return false;
+        if (locale != that.locale) return false;
+        if (name != that.name) return false;
+        if (phone != that.phone) return false;
+        if (picture != that.picture) return false;
+        if (profile != that.profile) return false;
+        if (username != that.username) return false;
+        if (website != that.website) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = (name ? 1 : 0);
+        result = 31 * result + (username ? 1 : 0);
+        result = 31 * result + (profile ? 1 : 0);
+        result = 31 * result + (picture ? 1 : 0);
+        result = 31 * result + (website ? 1 : 0);
+        result = 31 * result + (email ? 1 : 0);
+        result = 31 * result + (gender ? 1 : 0);
+        result = 31 * result + (locale ? 1 : 0);
+        result = 31 * result + (address ? 1 : 0);
+        result = 31 * result + (phone ? 1 : 0);
+        return result;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java
index 8f87c8a..e6b3f2a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ClientMappingsRepresentation.java
@@ -1,38 +1,38 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientMappingsRepresentation {
-    protected String id;
-    protected String client;
-
-    protected List<RoleRepresentation> mappings;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getClient() {
-        return client;
-    }
-
-    public void setClient(String client) {
-        this.client = client;
-    }
-
-    public List<RoleRepresentation> getMappings() {
-        return mappings;
-    }
-
-    public void setMappings(List<RoleRepresentation> mappings) {
-        this.mappings = mappings;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientMappingsRepresentation {
+    protected String id;
+    protected String client;
+
+    protected List<RoleRepresentation> mappings;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getClient() {
+        return client;
+    }
+
+    public void setClient(String client) {
+        this.client = client;
+    }
+
+    public List<RoleRepresentation> getMappings() {
+        return mappings;
+    }
+
+    public void setMappings(List<RoleRepresentation> mappings) {
+        this.mappings = mappings;
+    }
+}
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 0a96270..7192a57 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java
@@ -1,53 +1,53 @@
-package org.keycloak.representations.idm;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class ConfigPropertyRepresentation {
-    protected String name;
-    protected String label;
-    protected String helpText;
-    protected String type;
-    protected Object defaultValue;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    public void setDefaultValue(Object defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    public String getHelpText() {
-        return helpText;
-    }
-
-    public void setHelpText(String helpText) {
-        this.helpText = helpText;
-    }
-}
+package org.keycloak.representations.idm;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class ConfigPropertyRepresentation {
+    protected String name;
+    protected String label;
+    protected String helpText;
+    protected String type;
+    protected Object defaultValue;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Object getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(Object defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    public String getHelpText() {
+        return helpText;
+    }
+
+    public void setHelpText(String helpText) {
+        this.helpText = helpText;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/CredentialRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/CredentialRepresentation.java
index b7dad57..4b2ad4e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/CredentialRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/CredentialRepresentation.java
@@ -1,83 +1,83 @@
-package org.keycloak.representations.idm;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CredentialRepresentation {
-    public static final String SECRET = "secret";
-    public static final String PASSWORD = "password";
-    public static final String PASSWORD_TOKEN = "password-token";
-    public static final String TOTP = "totp";
-    public static final String CLIENT_CERT = "cert";
-    public static final String KERBEROS = "kerberos";
-
-    protected String type;
-    protected String device;
-
-    // Plain-text value of credential (used for example during import from manually created JSON file)
-    protected String value;
-
-    // Value stored in DB (used for example during export/import)
-    protected String hashedSaltedValue;
-    protected String salt;
-    protected Integer hashIterations;
-    // only used when updating a credential.  Might set required action
-    protected boolean temporary;
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public String getDevice() {
-        return device;
-    }
-
-    public void setDevice(String device) {
-        this.device = device;
-    }
-
-    public String getHashedSaltedValue() {
-        return hashedSaltedValue;
-    }
-
-    public void setHashedSaltedValue(String hashedSaltedValue) {
-        this.hashedSaltedValue = hashedSaltedValue;
-    }
-
-    public String getSalt() {
-        return salt;
-    }
-
-    public void setSalt(String salt) {
-        this.salt = salt;
-    }
-
-    public Integer getHashIterations() {
-        return hashIterations;
-    }
-
-    public void setHashIterations(Integer hashIterations) {
-        this.hashIterations = hashIterations;
-    }
-
-    public boolean isTemporary() {
-        return temporary;
-    }
-
-    public void setTemporary(boolean temporary) {
-        this.temporary = temporary;
-    }
-}
+package org.keycloak.representations.idm;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CredentialRepresentation {
+    public static final String SECRET = "secret";
+    public static final String PASSWORD = "password";
+    public static final String PASSWORD_TOKEN = "password-token";
+    public static final String TOTP = "totp";
+    public static final String CLIENT_CERT = "cert";
+    public static final String KERBEROS = "kerberos";
+
+    protected String type;
+    protected String device;
+
+    // Plain-text value of credential (used for example during import from manually created JSON file)
+    protected String value;
+
+    // Value stored in DB (used for example during export/import)
+    protected String hashedSaltedValue;
+    protected String salt;
+    protected Integer hashIterations;
+    // only used when updating a credential.  Might set required action
+    protected boolean temporary;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getDevice() {
+        return device;
+    }
+
+    public void setDevice(String device) {
+        this.device = device;
+    }
+
+    public String getHashedSaltedValue() {
+        return hashedSaltedValue;
+    }
+
+    public void setHashedSaltedValue(String hashedSaltedValue) {
+        this.hashedSaltedValue = hashedSaltedValue;
+    }
+
+    public String getSalt() {
+        return salt;
+    }
+
+    public void setSalt(String salt) {
+        this.salt = salt;
+    }
+
+    public Integer getHashIterations() {
+        return hashIterations;
+    }
+
+    public void setHashIterations(Integer hashIterations) {
+        this.hashIterations = hashIterations;
+    }
+
+    public boolean isTemporary() {
+        return temporary;
+    }
+
+    public void setTemporary(boolean temporary) {
+        this.temporary = temporary;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperRepresentation.java
index 2d59ab8..39b0197 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperRepresentation.java
@@ -1,57 +1,57 @@
-package org.keycloak.representations.idm;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class IdentityProviderMapperRepresentation {
-    protected String id;
-    protected String name;
-    protected String identityProviderAlias;
-    protected String identityProviderMapper;
-    protected Map<String, String> config = new HashMap<String, String>();
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getIdentityProviderAlias() {
-        return identityProviderAlias;
-    }
-
-    public void setIdentityProviderAlias(String identityProviderAlias) {
-        this.identityProviderAlias = identityProviderAlias;
-    }
-
-    public String getIdentityProviderMapper() {
-        return identityProviderMapper;
-    }
-
-    public void setIdentityProviderMapper(String identityProviderMapper) {
-        this.identityProviderMapper = identityProviderMapper;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IdentityProviderMapperRepresentation {
+    protected String id;
+    protected String name;
+    protected String identityProviderAlias;
+    protected String identityProviderMapper;
+    protected Map<String, String> config = new HashMap<String, String>();
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getIdentityProviderAlias() {
+        return identityProviderAlias;
+    }
+
+    public void setIdentityProviderAlias(String identityProviderAlias) {
+        this.identityProviderAlias = identityProviderAlias;
+    }
+
+    public String getIdentityProviderMapper() {
+        return identityProviderMapper;
+    }
+
+    public void setIdentityProviderMapper(String identityProviderMapper) {
+        this.identityProviderMapper = identityProviderMapper;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperTypeRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperTypeRepresentation.java
index 81fdf0f..117fc18 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperTypeRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderMapperTypeRepresentation.java
@@ -1,57 +1,57 @@
-package org.keycloak.representations.idm;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class IdentityProviderMapperTypeRepresentation {
-    protected String id;
-    protected String name;
-    protected String category;
-    protected String helpText;
-
-    protected List<ConfigPropertyRepresentation> properties = new LinkedList<>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getCategory() {
-        return category;
-    }
-
-    public void setCategory(String category) {
-        this.category = category;
-    }
-
-    public String getHelpText() {
-        return helpText;
-    }
-
-    public void setHelpText(String helpText) {
-        this.helpText = helpText;
-    }
-
-    public List<ConfigPropertyRepresentation> getProperties() {
-        return properties;
-    }
-
-    public void setProperties(List<ConfigPropertyRepresentation> properties) {
-        this.properties = properties;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IdentityProviderMapperTypeRepresentation {
+    protected String id;
+    protected String name;
+    protected String category;
+    protected String helpText;
+
+    protected List<ConfigPropertyRepresentation> properties = new LinkedList<>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public String getHelpText() {
+        return helpText;
+    }
+
+    public void setHelpText(String helpText) {
+        this.helpText = helpText;
+    }
+
+    public List<ConfigPropertyRepresentation> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<ConfigPropertyRepresentation> properties) {
+        this.properties = properties;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
index b7e90b8..e88d5c0 100755
--- a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
@@ -1,29 +1,29 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MappingsRepresentation {
-    protected List<RoleRepresentation> realmMappings;
-    protected Map<String, ClientMappingsRepresentation> clientMappings;
-
-    public List<RoleRepresentation> getRealmMappings() {
-        return realmMappings;
-    }
-
-    public void setRealmMappings(List<RoleRepresentation> realmMappings) {
-        this.realmMappings = realmMappings;
-    }
-
-    public Map<String, ClientMappingsRepresentation> getClientMappings() {
-        return clientMappings;
-    }
-
-    public void setClientMappings(Map<String, ClientMappingsRepresentation> clientMappings) {
-        this.clientMappings = clientMappings;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MappingsRepresentation {
+    protected List<RoleRepresentation> realmMappings;
+    protected Map<String, ClientMappingsRepresentation> clientMappings;
+
+    public List<RoleRepresentation> getRealmMappings() {
+        return realmMappings;
+    }
+
+    public void setRealmMappings(List<RoleRepresentation> realmMappings) {
+        this.realmMappings = realmMappings;
+    }
+
+    public Map<String, ClientMappingsRepresentation> getClientMappings() {
+        return clientMappings;
+    }
+
+    public void setClientMappings(Map<String, ClientMappingsRepresentation> clientMappings) {
+        this.clientMappings = clientMappings;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
index 7637cb5..6b37b6f 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperRepresentation.java
@@ -1,75 +1,75 @@
-package org.keycloak.representations.idm;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMapperRepresentation {
-    protected String id;
-    protected String name;
-    protected String protocol;
-    protected String protocolMapper;
-    protected boolean consentRequired;
-    protected String consentText;
-    protected Map<String, String> config = new HashMap<String, String>();
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public String getProtocolMapper() {
-        return protocolMapper;
-    }
-
-    public void setProtocolMapper(String protocolMapper) {
-        this.protocolMapper = protocolMapper;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public String getConsentText() {
-        return consentText;
-    }
-
-    public void setConsentText(String consentText) {
-        this.consentText = consentText;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMapperRepresentation {
+    protected String id;
+    protected String name;
+    protected String protocol;
+    protected String protocolMapper;
+    protected boolean consentRequired;
+    protected String consentText;
+    protected Map<String, String> config = new HashMap<String, String>();
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProtocolMapper() {
+        return protocolMapper;
+    }
+
+    public void setProtocolMapper(String protocolMapper) {
+        this.protocolMapper = protocolMapper;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public String getConsentText() {
+        return consentText;
+    }
+
+    public void setConsentText(String consentText) {
+        this.consentText = consentText;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
index 212fe58..6fccb1a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
@@ -1,56 +1,56 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMapperTypeRepresentation {
-    protected String id;
-    protected String name;
-    protected String category;
-    protected String helpText;
-
-    protected List<ConfigPropertyRepresentation> properties;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getCategory() {
-        return category;
-    }
-
-    public void setCategory(String category) {
-        this.category = category;
-    }
-
-    public String getHelpText() {
-        return helpText;
-    }
-
-    public void setHelpText(String helpText) {
-        this.helpText = helpText;
-    }
-
-    public List<ConfigPropertyRepresentation> getProperties() {
-        return properties;
-    }
-
-    public void setProperties(List<ConfigPropertyRepresentation> properties) {
-        this.properties = properties;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMapperTypeRepresentation {
+    protected String id;
+    protected String name;
+    protected String category;
+    protected String helpText;
+
+    protected List<ConfigPropertyRepresentation> properties;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public String getHelpText() {
+        return helpText;
+    }
+
+    public void setHelpText(String helpText) {
+        this.helpText = helpText;
+    }
+
+    public List<ConfigPropertyRepresentation> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<ConfigPropertyRepresentation> properties) {
+        this.properties = properties;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
index 5b39f7e..1dc8c7c 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
@@ -1,66 +1,66 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmEventsConfigRepresentation {
-    protected boolean eventsEnabled;
-    protected Long eventsExpiration;
-    protected List<String> eventsListeners;
-    protected List<String> enabledEventTypes;
-    
-    protected Boolean adminEventsEnabled;
-    protected Boolean adminEventsDetailsEnabled;
-
-    public boolean isEventsEnabled() {
-        return eventsEnabled;
-    }
-
-    public void setEventsEnabled(boolean eventsEnabled) {
-        this.eventsEnabled = eventsEnabled;
-    }
-
-    public Long getEventsExpiration() {
-        return eventsExpiration;
-    }
-
-    public void setEventsExpiration(Long eventsExpiration) {
-        this.eventsExpiration = eventsExpiration;
-    }
-
-    public List<String> getEventsListeners() {
-        return eventsListeners;
-    }
-
-    public void setEventsListeners(List<String> eventsListeners) {
-        this.eventsListeners = eventsListeners;
-    }
-
-    public List<String> getEnabledEventTypes() {
-        return enabledEventTypes;
-    }
-
-    public void setEnabledEventTypes(List<String> enabledEventTypes) {
-        this.enabledEventTypes = enabledEventTypes;
-    }
-
-    public Boolean isAdminEventsEnabled() {
-        return adminEventsEnabled;
-    }
-
-    public void setAdminEventsEnabled(Boolean adminEventsEnabled) {
-        this.adminEventsEnabled = adminEventsEnabled;
-    }
-
-    public Boolean isAdminEventsDetailsEnabled() {
-        return adminEventsDetailsEnabled;
-    }
-
-    public void setAdminEventsDetailsEnabled(Boolean adminEventsDetailsEnabled) {
-        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
-    }
-    
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmEventsConfigRepresentation {
+    protected boolean eventsEnabled;
+    protected Long eventsExpiration;
+    protected List<String> eventsListeners;
+    protected List<String> enabledEventTypes;
+    
+    protected Boolean adminEventsEnabled;
+    protected Boolean adminEventsDetailsEnabled;
+
+    public boolean isEventsEnabled() {
+        return eventsEnabled;
+    }
+
+    public void setEventsEnabled(boolean eventsEnabled) {
+        this.eventsEnabled = eventsEnabled;
+    }
+
+    public Long getEventsExpiration() {
+        return eventsExpiration;
+    }
+
+    public void setEventsExpiration(Long eventsExpiration) {
+        this.eventsExpiration = eventsExpiration;
+    }
+
+    public List<String> getEventsListeners() {
+        return eventsListeners;
+    }
+
+    public void setEventsListeners(List<String> eventsListeners) {
+        this.eventsListeners = eventsListeners;
+    }
+
+    public List<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(List<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
+
+    public Boolean isAdminEventsEnabled() {
+        return adminEventsEnabled;
+    }
+
+    public void setAdminEventsEnabled(Boolean adminEventsEnabled) {
+        this.adminEventsEnabled = adminEventsEnabled;
+    }
+
+    public Boolean isAdminEventsDetailsEnabled() {
+        return adminEventsDetailsEnabled;
+    }
+
+    public void setAdminEventsDetailsEnabled(Boolean adminEventsDetailsEnabled) {
+        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
+    }
+    
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 25ff0a3..a91f9e2 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -1,646 +1,646 @@
-package org.keycloak.representations.idm;
-
-import java.util.*;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmRepresentation {
-    protected String id;
-    protected String realm;
-    protected Integer notBefore;
-    protected Integer accessTokenLifespan;
-    protected Integer ssoSessionIdleTimeout;
-    protected Integer ssoSessionMaxLifespan;
-    protected Integer accessCodeLifespan;
-    protected Integer accessCodeLifespanUserAction;
-    protected Integer accessCodeLifespanLogin;
-    protected Boolean enabled;
-    protected String sslRequired;
-    @Deprecated
-    protected Boolean passwordCredentialGrantAllowed;
-    protected Boolean registrationAllowed;
-    protected Boolean registrationEmailAsUsername;
-    protected Boolean rememberMe;
-    protected Boolean verifyEmail;
-    protected Boolean resetPasswordAllowed;
-    protected Boolean editUsernameAllowed;
-
-    protected Boolean userCacheEnabled;
-    protected Boolean realmCacheEnabled;
-
-    //--- brute force settings
-    protected Boolean bruteForceProtected;
-    protected Integer maxFailureWaitSeconds;
-    protected Integer minimumQuickLoginWaitSeconds;
-    protected Integer waitIncrementSeconds;
-    protected Long quickLoginCheckMilliSeconds;
-    protected Integer maxDeltaTimeSeconds;
-    protected Integer failureFactor;
-    //--- end brute force settings
-
-    protected String privateKey;
-    protected String publicKey;
-    protected String certificate;
-    protected String codeSecret;
-    protected RolesRepresentation roles;
-    protected List<String> defaultRoles;
-    protected Set<String> requiredCredentials;
-    protected String passwordPolicy;
-    protected List<UserRepresentation> users;
-    protected List<ScopeMappingRepresentation> scopeMappings;
-    protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
-    protected List<ClientRepresentation> clients;
-    protected Map<String, String> browserSecurityHeaders;
-    protected Map<String, String> smtpServer;
-    protected List<UserFederationProviderRepresentation> userFederationProviders;
-    protected List<UserFederationMapperRepresentation> userFederationMappers;
-    protected String loginTheme;
-    protected String accountTheme;
-    protected String adminTheme;
-    protected String emailTheme;
-    
-    protected Boolean eventsEnabled;
-    protected Long eventsExpiration;
-    protected List<String> eventsListeners;
-    protected List<String> enabledEventTypes;
-    
-    protected Boolean adminEventsEnabled;
-    protected Boolean adminEventsDetailsEnabled;
-    
-    private List<IdentityProviderRepresentation> identityProviders;
-    private List<IdentityProviderMapperRepresentation> identityProviderMappers;
-    private List<ProtocolMapperRepresentation> protocolMappers;
-    private Boolean identityFederationEnabled;
-    protected Boolean internationalizationEnabled;
-    protected Set<String> supportedLocales;
-    protected String defaultLocale;
-    protected List<AuthenticationFlowRepresentation> authenticationFlows;
-    protected List<AuthenticatorConfigRepresentation> authenticatorConfig;
-
-    @Deprecated
-    protected Boolean social;
-    @Deprecated
-    protected Boolean updateProfileOnInitialSocialLogin;
-    @Deprecated
-    protected Map<String, String> socialProviders;
-    @Deprecated
-    protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
-    @Deprecated
-    protected List<ApplicationRepresentation> applications;
-    @Deprecated
-    protected List<OAuthClientRepresentation> oauthClients;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public void setRealm(String realm) {
-        this.realm = realm;
-    }
-
-    public List<UserRepresentation> getUsers() {
-        return users;
-    }
-
-    public List<ApplicationRepresentation> getApplications() {
-        return applications;
-    }
-
-    public void setUsers(List<UserRepresentation> users) {
-        this.users = users;
-    }
-
-    public UserRepresentation user(String username) {
-        UserRepresentation user = new UserRepresentation();
-        user.setUsername(username);
-        if (users == null) users = new ArrayList<UserRepresentation>();
-        users.add(user);
-        return user;
-    }
-
-    public List<ClientRepresentation> getClients() {
-        return clients;
-    }
-
-    public void setClients(List<ClientRepresentation> clients) {
-        this.clients = clients;
-    }
-
-    public Boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(Boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getSslRequired() {
-        return sslRequired;
-    }
-
-    public void setSslRequired(String sslRequired) {
-        this.sslRequired = sslRequired;
-    }
-
-    public Integer getAccessTokenLifespan() {
-        return accessTokenLifespan;
-    }
-
-    public void setAccessTokenLifespan(Integer accessTokenLifespan) {
-        this.accessTokenLifespan = accessTokenLifespan;
-    }
-
-    public Integer getSsoSessionIdleTimeout() {
-        return ssoSessionIdleTimeout;
-    }
-
-    public void setSsoSessionIdleTimeout(Integer ssoSessionIdleTimeout) {
-        this.ssoSessionIdleTimeout = ssoSessionIdleTimeout;
-    }
-
-    public Integer getSsoSessionMaxLifespan() {
-        return ssoSessionMaxLifespan;
-    }
-
-    public void setSsoSessionMaxLifespan(Integer ssoSessionMaxLifespan) {
-        this.ssoSessionMaxLifespan = ssoSessionMaxLifespan;
-    }
-
-    public List<ScopeMappingRepresentation> getScopeMappings() {
-        return scopeMappings;
-    }
-
-    public ScopeMappingRepresentation scopeMapping(String username) {
-        ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
-        mapping.setClient(username);
-        if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
-        scopeMappings.add(mapping);
-        return mapping;
-    }
-
-    public Set<String> getRequiredCredentials() {
-        return requiredCredentials;
-    }
-
-    public void setRequiredCredentials(Set<String> requiredCredentials) {
-        this.requiredCredentials = requiredCredentials;
-    }
-
-    public String getPasswordPolicy() {
-        return passwordPolicy;
-    }
-
-    public void setPasswordPolicy(String passwordPolicy) {
-        this.passwordPolicy = passwordPolicy;
-    }
-
-    public Integer getAccessCodeLifespan() {
-        return accessCodeLifespan;
-    }
-
-    public void setAccessCodeLifespan(Integer accessCodeLifespan) {
-        this.accessCodeLifespan = accessCodeLifespan;
-    }
-
-    public Integer getAccessCodeLifespanUserAction() {
-        return accessCodeLifespanUserAction;
-    }
-
-    public void setAccessCodeLifespanUserAction(Integer accessCodeLifespanUserAction) {
-        this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
-    }
-
-    public Integer getAccessCodeLifespanLogin() {
-        return accessCodeLifespanLogin;
-    }
-
-    public void setAccessCodeLifespanLogin(Integer accessCodeLifespanLogin) {
-        this.accessCodeLifespanLogin = accessCodeLifespanLogin;
-    }
-
-    public List<String> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public void setDefaultRoles(List<String> defaultRoles) {
-        this.defaultRoles = defaultRoles;
-    }
-
-    public String getPrivateKey() {
-        return privateKey;
-    }
-
-    public void setPrivateKey(String privateKey) {
-        this.privateKey = privateKey;
-    }
-
-    public String getPublicKey() {
-        return publicKey;
-    }
-
-    public void setPublicKey(String publicKey) {
-        this.publicKey = publicKey;
-    }
-
-    public String getCertificate() {
-        return certificate;
-    }
-
-    public void setCertificate(String certificate) {
-        this.certificate = certificate;
-    }
-
-    public String getCodeSecret() {
-        return codeSecret;
-    }
-
-    public void setCodeSecret(String codeSecret) {
-        this.codeSecret = codeSecret;
-    }
-
-    public Boolean isPasswordCredentialGrantAllowed() {
-        return passwordCredentialGrantAllowed;
-    }
-
-    public Boolean isRegistrationAllowed() {
-        return registrationAllowed;
-    }
-
-    public void setRegistrationAllowed(Boolean registrationAllowed) {
-        this.registrationAllowed = registrationAllowed;
-    }
-
-    public Boolean isRegistrationEmailAsUsername() {
-        return registrationEmailAsUsername;
-    }
-
-    public void setRegistrationEmailAsUsername(Boolean registrationEmailAsUsername) {
-        this.registrationEmailAsUsername = registrationEmailAsUsername;
-    }
-
-    public Boolean isRememberMe() {
-        return rememberMe;
-    }
-
-    public void setRememberMe(Boolean rememberMe) {
-        this.rememberMe = rememberMe;
-    }
-
-    public Boolean isRealmCacheEnabled() {
-        return realmCacheEnabled;
-    }
-
-    public void setRealmCacheEnabled(Boolean realmCacheEnabled) {
-        this.realmCacheEnabled = realmCacheEnabled;
-    }
-
-    public Boolean isUserCacheEnabled() {
-        return userCacheEnabled;
-    }
-
-    public void setUserCacheEnabled(Boolean userCacheEnabled) {
-        this.userCacheEnabled = userCacheEnabled;
-    }
-
-    public Boolean isVerifyEmail() {
-        return verifyEmail;
-    }
-
-    public void setVerifyEmail(Boolean verifyEmail) {
-        this.verifyEmail = verifyEmail;
-    }
-
-    public Boolean isResetPasswordAllowed() {
-        return resetPasswordAllowed;
-    }
-
-    public void setResetPasswordAllowed(Boolean resetPassword) {
-        this.resetPasswordAllowed = resetPassword;
-    }
-
-    public Boolean isEditUsernameAllowed() {
-        return editUsernameAllowed;
-    }
-
-    public void setEditUsernameAllowed(Boolean editUsernameAllowed) {
-        this.editUsernameAllowed = editUsernameAllowed;
-    }
-
-    @Deprecated
-    public Boolean isSocial() {
-        return social;
-    }
-
-    @Deprecated
-    public Boolean isUpdateProfileOnInitialSocialLogin() {
-        return updateProfileOnInitialSocialLogin;
-    }
-
-    public Map<String, String> getBrowserSecurityHeaders() {
-        return browserSecurityHeaders;
-    }
-
-    public void setBrowserSecurityHeaders(Map<String, String> browserSecurityHeaders) {
-        this.browserSecurityHeaders = browserSecurityHeaders;
-    }
-
-    @Deprecated
-    public Map<String, String> getSocialProviders() {
-        return socialProviders;
-    }
-
-    public Map<String, String> getSmtpServer() {
-        return smtpServer;
-    }
-
-    public void setSmtpServer(Map<String, String> smtpServer) {
-        this.smtpServer = smtpServer;
-    }
-
-    @Deprecated
-    public List<OAuthClientRepresentation> getOauthClients() {
-        return oauthClients;
-    }
-
-    public Map<String, List<ScopeMappingRepresentation>> getClientScopeMappings() {
-        return clientScopeMappings;
-    }
-
-    public void setClientScopeMappings(Map<String, List<ScopeMappingRepresentation>> clientScopeMappings) {
-        this.clientScopeMappings = clientScopeMappings;
-    }
-
-    @Deprecated
-    public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
-        return applicationScopeMappings;
-    }
-
-    public RolesRepresentation getRoles() {
-        return roles;
-    }
-
-    public void setRoles(RolesRepresentation roles) {
-        this.roles = roles;
-    }
-
-    public String getLoginTheme() {
-        return loginTheme;
-    }
-
-    public void setLoginTheme(String loginTheme) {
-        this.loginTheme = loginTheme;
-    }
-
-    public String getAccountTheme() {
-        return accountTheme;
-    }
-
-    public void setAccountTheme(String accountTheme) {
-        this.accountTheme = accountTheme;
-    }
-
-    public String getAdminTheme() {
-        return adminTheme;
-    }
-
-    public void setAdminTheme(String adminTheme) {
-        this.adminTheme = adminTheme;
-    }
-
-    public String getEmailTheme() {
-        return emailTheme;
-    }
-
-    public void setEmailTheme(String emailTheme) {
-        this.emailTheme = emailTheme;
-    }
-
-    public Integer getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(Integer notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public Boolean isBruteForceProtected() {
-        return bruteForceProtected;
-    }
-
-    public void setBruteForceProtected(Boolean bruteForceProtected) {
-        this.bruteForceProtected = bruteForceProtected;
-    }
-
-    public Integer getMaxFailureWaitSeconds() {
-        return maxFailureWaitSeconds;
-    }
-
-    public void setMaxFailureWaitSeconds(Integer maxFailureWaitSeconds) {
-        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
-    }
-
-    public Integer getMinimumQuickLoginWaitSeconds() {
-        return minimumQuickLoginWaitSeconds;
-    }
-
-    public void setMinimumQuickLoginWaitSeconds(Integer minimumQuickLoginWaitSeconds) {
-        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
-    }
-
-    public Integer getWaitIncrementSeconds() {
-        return waitIncrementSeconds;
-    }
-
-    public void setWaitIncrementSeconds(Integer waitIncrementSeconds) {
-        this.waitIncrementSeconds = waitIncrementSeconds;
-    }
-
-    public Long getQuickLoginCheckMilliSeconds() {
-        return quickLoginCheckMilliSeconds;
-    }
-
-    public void setQuickLoginCheckMilliSeconds(Long quickLoginCheckMilliSeconds) {
-        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
-    }
-
-    public Integer getMaxDeltaTimeSeconds() {
-        return maxDeltaTimeSeconds;
-    }
-
-    public void setMaxDeltaTimeSeconds(Integer maxDeltaTimeSeconds) {
-        this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
-    }
-
-    public Integer getFailureFactor() {
-        return failureFactor;
-    }
-
-    public void setFailureFactor(Integer failureFactor) {
-        this.failureFactor = failureFactor;
-    }
-
-    public Boolean isEventsEnabled() {
-        return eventsEnabled;
-    }
-
-    public void setEventsEnabled(boolean eventsEnabled) {
-        this.eventsEnabled = eventsEnabled;
-    }
-
-    public Long getEventsExpiration() {
-        return eventsExpiration;
-    }
-
-    public void setEventsExpiration(long eventsExpiration) {
-        this.eventsExpiration = eventsExpiration;
-    }
-
-    public List<String> getEventsListeners() {
-        return eventsListeners;
-    }
-
-    public void setEventsListeners(List<String> eventsListeners) {
-        this.eventsListeners = eventsListeners;
-    }
-    
-    public List<String> getEnabledEventTypes() {
-        return enabledEventTypes;
-    }
-
-    public void setEnabledEventTypes(List<String> enabledEventTypes) {
-        this.enabledEventTypes = enabledEventTypes;
-    }
-
-    public Boolean isAdminEventsEnabled() {
-        return adminEventsEnabled;
-    }
-
-    public void setAdminEventsEnabled(Boolean adminEventsEnabled) {
-        this.adminEventsEnabled = adminEventsEnabled;
-    }
-
-    public Boolean isAdminEventsDetailsEnabled() {
-        return adminEventsDetailsEnabled;
-    }
-
-    public void setAdminEventsDetailsEnabled(Boolean adminEventsDetailsEnabled) {
-        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
-    }
-
-    public List<UserFederationProviderRepresentation> getUserFederationProviders() {
-        return userFederationProviders;
-    }
-
-    public void setUserFederationProviders(List<UserFederationProviderRepresentation> userFederationProviders) {
-        this.userFederationProviders = userFederationProviders;
-    }
-
-    public List<UserFederationMapperRepresentation> getUserFederationMappers() {
-        return userFederationMappers;
-    }
-
-    public void setUserFederationMappers(List<UserFederationMapperRepresentation> userFederationMappers) {
-        this.userFederationMappers = userFederationMappers;
-    }
-
-    public void addUserFederationMapper(UserFederationMapperRepresentation userFederationMapper) {
-        if (userFederationMappers == null) userFederationMappers = new LinkedList<>();
-        userFederationMappers.add(userFederationMapper);
-    }
-
-    public List<IdentityProviderRepresentation> getIdentityProviders() {
-        return identityProviders;
-    }
-
-    public void setIdentityProviders(List<IdentityProviderRepresentation> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public void addIdentityProvider(IdentityProviderRepresentation identityProviderRepresentation) {
-        if (identityProviders == null) identityProviders = new LinkedList<>();
-        identityProviders.add(identityProviderRepresentation);
-    }
-
-    public boolean isIdentityFederationEnabled() {
-        return identityProviders != null && !identityProviders.isEmpty();
-    }
-
-    public List<ProtocolMapperRepresentation> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void addProtocolMapper(ProtocolMapperRepresentation rep) {
-        if (protocolMappers == null) protocolMappers = new LinkedList<ProtocolMapperRepresentation>();
-        protocolMappers.add(rep);
-    }
-
-    public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public Boolean isInternationalizationEnabled() {
-        return internationalizationEnabled;
-    }
-
-    public void setInternationalizationEnabled(Boolean internationalizationEnabled) {
-        this.internationalizationEnabled = internationalizationEnabled;
-    }
-
-    public Set<String> getSupportedLocales() {
-        if(supportedLocales == null){
-            supportedLocales = new HashSet<String>();
-        }
-        return supportedLocales;
-    }
-
-    public void setSupportedLocales(Set<String> supportedLocales) {
-        this.supportedLocales = supportedLocales;
-    }
-
-    public String getDefaultLocale() {
-        return defaultLocale;
-    }
-
-    public void setDefaultLocale(String defaultLocale) {
-        this.defaultLocale = defaultLocale;
-    }
-
-    public List<IdentityProviderMapperRepresentation> getIdentityProviderMappers() {
-        return identityProviderMappers;
-    }
-
-    public void setIdentityProviderMappers(List<IdentityProviderMapperRepresentation> identityProviderMappers) {
-        this.identityProviderMappers = identityProviderMappers;
-    }
-
-    public void addIdentityProviderMapper(IdentityProviderMapperRepresentation rep) {
-        if (identityProviderMappers == null) identityProviderMappers = new LinkedList<>();
-        identityProviderMappers.add(rep);
-    }
-
-    public List<AuthenticationFlowRepresentation> getAuthenticationFlows() {
-        return authenticationFlows;
-    }
-
-    public void setAuthenticationFlows(List<AuthenticationFlowRepresentation> authenticationFlows) {
-        this.authenticationFlows = authenticationFlows;
-    }
-
-    public List<AuthenticatorConfigRepresentation> getAuthenticatorConfig() {
-        return authenticatorConfig;
-    }
-
-    public void setAuthenticatorConfig(List<AuthenticatorConfigRepresentation> authenticatorConfig) {
-        this.authenticatorConfig = authenticatorConfig;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.*;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmRepresentation {
+    protected String id;
+    protected String realm;
+    protected Integer notBefore;
+    protected Integer accessTokenLifespan;
+    protected Integer ssoSessionIdleTimeout;
+    protected Integer ssoSessionMaxLifespan;
+    protected Integer accessCodeLifespan;
+    protected Integer accessCodeLifespanUserAction;
+    protected Integer accessCodeLifespanLogin;
+    protected Boolean enabled;
+    protected String sslRequired;
+    @Deprecated
+    protected Boolean passwordCredentialGrantAllowed;
+    protected Boolean registrationAllowed;
+    protected Boolean registrationEmailAsUsername;
+    protected Boolean rememberMe;
+    protected Boolean verifyEmail;
+    protected Boolean resetPasswordAllowed;
+    protected Boolean editUsernameAllowed;
+
+    protected Boolean userCacheEnabled;
+    protected Boolean realmCacheEnabled;
+
+    //--- brute force settings
+    protected Boolean bruteForceProtected;
+    protected Integer maxFailureWaitSeconds;
+    protected Integer minimumQuickLoginWaitSeconds;
+    protected Integer waitIncrementSeconds;
+    protected Long quickLoginCheckMilliSeconds;
+    protected Integer maxDeltaTimeSeconds;
+    protected Integer failureFactor;
+    //--- end brute force settings
+
+    protected String privateKey;
+    protected String publicKey;
+    protected String certificate;
+    protected String codeSecret;
+    protected RolesRepresentation roles;
+    protected List<String> defaultRoles;
+    protected Set<String> requiredCredentials;
+    protected String passwordPolicy;
+    protected List<UserRepresentation> users;
+    protected List<ScopeMappingRepresentation> scopeMappings;
+    protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
+    protected List<ClientRepresentation> clients;
+    protected Map<String, String> browserSecurityHeaders;
+    protected Map<String, String> smtpServer;
+    protected List<UserFederationProviderRepresentation> userFederationProviders;
+    protected List<UserFederationMapperRepresentation> userFederationMappers;
+    protected String loginTheme;
+    protected String accountTheme;
+    protected String adminTheme;
+    protected String emailTheme;
+    
+    protected Boolean eventsEnabled;
+    protected Long eventsExpiration;
+    protected List<String> eventsListeners;
+    protected List<String> enabledEventTypes;
+    
+    protected Boolean adminEventsEnabled;
+    protected Boolean adminEventsDetailsEnabled;
+    
+    private List<IdentityProviderRepresentation> identityProviders;
+    private List<IdentityProviderMapperRepresentation> identityProviderMappers;
+    private List<ProtocolMapperRepresentation> protocolMappers;
+    private Boolean identityFederationEnabled;
+    protected Boolean internationalizationEnabled;
+    protected Set<String> supportedLocales;
+    protected String defaultLocale;
+    protected List<AuthenticationFlowRepresentation> authenticationFlows;
+    protected List<AuthenticatorConfigRepresentation> authenticatorConfig;
+
+    @Deprecated
+    protected Boolean social;
+    @Deprecated
+    protected Boolean updateProfileOnInitialSocialLogin;
+    @Deprecated
+    protected Map<String, String> socialProviders;
+    @Deprecated
+    protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
+    @Deprecated
+    protected List<ApplicationRepresentation> applications;
+    @Deprecated
+    protected List<OAuthClientRepresentation> oauthClients;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+
+    public List<UserRepresentation> getUsers() {
+        return users;
+    }
+
+    public List<ApplicationRepresentation> getApplications() {
+        return applications;
+    }
+
+    public void setUsers(List<UserRepresentation> users) {
+        this.users = users;
+    }
+
+    public UserRepresentation user(String username) {
+        UserRepresentation user = new UserRepresentation();
+        user.setUsername(username);
+        if (users == null) users = new ArrayList<UserRepresentation>();
+        users.add(user);
+        return user;
+    }
+
+    public List<ClientRepresentation> getClients() {
+        return clients;
+    }
+
+    public void setClients(List<ClientRepresentation> clients) {
+        this.clients = clients;
+    }
+
+    public Boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getSslRequired() {
+        return sslRequired;
+    }
+
+    public void setSslRequired(String sslRequired) {
+        this.sslRequired = sslRequired;
+    }
+
+    public Integer getAccessTokenLifespan() {
+        return accessTokenLifespan;
+    }
+
+    public void setAccessTokenLifespan(Integer accessTokenLifespan) {
+        this.accessTokenLifespan = accessTokenLifespan;
+    }
+
+    public Integer getSsoSessionIdleTimeout() {
+        return ssoSessionIdleTimeout;
+    }
+
+    public void setSsoSessionIdleTimeout(Integer ssoSessionIdleTimeout) {
+        this.ssoSessionIdleTimeout = ssoSessionIdleTimeout;
+    }
+
+    public Integer getSsoSessionMaxLifespan() {
+        return ssoSessionMaxLifespan;
+    }
+
+    public void setSsoSessionMaxLifespan(Integer ssoSessionMaxLifespan) {
+        this.ssoSessionMaxLifespan = ssoSessionMaxLifespan;
+    }
+
+    public List<ScopeMappingRepresentation> getScopeMappings() {
+        return scopeMappings;
+    }
+
+    public ScopeMappingRepresentation scopeMapping(String username) {
+        ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
+        mapping.setClient(username);
+        if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
+        scopeMappings.add(mapping);
+        return mapping;
+    }
+
+    public Set<String> getRequiredCredentials() {
+        return requiredCredentials;
+    }
+
+    public void setRequiredCredentials(Set<String> requiredCredentials) {
+        this.requiredCredentials = requiredCredentials;
+    }
+
+    public String getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public void setPasswordPolicy(String passwordPolicy) {
+        this.passwordPolicy = passwordPolicy;
+    }
+
+    public Integer getAccessCodeLifespan() {
+        return accessCodeLifespan;
+    }
+
+    public void setAccessCodeLifespan(Integer accessCodeLifespan) {
+        this.accessCodeLifespan = accessCodeLifespan;
+    }
+
+    public Integer getAccessCodeLifespanUserAction() {
+        return accessCodeLifespanUserAction;
+    }
+
+    public void setAccessCodeLifespanUserAction(Integer accessCodeLifespanUserAction) {
+        this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
+    }
+
+    public Integer getAccessCodeLifespanLogin() {
+        return accessCodeLifespanLogin;
+    }
+
+    public void setAccessCodeLifespanLogin(Integer accessCodeLifespanLogin) {
+        this.accessCodeLifespanLogin = accessCodeLifespanLogin;
+    }
+
+    public List<String> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(List<String> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public void setPrivateKey(String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    public String getPublicKey() {
+        return publicKey;
+    }
+
+    public void setPublicKey(String publicKey) {
+        this.publicKey = publicKey;
+    }
+
+    public String getCertificate() {
+        return certificate;
+    }
+
+    public void setCertificate(String certificate) {
+        this.certificate = certificate;
+    }
+
+    public String getCodeSecret() {
+        return codeSecret;
+    }
+
+    public void setCodeSecret(String codeSecret) {
+        this.codeSecret = codeSecret;
+    }
+
+    public Boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public Boolean isRegistrationAllowed() {
+        return registrationAllowed;
+    }
+
+    public void setRegistrationAllowed(Boolean registrationAllowed) {
+        this.registrationAllowed = registrationAllowed;
+    }
+
+    public Boolean isRegistrationEmailAsUsername() {
+        return registrationEmailAsUsername;
+    }
+
+    public void setRegistrationEmailAsUsername(Boolean registrationEmailAsUsername) {
+        this.registrationEmailAsUsername = registrationEmailAsUsername;
+    }
+
+    public Boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    public void setRememberMe(Boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
+    public Boolean isRealmCacheEnabled() {
+        return realmCacheEnabled;
+    }
+
+    public void setRealmCacheEnabled(Boolean realmCacheEnabled) {
+        this.realmCacheEnabled = realmCacheEnabled;
+    }
+
+    public Boolean isUserCacheEnabled() {
+        return userCacheEnabled;
+    }
+
+    public void setUserCacheEnabled(Boolean userCacheEnabled) {
+        this.userCacheEnabled = userCacheEnabled;
+    }
+
+    public Boolean isVerifyEmail() {
+        return verifyEmail;
+    }
+
+    public void setVerifyEmail(Boolean verifyEmail) {
+        this.verifyEmail = verifyEmail;
+    }
+
+    public Boolean isResetPasswordAllowed() {
+        return resetPasswordAllowed;
+    }
+
+    public void setResetPasswordAllowed(Boolean resetPassword) {
+        this.resetPasswordAllowed = resetPassword;
+    }
+
+    public Boolean isEditUsernameAllowed() {
+        return editUsernameAllowed;
+    }
+
+    public void setEditUsernameAllowed(Boolean editUsernameAllowed) {
+        this.editUsernameAllowed = editUsernameAllowed;
+    }
+
+    @Deprecated
+    public Boolean isSocial() {
+        return social;
+    }
+
+    @Deprecated
+    public Boolean isUpdateProfileOnInitialSocialLogin() {
+        return updateProfileOnInitialSocialLogin;
+    }
+
+    public Map<String, String> getBrowserSecurityHeaders() {
+        return browserSecurityHeaders;
+    }
+
+    public void setBrowserSecurityHeaders(Map<String, String> browserSecurityHeaders) {
+        this.browserSecurityHeaders = browserSecurityHeaders;
+    }
+
+    @Deprecated
+    public Map<String, String> getSocialProviders() {
+        return socialProviders;
+    }
+
+    public Map<String, String> getSmtpServer() {
+        return smtpServer;
+    }
+
+    public void setSmtpServer(Map<String, String> smtpServer) {
+        this.smtpServer = smtpServer;
+    }
+
+    @Deprecated
+    public List<OAuthClientRepresentation> getOauthClients() {
+        return oauthClients;
+    }
+
+    public Map<String, List<ScopeMappingRepresentation>> getClientScopeMappings() {
+        return clientScopeMappings;
+    }
+
+    public void setClientScopeMappings(Map<String, List<ScopeMappingRepresentation>> clientScopeMappings) {
+        this.clientScopeMappings = clientScopeMappings;
+    }
+
+    @Deprecated
+    public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
+        return applicationScopeMappings;
+    }
+
+    public RolesRepresentation getRoles() {
+        return roles;
+    }
+
+    public void setRoles(RolesRepresentation roles) {
+        this.roles = roles;
+    }
+
+    public String getLoginTheme() {
+        return loginTheme;
+    }
+
+    public void setLoginTheme(String loginTheme) {
+        this.loginTheme = loginTheme;
+    }
+
+    public String getAccountTheme() {
+        return accountTheme;
+    }
+
+    public void setAccountTheme(String accountTheme) {
+        this.accountTheme = accountTheme;
+    }
+
+    public String getAdminTheme() {
+        return adminTheme;
+    }
+
+    public void setAdminTheme(String adminTheme) {
+        this.adminTheme = adminTheme;
+    }
+
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public void setEmailTheme(String emailTheme) {
+        this.emailTheme = emailTheme;
+    }
+
+    public Integer getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(Integer notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public Boolean isBruteForceProtected() {
+        return bruteForceProtected;
+    }
+
+    public void setBruteForceProtected(Boolean bruteForceProtected) {
+        this.bruteForceProtected = bruteForceProtected;
+    }
+
+    public Integer getMaxFailureWaitSeconds() {
+        return maxFailureWaitSeconds;
+    }
+
+    public void setMaxFailureWaitSeconds(Integer maxFailureWaitSeconds) {
+        this.maxFailureWaitSeconds = maxFailureWaitSeconds;
+    }
+
+    public Integer getMinimumQuickLoginWaitSeconds() {
+        return minimumQuickLoginWaitSeconds;
+    }
+
+    public void setMinimumQuickLoginWaitSeconds(Integer minimumQuickLoginWaitSeconds) {
+        this.minimumQuickLoginWaitSeconds = minimumQuickLoginWaitSeconds;
+    }
+
+    public Integer getWaitIncrementSeconds() {
+        return waitIncrementSeconds;
+    }
+
+    public void setWaitIncrementSeconds(Integer waitIncrementSeconds) {
+        this.waitIncrementSeconds = waitIncrementSeconds;
+    }
+
+    public Long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public void setQuickLoginCheckMilliSeconds(Long quickLoginCheckMilliSeconds) {
+        this.quickLoginCheckMilliSeconds = quickLoginCheckMilliSeconds;
+    }
+
+    public Integer getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public void setMaxDeltaTimeSeconds(Integer maxDeltaTimeSeconds) {
+        this.maxDeltaTimeSeconds = maxDeltaTimeSeconds;
+    }
+
+    public Integer getFailureFactor() {
+        return failureFactor;
+    }
+
+    public void setFailureFactor(Integer failureFactor) {
+        this.failureFactor = failureFactor;
+    }
+
+    public Boolean isEventsEnabled() {
+        return eventsEnabled;
+    }
+
+    public void setEventsEnabled(boolean eventsEnabled) {
+        this.eventsEnabled = eventsEnabled;
+    }
+
+    public Long getEventsExpiration() {
+        return eventsExpiration;
+    }
+
+    public void setEventsExpiration(long eventsExpiration) {
+        this.eventsExpiration = eventsExpiration;
+    }
+
+    public List<String> getEventsListeners() {
+        return eventsListeners;
+    }
+
+    public void setEventsListeners(List<String> eventsListeners) {
+        this.eventsListeners = eventsListeners;
+    }
+    
+    public List<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(List<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
+
+    public Boolean isAdminEventsEnabled() {
+        return adminEventsEnabled;
+    }
+
+    public void setAdminEventsEnabled(Boolean adminEventsEnabled) {
+        this.adminEventsEnabled = adminEventsEnabled;
+    }
+
+    public Boolean isAdminEventsDetailsEnabled() {
+        return adminEventsDetailsEnabled;
+    }
+
+    public void setAdminEventsDetailsEnabled(Boolean adminEventsDetailsEnabled) {
+        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
+    }
+
+    public List<UserFederationProviderRepresentation> getUserFederationProviders() {
+        return userFederationProviders;
+    }
+
+    public void setUserFederationProviders(List<UserFederationProviderRepresentation> userFederationProviders) {
+        this.userFederationProviders = userFederationProviders;
+    }
+
+    public List<UserFederationMapperRepresentation> getUserFederationMappers() {
+        return userFederationMappers;
+    }
+
+    public void setUserFederationMappers(List<UserFederationMapperRepresentation> userFederationMappers) {
+        this.userFederationMappers = userFederationMappers;
+    }
+
+    public void addUserFederationMapper(UserFederationMapperRepresentation userFederationMapper) {
+        if (userFederationMappers == null) userFederationMappers = new LinkedList<>();
+        userFederationMappers.add(userFederationMapper);
+    }
+
+    public List<IdentityProviderRepresentation> getIdentityProviders() {
+        return identityProviders;
+    }
+
+    public void setIdentityProviders(List<IdentityProviderRepresentation> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public void addIdentityProvider(IdentityProviderRepresentation identityProviderRepresentation) {
+        if (identityProviders == null) identityProviders = new LinkedList<>();
+        identityProviders.add(identityProviderRepresentation);
+    }
+
+    public boolean isIdentityFederationEnabled() {
+        return identityProviders != null && !identityProviders.isEmpty();
+    }
+
+    public List<ProtocolMapperRepresentation> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void addProtocolMapper(ProtocolMapperRepresentation rep) {
+        if (protocolMappers == null) protocolMappers = new LinkedList<ProtocolMapperRepresentation>();
+        protocolMappers.add(rep);
+    }
+
+    public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public Boolean isInternationalizationEnabled() {
+        return internationalizationEnabled;
+    }
+
+    public void setInternationalizationEnabled(Boolean internationalizationEnabled) {
+        this.internationalizationEnabled = internationalizationEnabled;
+    }
+
+    public Set<String> getSupportedLocales() {
+        if(supportedLocales == null){
+            supportedLocales = new HashSet<String>();
+        }
+        return supportedLocales;
+    }
+
+    public void setSupportedLocales(Set<String> supportedLocales) {
+        this.supportedLocales = supportedLocales;
+    }
+
+    public String getDefaultLocale() {
+        return defaultLocale;
+    }
+
+    public void setDefaultLocale(String defaultLocale) {
+        this.defaultLocale = defaultLocale;
+    }
+
+    public List<IdentityProviderMapperRepresentation> getIdentityProviderMappers() {
+        return identityProviderMappers;
+    }
+
+    public void setIdentityProviderMappers(List<IdentityProviderMapperRepresentation> identityProviderMappers) {
+        this.identityProviderMappers = identityProviderMappers;
+    }
+
+    public void addIdentityProviderMapper(IdentityProviderMapperRepresentation rep) {
+        if (identityProviderMappers == null) identityProviderMappers = new LinkedList<>();
+        identityProviderMappers.add(rep);
+    }
+
+    public List<AuthenticationFlowRepresentation> getAuthenticationFlows() {
+        return authenticationFlows;
+    }
+
+    public void setAuthenticationFlows(List<AuthenticationFlowRepresentation> authenticationFlows) {
+        this.authenticationFlows = authenticationFlows;
+    }
+
+    public List<AuthenticatorConfigRepresentation> getAuthenticatorConfig() {
+        return authenticatorConfig;
+    }
+
+    public void setAuthenticatorConfig(List<AuthenticatorConfigRepresentation> authenticatorConfig) {
+        this.authenticatorConfig = authenticatorConfig;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
index 9d0909d..c335ab4 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -1,98 +1,98 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleRepresentation {
-    protected String id;
-    protected String name;
-    protected String description;
-    protected boolean composite;
-    protected Composites composites;
-
-    public static class Composites {
-        protected Set<String> realm;
-        protected Map<String, List<String>> client;
-        @Deprecated
-        protected Map<String, List<String>> application;
-
-        public Set<String> getRealm() {
-            return realm;
-        }
-
-        public void setRealm(Set<String> realm) {
-            this.realm = realm;
-        }
-
-        public Map<String, List<String>> getClient() {
-            return client;
-        }
-
-        public void setClient(Map<String, List<String>> client) {
-            this.client = client;
-        }
-
-        @Deprecated
-        public Map<String, List<String>> getApplication() {
-            return application;
-        }
-    }
-
-    public RoleRepresentation() {
-    }
-
-    public RoleRepresentation(String name, String description) {
-        this.name = name;
-        this.description = description;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Composites getComposites() {
-        return composites;
-    }
-
-    public void setComposites(Composites composites) {
-        this.composites = composites;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    public boolean isComposite() {
-        return composite;
-    }
-
-    public void setComposite(boolean composite) {
-        this.composite = composite;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleRepresentation {
+    protected String id;
+    protected String name;
+    protected String description;
+    protected boolean composite;
+    protected Composites composites;
+
+    public static class Composites {
+        protected Set<String> realm;
+        protected Map<String, List<String>> client;
+        @Deprecated
+        protected Map<String, List<String>> application;
+
+        public Set<String> getRealm() {
+            return realm;
+        }
+
+        public void setRealm(Set<String> realm) {
+            this.realm = realm;
+        }
+
+        public Map<String, List<String>> getClient() {
+            return client;
+        }
+
+        public void setClient(Map<String, List<String>> client) {
+            this.client = client;
+        }
+
+        @Deprecated
+        public Map<String, List<String>> getApplication() {
+            return application;
+        }
+    }
+
+    public RoleRepresentation() {
+    }
+
+    public RoleRepresentation(String name, String description) {
+        this.name = name;
+        this.description = description;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Composites getComposites() {
+        return composites;
+    }
+
+    public void setComposites(Composites composites) {
+        this.composites = composites;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public boolean isComposite() {
+        return composite;
+    }
+
+    public void setComposite(boolean composite) {
+        this.composite = composite;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
index afeb96a..705653c 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
@@ -1,36 +1,36 @@
-package org.keycloak.representations.idm;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RolesRepresentation {
-    protected List<RoleRepresentation> realm;
-    protected Map<String, List<RoleRepresentation>> client;
-    @Deprecated
-    protected Map<String, List<RoleRepresentation>> application;
-
-    public List<RoleRepresentation> getRealm() {
-        return realm;
-    }
-
-    public void setRealm(List<RoleRepresentation> realm) {
-        this.realm = realm;
-    }
-
-    public Map<String, List<RoleRepresentation>> getClient() {
-        return client;
-    }
-
-    public void setClient(Map<String, List<RoleRepresentation>> client) {
-        this.client = client;
-    }
-
-    @Deprecated
-    public Map<String, List<RoleRepresentation>> getApplication() {
-        return application;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RolesRepresentation {
+    protected List<RoleRepresentation> realm;
+    protected Map<String, List<RoleRepresentation>> client;
+    @Deprecated
+    protected Map<String, List<RoleRepresentation>> application;
+
+    public List<RoleRepresentation> getRealm() {
+        return realm;
+    }
+
+    public void setRealm(List<RoleRepresentation> realm) {
+        this.realm = realm;
+    }
+
+    public Map<String, List<RoleRepresentation>> getClient() {
+        return client;
+    }
+
+    public void setClient(Map<String, List<RoleRepresentation>> client) {
+        this.client = client;
+    }
+
+    @Deprecated
+    public Map<String, List<RoleRepresentation>> getApplication() {
+        return application;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
index bcb363b..56b96b0 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
@@ -1,76 +1,76 @@
-package org.keycloak.representations.idm;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserSessionRepresentation {
-    private String id;
-    private String username;
-    private String userId;
-    private String ipAddress;
-    private long start;
-    private long lastAccess;
-    private Map<String, String> clients = new HashMap<String, String>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-    
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    public String getIpAddress() {
-        return ipAddress;
-    }
-
-    public void setIpAddress(String ipAddress) {
-        this.ipAddress = ipAddress;
-    }
-
-    public long getStart() {
-        return start;
-    }
-
-    public void setStart(long start) {
-        this.start = start;
-    }
-
-    public long getLastAccess() {
-        return lastAccess;
-    }
-
-    public void setLastAccess(long lastAccess) {
-        this.lastAccess = lastAccess;
-    }
-
-    public Map<String, String> getClients() {
-        return clients;
-    }
-
-    public void setClients(Map<String, String> clients) {
-        this.clients = clients;
-    }
-}
+package org.keycloak.representations.idm;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserSessionRepresentation {
+    private String id;
+    private String username;
+    private String userId;
+    private String ipAddress;
+    private long start;
+    private long lastAccess;
+    private Map<String, String> clients = new HashMap<String, String>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+    
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public long getStart() {
+        return start;
+    }
+
+    public void setStart(long start) {
+        this.start = start;
+    }
+
+    public long getLastAccess() {
+        return lastAccess;
+    }
+
+    public void setLastAccess(long lastAccess) {
+        this.lastAccess = lastAccess;
+    }
+
+    public Map<String, String> getClients() {
+        return clients;
+    }
+
+    public void setClients(Map<String, String> clients) {
+        this.clients = clients;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/IDToken.java b/core/src/main/java/org/keycloak/representations/IDToken.java
index 78fa5ce..42f7679 100755
--- a/core/src/main/java/org/keycloak/representations/IDToken.java
+++ b/core/src/main/java/org/keycloak/representations/IDToken.java
@@ -1,282 +1,282 @@
-package org.keycloak.representations;
-
-import org.codehaus.jackson.annotate.JsonAnyGetter;
-import org.codehaus.jackson.annotate.JsonAnySetter;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonUnwrapped;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class IDToken extends JsonWebToken {
-    public static final String NONCE = "nonce";
-    public static final String SESSION_STATE = "session_state";
-    public static final String NAME = "name";
-    public static final String GIVEN_NAME = "given_name";
-    public static final String FAMILY_NAME = "family_name";
-    public static final String MIDDLE_NAME = "middle_name";
-    public static final String NICKNAME = "nickname";
-    public static final String PREFERRED_USERNAME = "preferred_username";
-    public static final String PROFILE = "profile";
-    public static final String PICTURE = "picture";
-    public static final String WEBSITE = "website";
-    public static final String EMAIL = "email";
-    public static final String EMAIL_VERIFIED = "email_verified";
-    public static final String GENDER = "gender";
-    public static final String BIRTHDATE = "birthdate";
-    public static final String ZONEINFO = "zoneinfo";
-    public static final String LOCALE = "locale";
-    public static final String PHONE_NUMBER = "phone_number";
-    public static final String PHONE_NUMBER_VERIFIED = "phone_number_verified";
-    public static final String ADDRESS = "address";
-    public static final String UPDATED_AT = "updated_at";
-    public static final String CLAIMS_LOCALES = "claims_locales";
-    // NOTE!!!  WE used to use @JsonUnwrapped on a UserClaimSet object.  This screws up otherClaims and the won't work
-    // anymore.  So don't have any @JsonUnwrapped!
-    @JsonProperty(NONCE)
-    protected String nonce;
-
-    @JsonProperty(SESSION_STATE)
-    protected String sessionState;
-
-    @JsonProperty(NAME)
-    protected String name;
-
-    @JsonProperty(GIVEN_NAME)
-    protected String givenName;
-
-    @JsonProperty(FAMILY_NAME)
-    protected String familyName;
-
-    @JsonProperty(MIDDLE_NAME)
-    protected String middleName;
-
-    @JsonProperty(NICKNAME)
-    protected String nickName;
-
-    @JsonProperty(PREFERRED_USERNAME)
-    protected String preferredUsername;
-
-    @JsonProperty(PROFILE)
-    protected String profile;
-
-    @JsonProperty(PICTURE)
-    protected String picture;
-
-    @JsonProperty(WEBSITE)
-    protected String website;
-
-    @JsonProperty(EMAIL)
-    protected String email;
-
-    @JsonProperty(EMAIL_VERIFIED)
-    protected Boolean emailVerified;
-
-    @JsonProperty(GENDER)
-    protected String gender;
-
-    @JsonProperty(BIRTHDATE)
-    protected String birthdate;
-
-    @JsonProperty(ZONEINFO)
-    protected String zoneinfo;
-
-    @JsonProperty(LOCALE)
-    protected String locale;
-
-    @JsonProperty(PHONE_NUMBER)
-    protected String phoneNumber;
-
-    @JsonProperty(PHONE_NUMBER_VERIFIED)
-    protected Boolean phoneNumberVerified;
-
-    @JsonProperty(ADDRESS)
-    protected AddressClaimSet address;
-
-    @JsonProperty(UPDATED_AT)
-    protected Long updatedAt;
-
-    @JsonProperty(CLAIMS_LOCALES)
-    protected String claimsLocales;
-
-    public String getNonce() {
-        return nonce;
-    }
-
-    public void setNonce(String nonce) {
-        this.nonce = nonce;
-    }
-
-    public String getSessionState() {
-        return sessionState;
-    }
-
-    public void setSessionState(String sessionState) {
-        this.sessionState = sessionState;
-    }
-
-    public String getName() {
-        return this.name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getGivenName() {
-        return this.givenName;
-    }
-
-    public void setGivenName(String givenName) {
-        this.givenName = givenName;
-    }
-
-    public String getFamilyName() {
-        return this.familyName;
-    }
-
-    public void setFamilyName(String familyName) {
-        this.familyName = familyName;
-    }
-
-    public String getMiddleName() {
-        return this.middleName;
-    }
-
-    public void setMiddleName(String middleName) {
-        this.middleName = middleName;
-    }
-
-    public String getNickName() {
-        return this.nickName;
-    }
-
-    public void setNickName(String nickName) {
-        this.nickName = nickName;
-    }
-
-    public String getPreferredUsername() {
-        return this.preferredUsername;
-    }
-
-    public void setPreferredUsername(String preferredUsername) {
-        this.preferredUsername = preferredUsername;
-    }
-
-    public String getProfile() {
-        return this.profile;
-    }
-
-    public void setProfile(String profile) {
-        this.profile = profile;
-    }
-
-    public String getPicture() {
-        return this.picture;
-    }
-
-    public void setPicture(String picture) {
-        this.picture = picture;
-    }
-
-    public String getWebsite() {
-        return this.website;
-    }
-
-    public void setWebsite(String website) {
-        this.website = website;
-    }
-
-    public String getEmail() {
-        return this.email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-    public Boolean getEmailVerified() {
-        return this.emailVerified;
-    }
-
-    public void setEmailVerified(Boolean emailVerified) {
-        this.emailVerified = emailVerified;
-    }
-
-    public String getGender() {
-        return this.gender;
-    }
-
-    public void setGender(String gender) {
-        this.gender = gender;
-    }
-
-    public String getBirthdate() {
-        return this.birthdate;
-    }
-
-    public void setBirthdate(String birthdate) {
-        this.birthdate = birthdate;
-    }
-
-    public String getZoneinfo() {
-        return this.zoneinfo;
-    }
-
-    public void setZoneinfo(String zoneinfo) {
-        this.zoneinfo = zoneinfo;
-    }
-
-    public String getLocale() {
-        return this.locale;
-    }
-
-    public void setLocale(String locale) {
-        this.locale = locale;
-    }
-
-    public String getPhoneNumber() {
-        return this.phoneNumber;
-    }
-
-    public void setPhoneNumber(String phoneNumber) {
-        this.phoneNumber = phoneNumber;
-    }
-
-    public Boolean getPhoneNumberVerified() {
-        return this.phoneNumberVerified;
-    }
-
-    public void setPhoneNumberVerified(Boolean phoneNumberVerified) {
-        this.phoneNumberVerified = phoneNumberVerified;
-    }
-
-    public AddressClaimSet getAddress() {
-        return address;
-    }
-
-    public void setAddress(AddressClaimSet address) {
-        this.address = address;
-    }
-
-    public Long getUpdatedAt() {
-        return this.updatedAt;
-    }
-
-    public void setUpdatedAt(Long updatedAt) {
-        this.updatedAt = updatedAt;
-    }
-
-    public String getClaimsLocales() {
-        return this.claimsLocales;
-    }
-
-    public void setClaimsLocales(String claimsLocales) {
-        this.claimsLocales = claimsLocales;
-    }
-
-}
+package org.keycloak.representations;
+
+import org.codehaus.jackson.annotate.JsonAnyGetter;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonUnwrapped;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IDToken extends JsonWebToken {
+    public static final String NONCE = "nonce";
+    public static final String SESSION_STATE = "session_state";
+    public static final String NAME = "name";
+    public static final String GIVEN_NAME = "given_name";
+    public static final String FAMILY_NAME = "family_name";
+    public static final String MIDDLE_NAME = "middle_name";
+    public static final String NICKNAME = "nickname";
+    public static final String PREFERRED_USERNAME = "preferred_username";
+    public static final String PROFILE = "profile";
+    public static final String PICTURE = "picture";
+    public static final String WEBSITE = "website";
+    public static final String EMAIL = "email";
+    public static final String EMAIL_VERIFIED = "email_verified";
+    public static final String GENDER = "gender";
+    public static final String BIRTHDATE = "birthdate";
+    public static final String ZONEINFO = "zoneinfo";
+    public static final String LOCALE = "locale";
+    public static final String PHONE_NUMBER = "phone_number";
+    public static final String PHONE_NUMBER_VERIFIED = "phone_number_verified";
+    public static final String ADDRESS = "address";
+    public static final String UPDATED_AT = "updated_at";
+    public static final String CLAIMS_LOCALES = "claims_locales";
+    // NOTE!!!  WE used to use @JsonUnwrapped on a UserClaimSet object.  This screws up otherClaims and the won't work
+    // anymore.  So don't have any @JsonUnwrapped!
+    @JsonProperty(NONCE)
+    protected String nonce;
+
+    @JsonProperty(SESSION_STATE)
+    protected String sessionState;
+
+    @JsonProperty(NAME)
+    protected String name;
+
+    @JsonProperty(GIVEN_NAME)
+    protected String givenName;
+
+    @JsonProperty(FAMILY_NAME)
+    protected String familyName;
+
+    @JsonProperty(MIDDLE_NAME)
+    protected String middleName;
+
+    @JsonProperty(NICKNAME)
+    protected String nickName;
+
+    @JsonProperty(PREFERRED_USERNAME)
+    protected String preferredUsername;
+
+    @JsonProperty(PROFILE)
+    protected String profile;
+
+    @JsonProperty(PICTURE)
+    protected String picture;
+
+    @JsonProperty(WEBSITE)
+    protected String website;
+
+    @JsonProperty(EMAIL)
+    protected String email;
+
+    @JsonProperty(EMAIL_VERIFIED)
+    protected Boolean emailVerified;
+
+    @JsonProperty(GENDER)
+    protected String gender;
+
+    @JsonProperty(BIRTHDATE)
+    protected String birthdate;
+
+    @JsonProperty(ZONEINFO)
+    protected String zoneinfo;
+
+    @JsonProperty(LOCALE)
+    protected String locale;
+
+    @JsonProperty(PHONE_NUMBER)
+    protected String phoneNumber;
+
+    @JsonProperty(PHONE_NUMBER_VERIFIED)
+    protected Boolean phoneNumberVerified;
+
+    @JsonProperty(ADDRESS)
+    protected AddressClaimSet address;
+
+    @JsonProperty(UPDATED_AT)
+    protected Long updatedAt;
+
+    @JsonProperty(CLAIMS_LOCALES)
+    protected String claimsLocales;
+
+    public String getNonce() {
+        return nonce;
+    }
+
+    public void setNonce(String nonce) {
+        this.nonce = nonce;
+    }
+
+    public String getSessionState() {
+        return sessionState;
+    }
+
+    public void setSessionState(String sessionState) {
+        this.sessionState = sessionState;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getGivenName() {
+        return this.givenName;
+    }
+
+    public void setGivenName(String givenName) {
+        this.givenName = givenName;
+    }
+
+    public String getFamilyName() {
+        return this.familyName;
+    }
+
+    public void setFamilyName(String familyName) {
+        this.familyName = familyName;
+    }
+
+    public String getMiddleName() {
+        return this.middleName;
+    }
+
+    public void setMiddleName(String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getNickName() {
+        return this.nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getPreferredUsername() {
+        return this.preferredUsername;
+    }
+
+    public void setPreferredUsername(String preferredUsername) {
+        this.preferredUsername = preferredUsername;
+    }
+
+    public String getProfile() {
+        return this.profile;
+    }
+
+    public void setProfile(String profile) {
+        this.profile = profile;
+    }
+
+    public String getPicture() {
+        return this.picture;
+    }
+
+    public void setPicture(String picture) {
+        this.picture = picture;
+    }
+
+    public String getWebsite() {
+        return this.website;
+    }
+
+    public void setWebsite(String website) {
+        this.website = website;
+    }
+
+    public String getEmail() {
+        return this.email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public Boolean getEmailVerified() {
+        return this.emailVerified;
+    }
+
+    public void setEmailVerified(Boolean emailVerified) {
+        this.emailVerified = emailVerified;
+    }
+
+    public String getGender() {
+        return this.gender;
+    }
+
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+
+    public String getBirthdate() {
+        return this.birthdate;
+    }
+
+    public void setBirthdate(String birthdate) {
+        this.birthdate = birthdate;
+    }
+
+    public String getZoneinfo() {
+        return this.zoneinfo;
+    }
+
+    public void setZoneinfo(String zoneinfo) {
+        this.zoneinfo = zoneinfo;
+    }
+
+    public String getLocale() {
+        return this.locale;
+    }
+
+    public void setLocale(String locale) {
+        this.locale = locale;
+    }
+
+    public String getPhoneNumber() {
+        return this.phoneNumber;
+    }
+
+    public void setPhoneNumber(String phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
+
+    public Boolean getPhoneNumberVerified() {
+        return this.phoneNumberVerified;
+    }
+
+    public void setPhoneNumberVerified(Boolean phoneNumberVerified) {
+        this.phoneNumberVerified = phoneNumberVerified;
+    }
+
+    public AddressClaimSet getAddress() {
+        return address;
+    }
+
+    public void setAddress(AddressClaimSet address) {
+        this.address = address;
+    }
+
+    public Long getUpdatedAt() {
+        return this.updatedAt;
+    }
+
+    public void setUpdatedAt(Long updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getClaimsLocales() {
+        return this.claimsLocales;
+    }
+
+    public void setClaimsLocales(String claimsLocales) {
+        this.claimsLocales = claimsLocales;
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/representations/JsonWebToken.java b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
index 8db6ef3..f714d4f 100755
--- a/core/src/main/java/org/keycloak/representations/JsonWebToken.java
+++ b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
@@ -1,176 +1,176 @@
-package org.keycloak.representations;
-
-import org.codehaus.jackson.annotate.JsonAnyGetter;
-import org.codehaus.jackson.annotate.JsonAnySetter;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.keycloak.util.Time;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JsonWebToken implements Serializable {
-    @JsonProperty("jti")
-    protected String id;
-    @JsonProperty("exp")
-    protected int expiration;
-    @JsonProperty("nbf")
-    protected int notBefore;
-    @JsonProperty("iat")
-    protected int issuedAt;
-    @JsonProperty("iss")
-    protected String issuer;
-    @JsonProperty("aud")
-    protected String audience;
-    @JsonProperty("sub")
-    protected String subject;
-    @JsonProperty("typ")
-    protected String type;
-    @JsonProperty("azp")
-    public String issuedFor;
-    protected Map<String, Object> otherClaims = new HashMap<String, Object>();
-
-    public String getId() {
-        return id;
-    }
-
-    public JsonWebToken id(String id) {
-        this.id = id;
-        return this;
-    }
-
-
-    public int getExpiration() {
-        return expiration;
-    }
-
-    public JsonWebToken expiration(int expiration) {
-        this.expiration = expiration;
-        return this;
-    }
-
-    @JsonIgnore
-    public boolean isExpired() {
-        return Time.currentTime() > expiration;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public JsonWebToken notBefore(int notBefore) {
-        this.notBefore = notBefore;
-        return this;
-    }
-
-
-    @JsonIgnore
-    public boolean isNotBefore() {
-        return Time.currentTime() >= notBefore;
-
-    }
-
-    /**
-     * Tests that the token is not expired and is not-before.
-     *
-     * @return
-     */
-    @JsonIgnore
-    public boolean isActive() {
-        return (!isExpired() || expiration == 0) && (isNotBefore() || notBefore == 0);
-    }
-
-    public int getIssuedAt() {
-        return issuedAt;
-    }
-
-    /**
-     * Set issuedAt to the current time
-     */
-    @JsonIgnore
-    public JsonWebToken issuedNow() {
-        issuedAt = Time.currentTime();
-        return this;
-    }
-
-    public JsonWebToken issuedAt(int issuedAt) {
-        this.issuedAt = issuedAt;
-        return this;
-    }
-
-
-    public String getIssuer() {
-        return issuer;
-    }
-
-    public JsonWebToken issuer(String issuer) {
-        this.issuer = issuer;
-        return this;
-    }
-
-
-    public String getAudience() {
-        return audience;
-    }
-
-    public JsonWebToken audience(String audience) {
-        this.audience = audience;
-        return this;
-    }
-
-    public String getSubject() {
-        return subject;
-    }
-
-    public JsonWebToken subject(String subject) {
-        this.subject = subject;
-        return this;
-    }
-
-    public void setSubject(String subject) {
-        this.subject = subject;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public JsonWebToken type(String type) {
-        this.type = type;
-        return this;
-    }
-
-    /**
-     * OAuth client the token was issued for.
-     *
-     * @return
-     */
-    public String getIssuedFor() {
-        return issuedFor;
-    }
-
-    public JsonWebToken issuedFor(String issuedFor) {
-        this.issuedFor = issuedFor;
-        return this;
-    }
-
-    /**
-     * This is a map of any other claims and data that might be in the IDToken.  Could be custom claims set up by the auth server
-     *
-     * @return
-     */
-    @JsonAnyGetter
-    public Map<String, Object> getOtherClaims() {
-        return otherClaims;
-    }
-
-    @JsonAnySetter
-    public void setOtherClaims(String name, Object value) {
-        otherClaims.put(name, value);
-    }
-}
+package org.keycloak.representations;
+
+import org.codehaus.jackson.annotate.JsonAnyGetter;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.keycloak.util.Time;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JsonWebToken implements Serializable {
+    @JsonProperty("jti")
+    protected String id;
+    @JsonProperty("exp")
+    protected int expiration;
+    @JsonProperty("nbf")
+    protected int notBefore;
+    @JsonProperty("iat")
+    protected int issuedAt;
+    @JsonProperty("iss")
+    protected String issuer;
+    @JsonProperty("aud")
+    protected String audience;
+    @JsonProperty("sub")
+    protected String subject;
+    @JsonProperty("typ")
+    protected String type;
+    @JsonProperty("azp")
+    public String issuedFor;
+    protected Map<String, Object> otherClaims = new HashMap<String, Object>();
+
+    public String getId() {
+        return id;
+    }
+
+    public JsonWebToken id(String id) {
+        this.id = id;
+        return this;
+    }
+
+
+    public int getExpiration() {
+        return expiration;
+    }
+
+    public JsonWebToken expiration(int expiration) {
+        this.expiration = expiration;
+        return this;
+    }
+
+    @JsonIgnore
+    public boolean isExpired() {
+        return Time.currentTime() > expiration;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public JsonWebToken notBefore(int notBefore) {
+        this.notBefore = notBefore;
+        return this;
+    }
+
+
+    @JsonIgnore
+    public boolean isNotBefore() {
+        return Time.currentTime() >= notBefore;
+
+    }
+
+    /**
+     * Tests that the token is not expired and is not-before.
+     *
+     * @return
+     */
+    @JsonIgnore
+    public boolean isActive() {
+        return (!isExpired() || expiration == 0) && (isNotBefore() || notBefore == 0);
+    }
+
+    public int getIssuedAt() {
+        return issuedAt;
+    }
+
+    /**
+     * Set issuedAt to the current time
+     */
+    @JsonIgnore
+    public JsonWebToken issuedNow() {
+        issuedAt = Time.currentTime();
+        return this;
+    }
+
+    public JsonWebToken issuedAt(int issuedAt) {
+        this.issuedAt = issuedAt;
+        return this;
+    }
+
+
+    public String getIssuer() {
+        return issuer;
+    }
+
+    public JsonWebToken issuer(String issuer) {
+        this.issuer = issuer;
+        return this;
+    }
+
+
+    public String getAudience() {
+        return audience;
+    }
+
+    public JsonWebToken audience(String audience) {
+        this.audience = audience;
+        return this;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public JsonWebToken subject(String subject) {
+        this.subject = subject;
+        return this;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public JsonWebToken type(String type) {
+        this.type = type;
+        return this;
+    }
+
+    /**
+     * OAuth client the token was issued for.
+     *
+     * @return
+     */
+    public String getIssuedFor() {
+        return issuedFor;
+    }
+
+    public JsonWebToken issuedFor(String issuedFor) {
+        this.issuedFor = issuedFor;
+        return this;
+    }
+
+    /**
+     * This is a map of any other claims and data that might be in the IDToken.  Could be custom claims set up by the auth server
+     *
+     * @return
+     */
+    @JsonAnyGetter
+    public Map<String, Object> getOtherClaims() {
+        return otherClaims;
+    }
+
+    @JsonAnySetter
+    public void setOtherClaims(String name, Object value) {
+        otherClaims.put(name, value);
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/RefreshToken.java b/core/src/main/java/org/keycloak/representations/RefreshToken.java
index 25bf9a5..7bc1edf 100755
--- a/core/src/main/java/org/keycloak/representations/RefreshToken.java
+++ b/core/src/main/java/org/keycloak/representations/RefreshToken.java
@@ -1,42 +1,42 @@
-package org.keycloak.representations;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RefreshToken extends AccessToken {
-
-
-    private RefreshToken() {
-        type("REFRESH");
-    }
-
-    /**
-     * Deep copies issuer, subject, issuedFor, sessionState, realmAccess, and resourceAccess
-     * from AccessToken.
-     *
-     * @param token
-     */
-    public RefreshToken(AccessToken token) {
-        this();
-        this.clientSession = token.getClientSession();
-        this.issuer = token.issuer;
-        this.subject = token.subject;
-        this.issuedFor = token.issuedFor;
-        this.sessionState = token.sessionState;
-        if (token.realmAccess != null) {
-            realmAccess = token.realmAccess.clone();
-        }
-        if (token.resourceAccess != null) {
-            resourceAccess = new HashMap<String, Access>();
-            for (Map.Entry<String, Access> entry : token.resourceAccess.entrySet()) {
-                resourceAccess.put(entry.getKey(), entry.getValue().clone());
-            }
-        }
-    }
-}
+package org.keycloak.representations;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RefreshToken extends AccessToken {
+
+
+    private RefreshToken() {
+        type("REFRESH");
+    }
+
+    /**
+     * Deep copies issuer, subject, issuedFor, sessionState, realmAccess, and resourceAccess
+     * from AccessToken.
+     *
+     * @param token
+     */
+    public RefreshToken(AccessToken token) {
+        this();
+        this.clientSession = token.getClientSession();
+        this.issuer = token.issuer;
+        this.subject = token.subject;
+        this.issuedFor = token.issuedFor;
+        this.sessionState = token.sessionState;
+        if (token.realmAccess != null) {
+            realmAccess = token.realmAccess.clone();
+        }
+        if (token.resourceAccess != null) {
+            resourceAccess = new HashMap<String, Access>();
+            for (Map.Entry<String, Access> entry : token.resourceAccess.entrySet()) {
+                resourceAccess.put(entry.getKey(), entry.getValue().clone());
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/org/keycloak/RSATokenVerifier.java b/core/src/main/java/org/keycloak/RSATokenVerifier.java
index 1c324d6..9bd544d 100755
--- a/core/src/main/java/org/keycloak/RSATokenVerifier.java
+++ b/core/src/main/java/org/keycloak/RSATokenVerifier.java
@@ -1,59 +1,59 @@
-package org.keycloak;
-
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.representations.AccessToken;
-
-import java.io.IOException;
-import java.security.PublicKey;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RSATokenVerifier {
-    public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realmUrl) throws VerificationException {
-        return verifyToken(tokenString, realmKey, realmUrl, true);
-    }
-
-    public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realmUrl, boolean checkActive) throws VerificationException {
-        JWSInput input = null;
-        try {
-            input = new JWSInput(tokenString);
-        } catch (Exception e) {
-            throw new VerificationException("Couldn't parse token", e);
-        }
-        if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
-
-        AccessToken token;
-        try {
-            token = input.readJsonContent(AccessToken.class);
-        } catch (IOException e) {
-            throw new VerificationException("Couldn't parse token signature", e);
-        }
-        String user = token.getSubject();
-        if (user == null) {
-            throw new VerificationException("Token user was null.");
-        }
-        if (realmUrl == null) {
-            throw new VerificationException("Realm URL is null. Make sure to add auth-server-url to the configuration of your adapter!");
-        }
-        if (!realmUrl.equals(token.getIssuer())) {
-            throw new VerificationException("Token audience doesn't match domain. Token issuer is " + token.getIssuer() + ", but URL from configuration is " + realmUrl);
-
-        }
-        if (checkActive && !token.isActive()) {
-            throw new VerificationException("Token is not active.");
-        }
-
-        return token;
-    }
-
-    private static boolean isPublicKeyValid(JWSInput input, PublicKey realmKey) throws VerificationException {
-        try {
-            return RSAProvider.verify(input, realmKey);
-        } catch (Exception e) {
-            throw new VerificationException("Token signature not validated.", e);
-        }
-    }
-}
+package org.keycloak;
+
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.representations.AccessToken;
+
+import java.io.IOException;
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RSATokenVerifier {
+    public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realmUrl) throws VerificationException {
+        return verifyToken(tokenString, realmKey, realmUrl, true);
+    }
+
+    public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realmUrl, boolean checkActive) throws VerificationException {
+        JWSInput input = null;
+        try {
+            input = new JWSInput(tokenString);
+        } catch (Exception e) {
+            throw new VerificationException("Couldn't parse token", e);
+        }
+        if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
+
+        AccessToken token;
+        try {
+            token = input.readJsonContent(AccessToken.class);
+        } catch (IOException e) {
+            throw new VerificationException("Couldn't parse token signature", e);
+        }
+        String user = token.getSubject();
+        if (user == null) {
+            throw new VerificationException("Token user was null.");
+        }
+        if (realmUrl == null) {
+            throw new VerificationException("Realm URL is null. Make sure to add auth-server-url to the configuration of your adapter!");
+        }
+        if (!realmUrl.equals(token.getIssuer())) {
+            throw new VerificationException("Token audience doesn't match domain. Token issuer is " + token.getIssuer() + ", but URL from configuration is " + realmUrl);
+
+        }
+        if (checkActive && !token.isActive()) {
+            throw new VerificationException("Token is not active.");
+        }
+
+        return token;
+    }
+
+    private static boolean isPublicKeyValid(JWSInput input, PublicKey realmKey) throws VerificationException {
+        try {
+            return RSAProvider.verify(input, realmKey);
+        } catch (Exception e) {
+            throw new VerificationException("Token signature not validated.", e);
+        }
+    }
+}
diff --git a/core/src/main/java/org/keycloak/TokenIdGenerator.java b/core/src/main/java/org/keycloak/TokenIdGenerator.java
index 8ac61d3..6bf03ff 100755
--- a/core/src/main/java/org/keycloak/TokenIdGenerator.java
+++ b/core/src/main/java/org/keycloak/TokenIdGenerator.java
@@ -1,16 +1,16 @@
-package org.keycloak;
-
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class TokenIdGenerator {
-    private static final AtomicLong counter = new AtomicLong();
-
-    public static String generateId() {
-        return UUID.randomUUID().toString() + "-" + System.currentTimeMillis();
-    }
-}
+package org.keycloak;
+
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class TokenIdGenerator {
+    private static final AtomicLong counter = new AtomicLong();
+
+    public static String generateId() {
+        return UUID.randomUUID().toString() + "-" + System.currentTimeMillis();
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/Base64Url.java b/core/src/main/java/org/keycloak/util/Base64Url.java
index e4e63b1..a57ed1a 100755
--- a/core/src/main/java/org/keycloak/util/Base64Url.java
+++ b/core/src/main/java/org/keycloak/util/Base64Url.java
@@ -1,44 +1,44 @@
-package org.keycloak.util;
-
-
-import net.iharder.Base64;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class Base64Url {
-    public static String encode(byte[] bytes) {
-        String s = Base64.encodeBytes(bytes);
-        s = s.split("=")[0]; // Remove any trailing '='s
-        s = s.replace('+', '-'); // 62nd char of encoding
-        s = s.replace('/', '_'); // 63rd char of encoding
-        return s;
-    }
-
-    public static byte[] decode(String s) {
-        s = s.replace('-', '+'); // 62nd char of encoding
-        s = s.replace('_', '/'); // 63rd char of encoding
-        switch (s.length() % 4) // Pad with trailing '='s
-        {
-            case 0:
-                break; // No pad chars in this case
-            case 2:
-                s += "==";
-                break; // Two pad chars
-            case 3:
-                s += "=";
-                break; // One pad char
-            default:
-                throw new RuntimeException(
-                        "Illegal base64url string!");
-        }
-        try {
-            return Base64.decode(s);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-}
+package org.keycloak.util;
+
+
+import net.iharder.Base64;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Base64Url {
+    public static String encode(byte[] bytes) {
+        String s = Base64.encodeBytes(bytes);
+        s = s.split("=")[0]; // Remove any trailing '='s
+        s = s.replace('+', '-'); // 62nd char of encoding
+        s = s.replace('/', '_'); // 63rd char of encoding
+        return s;
+    }
+
+    public static byte[] decode(String s) {
+        s = s.replace('-', '+'); // 62nd char of encoding
+        s = s.replace('_', '/'); // 63rd char of encoding
+        switch (s.length() % 4) // Pad with trailing '='s
+        {
+            case 0:
+                break; // No pad chars in this case
+            case 2:
+                s += "==";
+                break; // Two pad chars
+            case 3:
+                s += "=";
+                break; // One pad char
+            default:
+                throw new RuntimeException(
+                        "Illegal base64url string!");
+        }
+        try {
+            return Base64.decode(s);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+}
diff --git a/core/src/main/java/org/keycloak/util/BasicAuthHelper.java b/core/src/main/java/org/keycloak/util/BasicAuthHelper.java
index 8806542..d5f8918 100755
--- a/core/src/main/java/org/keycloak/util/BasicAuthHelper.java
+++ b/core/src/main/java/org/keycloak/util/BasicAuthHelper.java
@@ -1,44 +1,44 @@
-package org.keycloak.util;
-
-import net.iharder.Base64;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class BasicAuthHelper
-{
-    public static String createHeader(String username, String password)
-    {
-        StringBuffer buf = new StringBuffer(username);
-        buf.append(':').append(password);
-        try
-        {
-            return "Basic " + Base64.encodeBytes(buf.toString().getBytes("UTF-8"));
-        }
-        catch (UnsupportedEncodingException e)
-        {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static String[] parseHeader(String header)
-    {
-        if (header.length() < 6) return null;
-        String type = header.substring(0, 5);
-        type = type.toLowerCase();
-        if (!type.equalsIgnoreCase("Basic")) return null;
-        String val = header.substring(6);
-        try {
-            val = new String(Base64.decode(val.getBytes()));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        String[] split = val.split(":");
-        if (split.length != 2) return null;
-        return split;
-    }
-}
+package org.keycloak.util;
+
+import net.iharder.Base64;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class BasicAuthHelper
+{
+    public static String createHeader(String username, String password)
+    {
+        StringBuffer buf = new StringBuffer(username);
+        buf.append(':').append(password);
+        try
+        {
+            return "Basic " + Base64.encodeBytes(buf.toString().getBytes("UTF-8"));
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String[] parseHeader(String header)
+    {
+        if (header.length() < 6) return null;
+        String type = header.substring(0, 5);
+        type = type.toLowerCase();
+        if (!type.equalsIgnoreCase("Basic")) return null;
+        String val = header.substring(6);
+        try {
+            val = new String(Base64.decode(val.getBytes()));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        String[] split = val.split(":");
+        if (split.length != 2) return null;
+        return split;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/CertificateUtils.java b/core/src/main/java/org/keycloak/util/CertificateUtils.java
index aefd740..8a47c7f 100755
--- a/core/src/main/java/org/keycloak/util/CertificateUtils.java
+++ b/core/src/main/java/org/keycloak/util/CertificateUtils.java
@@ -1,166 +1,166 @@
-package org.keycloak.util;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.cert.X509Certificate;
-import java.util.Calendar;
-import java.util.Date;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.KeyPurposeId;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.X509ExtensionUtils;
-import org.bouncycastle.cert.X509v1CertificateBuilder;
-import org.bouncycastle.cert.X509v3CertificateBuilder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.crypto.util.PrivateKeyFactory;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
-import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
-import org.bouncycastle.operator.DigestCalculator;
-import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
-import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-
-/**
- * The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
- * @version $Revision: 2 $
- */
-public class CertificateUtils {
-    static {
-        BouncyIntegration.init();
-    }
-
-    /**
-     * Generates version 3 {@link java.security.cert.X509Certificate}.
-     *
-     * @param keyPair the key pair
-     * @param caPrivateKey the CA private key
-     * @param caCert the CA certificate
-     * @param subject the subject name
-     * 
-     * @return the x509 certificate
-     * 
-     * @throws Exception the exception
-     */
-    public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
-            String subject) throws Exception {
-
-        try {
-            X500Name subjectDN = new X500Name("CN=" + subject);
-
-            // Serial Number
-            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
-            BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
-
-            // Validity
-            Date notBefore = new Date(System.currentTimeMillis());
-            Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
-
-            // SubjectPublicKeyInfo
-            SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
-                    .getEncoded()));
-
-            X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
-                    serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
-
-            DigestCalculator digCalc = new BcDigestCalculatorProvider()
-                    .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
-            X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
-
-            // Subject Key Identifier
-            certGen.addExtension(Extension.subjectKeyIdentifier, false,
-                    x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
-
-            // Authority Key Identifier
-            certGen.addExtension(Extension.authorityKeyIdentifier, false,
-                    x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
-
-            // Key Usage
-            certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
-                    | KeyUsage.cRLSign));
-
-            // Extended Key Usage
-            KeyPurposeId[] EKU = new KeyPurposeId[2];
-            EKU[0] = KeyPurposeId.id_kp_emailProtection;
-            EKU[1] = KeyPurposeId.id_kp_serverAuth;
-
-            certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
-
-            // Basic Constraints
-            certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
-
-            // Content Signer
-            ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
-
-            // Certificate
-            return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
-        } catch (Exception e) {
-            throw new RuntimeException("Error creating X509v3Certificate.", e);
-        }
-    }
-
-    /**
-     * Generate version 1 self signed {@link java.security.cert.X509Certificate}..
-     *
-     * @param caKeyPair the CA key pair
-     * @param subject the subject name
-     * 
-     * @return the x509 certificate
-     * 
-     * @throws Exception the exception
-     */
-    public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
-
-        try {
-            X500Name subjectDN = new X500Name("CN=" + subject);
-            BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
-            Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
-            Calendar calendar = Calendar.getInstance();
-            calendar.add(Calendar.YEAR, 10);
-            Date validityEndDate = new Date(calendar.getTime().getTime());
-            SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
-
-            X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
-                    validityEndDate, subjectDN, subPubKeyInfo);
-            X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
-
-            return new JcaX509CertificateConverter().getCertificate(holder);
-        } catch (Exception e) {
-            throw new RuntimeException("Error creating X509v1Certificate.", e);
-        }
-    }
-
-    /**
-     * Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
-     *
-     * @param privateKey the private key
-     *
-     * @return the content signer
-     */
-    public static ContentSigner createSigner(PrivateKey privateKey) {
-        try {
-            AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
-            AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
-
-            return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
-                    .build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
-        } catch (Exception e) {
-            throw new RuntimeException("Could not create content signer.", e);
-        }
-    }
-}
+package org.keycloak.util;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.KeyPurposeId;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509ExtensionUtils;
+import org.bouncycastle.cert.X509v1CertificateBuilder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.crypto.util.PrivateKeyFactory;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
+import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
+/**
+ * The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
+ * @version $Revision: 2 $
+ */
+public class CertificateUtils {
+    static {
+        BouncyIntegration.init();
+    }
+
+    /**
+     * Generates version 3 {@link java.security.cert.X509Certificate}.
+     *
+     * @param keyPair the key pair
+     * @param caPrivateKey the CA private key
+     * @param caCert the CA certificate
+     * @param subject the subject name
+     * 
+     * @return the x509 certificate
+     * 
+     * @throws Exception the exception
+     */
+    public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
+            String subject) throws Exception {
+
+        try {
+            X500Name subjectDN = new X500Name("CN=" + subject);
+
+            // Serial Number
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
+
+            // Validity
+            Date notBefore = new Date(System.currentTimeMillis());
+            Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
+
+            // SubjectPublicKeyInfo
+            SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
+                    .getEncoded()));
+
+            X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
+                    serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
+
+            DigestCalculator digCalc = new BcDigestCalculatorProvider()
+                    .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
+            X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
+
+            // Subject Key Identifier
+            certGen.addExtension(Extension.subjectKeyIdentifier, false,
+                    x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
+
+            // Authority Key Identifier
+            certGen.addExtension(Extension.authorityKeyIdentifier, false,
+                    x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
+
+            // Key Usage
+            certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
+                    | KeyUsage.cRLSign));
+
+            // Extended Key Usage
+            KeyPurposeId[] EKU = new KeyPurposeId[2];
+            EKU[0] = KeyPurposeId.id_kp_emailProtection;
+            EKU[1] = KeyPurposeId.id_kp_serverAuth;
+
+            certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
+
+            // Basic Constraints
+            certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
+
+            // Content Signer
+            ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
+
+            // Certificate
+            return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
+        } catch (Exception e) {
+            throw new RuntimeException("Error creating X509v3Certificate.", e);
+        }
+    }
+
+    /**
+     * Generate version 1 self signed {@link java.security.cert.X509Certificate}..
+     *
+     * @param caKeyPair the CA key pair
+     * @param subject the subject name
+     * 
+     * @return the x509 certificate
+     * 
+     * @throws Exception the exception
+     */
+    public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
+
+        try {
+            X500Name subjectDN = new X500Name("CN=" + subject);
+            BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
+            Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
+            Calendar calendar = Calendar.getInstance();
+            calendar.add(Calendar.YEAR, 10);
+            Date validityEndDate = new Date(calendar.getTime().getTime());
+            SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
+
+            X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
+                    validityEndDate, subjectDN, subPubKeyInfo);
+            X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
+
+            return new JcaX509CertificateConverter().getCertificate(holder);
+        } catch (Exception e) {
+            throw new RuntimeException("Error creating X509v1Certificate.", e);
+        }
+    }
+
+    /**
+     * Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
+     *
+     * @param privateKey the private key
+     *
+     * @return the content signer
+     */
+    public static ContentSigner createSigner(PrivateKey privateKey) {
+        try {
+            AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
+            AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
+
+            return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
+                    .build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
+        } catch (Exception e) {
+            throw new RuntimeException("Could not create content signer.", e);
+        }
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/EnvUtil.java b/core/src/main/java/org/keycloak/util/EnvUtil.java
index eafc7f6..f40db1e 100755
--- a/core/src/main/java/org/keycloak/util/EnvUtil.java
+++ b/core/src/main/java/org/keycloak/util/EnvUtil.java
@@ -1,37 +1,37 @@
-package org.keycloak.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public final class EnvUtil {
-    private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
-
-    private EnvUtil() {
-
-    }
-
-    /**
-     * Replaces any ${} strings with their corresponding environent variable.
-     *
-     * @param val
-     * @return
-     */
-    public static String replace(String val) {
-        Matcher matcher = p.matcher(val);
-        StringBuffer buf = new StringBuffer();
-        while (matcher.find()) {
-            String envVar = matcher.group(1);
-            String envVal = System.getProperty(envVar);
-            if (envVal == null) envVal = "NOT-SPECIFIED";
-            matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
-        }
-        matcher.appendTail(buf);
-        return buf.toString();
-    }
-}
-
-
+package org.keycloak.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public final class EnvUtil {
+    private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
+
+    private EnvUtil() {
+
+    }
+
+    /**
+     * Replaces any ${} strings with their corresponding environent variable.
+     *
+     * @param val
+     * @return
+     */
+    public static String replace(String val) {
+        Matcher matcher = p.matcher(val);
+        StringBuffer buf = new StringBuffer();
+        while (matcher.find()) {
+            String envVar = matcher.group(1);
+            String envVal = System.getProperty(envVar);
+            if (envVal == null) envVal = "NOT-SPECIFIED";
+            matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
+        }
+        matcher.appendTail(buf);
+        return buf.toString();
+    }
+}
+
+
diff --git a/core/src/main/java/org/keycloak/util/FindFile.java b/core/src/main/java/org/keycloak/util/FindFile.java
index 07edebc..d7f1579 100755
--- a/core/src/main/java/org/keycloak/util/FindFile.java
+++ b/core/src/main/java/org/keycloak/util/FindFile.java
@@ -1,37 +1,37 @@
-package org.keycloak.util;
-
-import org.keycloak.constants.GenericConstants;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class FindFile {
-    public static InputStream findFile(String keycloakConfigFile) {
-        if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
-            String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
-            // Try current class classloader first
-            InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
-            if (is == null) {
-                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
-            }
-
-            if (is != null) {
-                return is;
-            } else {
-                throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
-            }
-        } else {
-            // Fallback to file
-            try {
-                return new FileInputStream(keycloakConfigFile);
-            } catch (FileNotFoundException fnfe) {
-                throw new RuntimeException(fnfe);
-            }
-        }
-    }
-}
+package org.keycloak.util;
+
+import org.keycloak.constants.GenericConstants;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class FindFile {
+    public static InputStream findFile(String keycloakConfigFile) {
+        if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
+            String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
+            // Try current class classloader first
+            InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
+            if (is == null) {
+                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
+            }
+
+            if (is != null) {
+                return is;
+            } else {
+                throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
+            }
+        } else {
+            // Fallback to file
+            try {
+                return new FileInputStream(keycloakConfigFile);
+            } catch (FileNotFoundException fnfe) {
+                throw new RuntimeException(fnfe);
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/KeycloakUriBuilder.java b/core/src/main/java/org/keycloak/util/KeycloakUriBuilder.java
index 2742a4e..f27979c 100755
--- a/core/src/main/java/org/keycloak/util/KeycloakUriBuilder.java
+++ b/core/src/main/java/org/keycloak/util/KeycloakUriBuilder.java
@@ -1,713 +1,713 @@
-package org.keycloak.util;
-
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakUriBuilder {
-
-    private String host;
-    private String scheme;
-    private int port = -1;
-
-    private String userInfo;
-    private String path;
-    private String query;
-    private String fragment;
-    private String ssp;
-    private String authority;
-
-    public static KeycloakUriBuilder fromUri(URI uri) {
-        return new KeycloakUriBuilder().uri(uri);
-    }
-
-    public static KeycloakUriBuilder fromUri(String uriTemplate) {
-        return new KeycloakUriBuilder().uri(uriTemplate);
-    }
-
-    public static KeycloakUriBuilder fromPath(String path) throws IllegalArgumentException {
-        return new KeycloakUriBuilder().path(path);
-    }
-
-
-    public KeycloakUriBuilder clone() {
-        KeycloakUriBuilder impl = new KeycloakUriBuilder();
-        impl.host = host;
-        impl.scheme = scheme;
-        impl.port = port;
-        impl.userInfo = userInfo;
-        impl.path = path;
-        impl.query = query;
-        impl.fragment = fragment;
-        impl.ssp = ssp;
-        impl.authority = authority;
-
-        return impl;
-    }
-
-    private static final Pattern opaqueUri = Pattern.compile("^([^:/?#]+):([^/].*)");
-    private static final Pattern hierarchicalUri = Pattern.compile("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
-    private static final Pattern hostPortPattern = Pattern.compile("([^/:]+):(\\d+)");
-
-    public static boolean compare(String s1, String s2) {
-        if (s1 == s2) return true;
-        if (s1 == null || s2 == null) return false;
-        return s1.equals(s2);
-    }
-
-    public static URI relativize(URI from, URI to) {
-        if (!compare(from.getScheme(), to.getScheme())) return to;
-        if (!compare(from.getHost(), to.getHost())) return to;
-        if (from.getPort() != to.getPort()) return to;
-        if (from.getPath() == null && to.getPath() == null) return URI.create("");
-        else if (from.getPath() == null) return URI.create(to.getPath());
-        else if (to.getPath() == null) return to;
-
-
-        String fromPath = from.getPath();
-        if (fromPath.startsWith("/")) fromPath = fromPath.substring(1);
-        String[] fsplit = fromPath.split("/");
-        String toPath = to.getPath();
-        if (toPath.startsWith("/")) toPath = toPath.substring(1);
-        String[] tsplit = toPath.split("/");
-
-        int f = 0;
-
-        for (; f < fsplit.length && f < tsplit.length; f++) {
-            if (!fsplit[f].equals(tsplit[f])) break;
-        }
-
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromPath("");
-        for (int i = f; i < fsplit.length; i++) builder.path("..");
-        for (int i = f; i < tsplit.length; i++) builder.path(tsplit[i]);
-        return builder.build();
-    }
-
-    /**
-     * You may put path parameters anywhere within the uriTemplate except port
-     *
-     * @param uriTemplate
-     * @return
-     */
-    public static KeycloakUriBuilder fromTemplate(String uriTemplate) {
-        KeycloakUriBuilder impl = new KeycloakUriBuilder();
-        impl.uriTemplate(uriTemplate);
-        return impl;
-    }
-
-    /**
-     * You may put path parameters anywhere within the uriTemplate except port
-     *
-     * @param uriTemplate
-     * @return
-     */
-    public KeycloakUriBuilder uriTemplate(String uriTemplate) {
-        if (uriTemplate == null) throw new IllegalArgumentException("uriTemplate parameter is null");
-        Matcher opaque = opaqueUri.matcher(uriTemplate);
-        if (opaque.matches()) {
-            this.authority = null;
-            this.host = null;
-            this.port = -1;
-            this.userInfo = null;
-            this.query = null;
-            this.scheme = opaque.group(1);
-            this.ssp = opaque.group(2);
-            return this;
-        } else {
-            Matcher match = hierarchicalUri.matcher(uriTemplate);
-            if (match.matches()) {
-                ssp = null;
-                return parseHierarchicalUri(uriTemplate, match);
-            }
-        }
-        throw new IllegalArgumentException("Illegal uri template: " + uriTemplate);
-    }
-
-    protected KeycloakUriBuilder parseHierarchicalUri(String uriTemplate, Matcher match) {
-        boolean scheme = match.group(2) != null;
-        if (scheme) this.scheme = match.group(2);
-        String authority = match.group(4);
-        if (authority != null) {
-            this.authority = null;
-            String host = match.group(4);
-            int at = host.indexOf('@');
-            if (at > -1) {
-                String user = host.substring(0, at);
-                host = host.substring(at + 1);
-                this.userInfo = user;
-            }
-            Matcher hostPortMatch = hostPortPattern.matcher(host);
-            if (hostPortMatch.matches()) {
-                this.host = hostPortMatch.group(1);
-                try {
-                    this.port = Integer.parseInt(hostPortMatch.group(2));
-                } catch (NumberFormatException e) {
-                    throw new IllegalArgumentException("Illegal uri template: " + uriTemplate, e);
-                }
-            } else {
-                this.host = host;
-            }
-        }
-        if (match.group(5) != null) {
-            String group = match.group(5);
-            if (!scheme && !"".equals(group) && !group.startsWith("/") && group.indexOf(':') > -1)
-                throw new IllegalArgumentException("Illegal uri template: " + uriTemplate);
-            if (!"".equals(group)) replacePath(group);
-        }
-        if (match.group(7) != null) replaceQuery(match.group(7));
-        if (match.group(9) != null) fragment(match.group(9));
-        return this;
-    }
-
-    public KeycloakUriBuilder uri(String uriTemplate) throws IllegalArgumentException {
-        return uriTemplate(uriTemplate);
-    }
-
-    public KeycloakUriBuilder uri(URI uri) throws IllegalArgumentException {
-        if (uri == null) throw new IllegalArgumentException("URI was null");
-
-        if (uri.getRawFragment() != null) fragment = uri.getRawFragment();
-
-        if (uri.isOpaque()) {
-            scheme = uri.getScheme();
-            ssp = uri.getRawSchemeSpecificPart();
-            return this;
-        }
-
-        if (uri.getScheme() == null) {
-            if (ssp != null) {
-                if (uri.getRawSchemeSpecificPart() != null) {
-                    ssp = uri.getRawSchemeSpecificPart();
-                    return this;
-                }
-            }
-        } else {
-            scheme = uri.getScheme();
-        }
-
-        ssp = null;
-        if (uri.getRawAuthority() != null) {
-            if (uri.getRawUserInfo() == null && uri.getHost() == null && uri.getPort() == -1) {
-                authority = uri.getRawAuthority();
-                userInfo = null;
-                host = null;
-                port = -1;
-            } else {
-                authority = null;
-                if (uri.getRawUserInfo() != null) {
-                    userInfo = uri.getRawUserInfo();
-                }
-                if (uri.getHost() != null) {
-                    host = uri.getHost();
-                }
-                if (uri.getPort() != -1) {
-                    port = uri.getPort();
-                }
-            }
-        }
-
-        if (uri.getRawPath() != null && uri.getRawPath().length() > 0) {
-            path = uri.getRawPath();
-        }
-        if (uri.getRawQuery() != null && uri.getRawQuery().length() > 0) {
-            query = uri.getRawQuery();
-        }
-
-        return this;
-    }
-
-    public KeycloakUriBuilder scheme(String scheme) throws IllegalArgumentException {
-        this.scheme = scheme;
-        return this;
-    }
-
-    public KeycloakUriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException {
-        if (ssp == null) throw new IllegalArgumentException("schemeSpecificPart was null");
-
-        StringBuilder sb = new StringBuilder();
-        if (scheme != null) sb.append(scheme).append(':');
-        if (ssp != null)
-            sb.append(ssp);
-        if (fragment != null && fragment.length() > 0) sb.append('#').append(fragment);
-        URI uri = URI.create(sb.toString());
-
-        if (uri.getRawSchemeSpecificPart() != null && uri.getRawPath() == null) {
-            this.ssp = uri.getRawSchemeSpecificPart();
-        } else {
-            this.ssp = null;
-            userInfo = uri.getRawUserInfo();
-            host = uri.getHost();
-            port = uri.getPort();
-            path = uri.getRawPath();
-            query = uri.getRawQuery();
-
-        }
-        return this;
-
-    }
-
-    public KeycloakUriBuilder userInfo(String ui) {
-        this.userInfo = ui;
-        return this;
-    }
-
-    public KeycloakUriBuilder host(String host) throws IllegalArgumentException {
-        if (host != null && host.equals("")) throw new IllegalArgumentException("invalid host");
-        this.host = host;
-        return this;
-    }
-
-    public KeycloakUriBuilder port(int port) throws IllegalArgumentException {
-        if (port < -1) throw new IllegalArgumentException("Invalid port value");
-        this.port = port;
-        return this;
-    }
-
-    protected static String paths(boolean encode, String basePath, String... segments) {
-        String path = basePath;
-        if (path == null) path = "";
-        for (String segment : segments) {
-            if ("".equals(segment)) continue;
-            if (path.endsWith("/")) {
-                if (segment.startsWith("/")) {
-                    segment = segment.substring(1);
-                    if ("".equals(segment)) continue;
-                }
-                if (encode) segment = Encode.encodePath(segment);
-                path += segment;
-            } else {
-                if (encode) segment = Encode.encodePath(segment);
-                if ("".equals(path)) {
-                    path = segment;
-                } else if (segment.startsWith("/")) {
-                    path += segment;
-                } else {
-                    path += "/" + segment;
-                }
-            }
-
-        }
-        return path;
-    }
-
-    public KeycloakUriBuilder path(String segment) throws IllegalArgumentException {
-        if (segment == null) throw new IllegalArgumentException("path was null");
-        path = paths(true, path, segment);
-        return this;
-    }
-
-    public KeycloakUriBuilder replaceMatrix(String matrix) throws IllegalArgumentException {
-        if (matrix == null) matrix = "";
-        if (!matrix.startsWith(";")) matrix = ";" + matrix;
-        matrix = Encode.encodePath(matrix);
-        if (path == null) {
-            path = matrix;
-        } else {
-            int start = path.lastIndexOf('/');
-            if (start < 0) start = 0;
-            int matrixIndex = path.indexOf(';', start);
-            if (matrixIndex > -1) path = path.substring(0, matrixIndex) + matrix;
-            else path += matrix;
-
-        }
-        return this;
-    }
-
-    public KeycloakUriBuilder replaceQuery(String query) throws IllegalArgumentException {
-        if (query == null || query.length() == 0) {
-            this.query = null;
-            return this;
-        }
-        this.query = Encode.encodeQueryString(query);
-        return this;
-    }
-
-    public KeycloakUriBuilder fragment(String fragment) throws IllegalArgumentException {
-        if (fragment == null) {
-            this.fragment = null;
-            return this;
-        }
-        this.fragment = Encode.encodeFragment(fragment);
-        return this;
-    }
-
-    /**
-     * Only replace path params in path of URI.  This changes state of URIBuilder.
-     *
-     * @param name
-     * @param value
-     * @param isEncoded
-     * @return
-     */
-    public KeycloakUriBuilder substitutePathParam(String name, Object value, boolean isEncoded) {
-        if (path != null) {
-            StringBuffer buffer = new StringBuffer();
-            replacePathParameter(name, value.toString(), isEncoded, path, buffer, false);
-            path = buffer.toString();
-        }
-        return this;
-    }
-
-    public URI buildFromMap(Map<String, ?> values) throws IllegalArgumentException {
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        return buildUriFromMap(values, false, true);
-    }
-
-    public URI buildFromEncodedMap(Map<String, ?> values) throws IllegalArgumentException {
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        return buildUriFromMap(values, true, false);
-    }
-
-    public URI buildFromMap(Map<String, ?> values, boolean encodeSlashInPath) throws IllegalArgumentException {
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        return buildUriFromMap(values, false, encodeSlashInPath);
-    }
-
-    protected URI buildUriFromMap(Map<String, ?> paramMap, boolean fromEncodedMap, boolean encodeSlash) throws IllegalArgumentException {
-        String buf = buildString(paramMap, fromEncodedMap, false, encodeSlash);
-        try {
-            return URI.create(buf);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to create URI: " + buf, e);
-        }
-    }
-
-    private String buildString(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, boolean encodeSlash) {
-        for (Map.Entry<String, ? extends Object> entry : paramMap.entrySet()) {
-            if (entry.getKey() == null) throw new IllegalArgumentException("map key is null");
-            if (entry.getValue() == null) throw new IllegalArgumentException("map value is null");
-        }
-        StringBuffer buffer = new StringBuffer();
-
-        if (scheme != null)
-            replaceParameter(paramMap, fromEncodedMap, isTemplate, scheme, buffer, encodeSlash).append(":");
-        if (ssp != null) {
-            buffer.append(ssp);
-        } else if (userInfo != null || host != null || port != -1) {
-            buffer.append("//");
-            if (userInfo != null)
-                replaceParameter(paramMap, fromEncodedMap, isTemplate, userInfo, buffer, encodeSlash).append("@");
-            if (host != null) {
-                if ("".equals(host)) throw new RuntimeException("empty host name");
-                replaceParameter(paramMap, fromEncodedMap, isTemplate, host, buffer, encodeSlash);
-            }
-            if (port != -1) buffer.append(":").append(Integer.toString(port));
-        } else if (authority != null) {
-            buffer.append("//");
-            replaceParameter(paramMap, fromEncodedMap, isTemplate, authority, buffer, encodeSlash);
-        }
-        if (path != null) {
-            StringBuffer tmp = new StringBuffer();
-            replaceParameter(paramMap, fromEncodedMap, isTemplate, path, tmp, encodeSlash);
-            String tmpPath = tmp.toString();
-            if (userInfo != null || host != null) {
-                if (!tmpPath.startsWith("/")) buffer.append("/");
-            }
-            buffer.append(tmpPath);
-        }
-        if (query != null) {
-            buffer.append("?");
-            replaceQueryStringParameter(paramMap, fromEncodedMap, isTemplate, query, buffer);
-        }
-        if (fragment != null) {
-            buffer.append("#");
-            replaceParameter(paramMap, fromEncodedMap, isTemplate, fragment, buffer, encodeSlash);
-        }
-        return buffer.toString();
-    }
-
-    protected StringBuffer replacePathParameter(String name, String value, boolean isEncoded, String string, StringBuffer buffer, boolean encodeSlash) {
-        Matcher matcher = createUriParamMatcher(string);
-        while (matcher.find()) {
-            String param = matcher.group(1);
-            if (!param.equals(name)) continue;
-            if (!isEncoded) {
-                if (encodeSlash) value = Encode.encodePath(value);
-                else value = Encode.encodePathSegment(value);
-
-            } else {
-                value = Encode.encodeNonCodes(value);
-            }
-            // if there is a $ then we must backslash it or it will screw up regex group substitution
-            value = value.replace("$", "\\$");
-            matcher.appendReplacement(buffer, value);
-        }
-        matcher.appendTail(buffer);
-        return buffer;
-    }
-
-    public static Matcher createUriParamMatcher(String string) {
-        return PathHelper.URI_PARAM_PATTERN.matcher(PathHelper.replaceEnclosedCurlyBraces(string));
-    }
-
-    protected StringBuffer replaceParameter(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, String string, StringBuffer buffer, boolean encodeSlash) {
-        Matcher matcher = createUriParamMatcher(string);
-        while (matcher.find()) {
-            String param = matcher.group(1);
-            Object valObj = paramMap.get(param);
-            if (valObj == null && !isTemplate) {
-                throw new IllegalArgumentException("NULL value for template parameter: " + param);
-            } else if (valObj == null && isTemplate) {
-                matcher.appendReplacement(buffer, matcher.group());
-                continue;
-            }
-            String value = valObj.toString();
-            if (value != null) {
-                if (!fromEncodedMap) {
-                    if (encodeSlash) value = Encode.encodePathSegmentAsIs(value);
-                    else value = Encode.encodePathAsIs(value);
-                } else {
-                    if (encodeSlash) value = Encode.encodePathSegmentSaveEncodings(value);
-                    else value = Encode.encodePathSaveEncodings(value);
-                }
-                matcher.appendReplacement(buffer, Matcher.quoteReplacement(value));
-            } else {
-                throw new IllegalArgumentException("path param " + param + " has not been provided by the parameter map");
-            }
-        }
-        matcher.appendTail(buffer);
-        return buffer;
-    }
-
-    protected StringBuffer replaceQueryStringParameter(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, String string, StringBuffer buffer) {
-        Matcher matcher = createUriParamMatcher(string);
-        while (matcher.find()) {
-            String param = matcher.group(1);
-            Object valObj = paramMap.get(param);
-            if (valObj == null && !isTemplate) {
-                throw new IllegalArgumentException("NULL value for template parameter: " + param);
-            } else if (valObj == null && isTemplate) {
-                matcher.appendReplacement(buffer, matcher.group());
-                continue;
-            }
-            String value = valObj.toString();
-            if (value != null) {
-                if (!fromEncodedMap) {
-                    value = Encode.encodeQueryParamAsIs(value);
-                } else {
-                    value = Encode.encodeQueryParamSaveEncodings(value);
-                }
-                matcher.appendReplacement(buffer, value);
-            } else {
-                throw new IllegalArgumentException("path param " + param + " has not been provided by the parameter map");
-            }
-        }
-        matcher.appendTail(buffer);
-        return buffer;
-    }
-
-    /**
-     * Return a unique order list of path params
-     *
-     * @return
-     */
-    public List<String> getPathParamNamesInDeclarationOrder() {
-        List<String> params = new ArrayList<String>();
-        HashSet<String> set = new HashSet<String>();
-        if (scheme != null) addToPathParamList(params, set, scheme);
-        if (userInfo != null) addToPathParamList(params, set, userInfo);
-        if (host != null) addToPathParamList(params, set, host);
-        if (path != null) addToPathParamList(params, set, path);
-        if (query != null) addToPathParamList(params, set, query);
-        if (fragment != null) addToPathParamList(params, set, fragment);
-
-        return params;
-    }
-
-    private void addToPathParamList(List<String> params, HashSet<String> set, String string) {
-        Matcher matcher = PathHelper.URI_PARAM_PATTERN.matcher(PathHelper.replaceEnclosedCurlyBraces(string));
-        while (matcher.find()) {
-            String param = matcher.group(1);
-            if (set.contains(param)) continue;
-            else {
-                set.add(param);
-                params.add(param);
-            }
-        }
-    }
-
-    public URI build(Object... values) throws IllegalArgumentException {
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        return buildFromValues(true, false, values);
-    }
-
-    protected URI buildFromValues(boolean encodeSlash, boolean encoded, Object... values) {
-        List<String> params = getPathParamNamesInDeclarationOrder();
-        if (values.length < params.size())
-            throw new IllegalArgumentException("You did not supply enough values to fill path parameters");
-
-        Map<String, Object> pathParams = new HashMap<String, Object>();
-
-
-        for (int i = 0; i < params.size(); i++) {
-            String pathParam = params.get(i);
-            Object val = values[i];
-            if (val == null) throw new IllegalArgumentException("A value was null");
-            pathParams.put(pathParam, val.toString());
-        }
-        String buf = null;
-        try {
-            buf = buildString(pathParams, encoded, false, encodeSlash);
-            return new URI(buf);
-            //return URI.create(buf);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to create URI: " + buf, e);
-        }
-    }
-
-    public KeycloakUriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
-        if (name == null) throw new IllegalArgumentException("name parameter is null");
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        if (path == null) path = "";
-        for (Object val : values) {
-            if (val == null) throw new IllegalArgumentException("null value");
-            path += ";" + Encode.encodeMatrixParam(name) + "=" + Encode.encodeMatrixParam(val.toString());
-        }
-        return this;
-    }
-
-    private static final Pattern PARAM_REPLACEMENT = Pattern.compile("_resteasy_uri_parameter");
-
-
-    public KeycloakUriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
-        if (name == null) throw new IllegalArgumentException("name parameter is null");
-        if (values == null) throw new IllegalArgumentException("values parameter is null");
-        for (Object value : values) {
-            if (value == null) throw new IllegalArgumentException("A passed in value was null");
-            if (query == null) query = "";
-            else query += "&";
-            query += Encode.encodeQueryParam(name) + "=" + Encode.encodeQueryParam(value.toString());
-        }
-        return this;
-    }
-
-    public KeycloakUriBuilder replaceQueryParam(String name, Object... values) throws IllegalArgumentException {
-        if (name == null) throw new IllegalArgumentException("name parameter is null");
-        if (query == null || query.equals("")) {
-            if (values != null) return queryParam(name, values);
-            return this;
-        }
-
-        String[] params = query.split("&");
-        query = null;
-
-        String replacedName = Encode.encodeQueryParam(name);
-
-
-        for (String param : params) {
-            int pos = param.indexOf('=');
-            if (pos >= 0) {
-                String paramName = param.substring(0, pos);
-                if (paramName.equals(replacedName)) continue;
-            } else {
-                if (param.equals(replacedName)) continue;
-            }
-            if (query == null) query = "";
-            else query += "&";
-            query += param;
-        }
-        // don't set values if values is null
-        if (values == null) return this;
-        return queryParam(name, values);
-    }
-
-    public String getHost() {
-        return host;
-    }
-
-    public String getScheme() {
-        return scheme;
-    }
-
-    public int getPort() {
-        return port;
-    }
-
-    public String getUserInfo() {
-        return userInfo;
-    }
-
-    public String getPath() {
-        return path;
-    }
-
-    public String getQuery() {
-        return query;
-    }
-
-    public String getFragment() {
-        return fragment;
-    }
-
-    public KeycloakUriBuilder segment(String... segments) throws IllegalArgumentException {
-        if (segments == null) throw new IllegalArgumentException("segments parameter was null");
-        for (String segment : segments) {
-            if (segment == null) throw new IllegalArgumentException("A segment is null");
-            path(Encode.encodePathSegment(segment));
-        }
-        return this;
-    }
-
-    public KeycloakUriBuilder replacePath(String path) {
-        if (path == null) {
-            this.path = null;
-            return this;
-        }
-        this.path = Encode.encodePath(path);
-        return this;
-    }
-
-    public URI build(Object[] values, boolean encodeSlashInPath) throws IllegalArgumentException {
-        if (values == null) throw new IllegalArgumentException("values param is null");
-        return buildFromValues(encodeSlashInPath, false, values);
-    }
-
-    public String toTemplate() {
-        return buildString(new HashMap<String, Object>(), true, true, true);
-    }
-
-    public KeycloakUriBuilder resolveTemplate(String name, Object value) throws IllegalArgumentException {
-        if (name == null) throw new IllegalArgumentException("name param is null");
-        if (value == null) throw new IllegalArgumentException("value param is null");
-        HashMap<String, Object> vals = new HashMap<String, Object>();
-        vals.put(name, value);
-        return resolveTemplates(vals);
-    }
-
-    public KeycloakUriBuilder resolveTemplates(Map<String, Object> templateValues) throws IllegalArgumentException {
-        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
-        String str = buildString(templateValues, false, true, true);
-        return fromTemplate(str);
-    }
-
-    public KeycloakUriBuilder resolveTemplate(String name, Object value, boolean encodeSlashInPath) throws IllegalArgumentException {
-        if (name == null) throw new IllegalArgumentException("name param is null");
-        if (value == null) throw new IllegalArgumentException("value param is null");
-        HashMap<String, Object> vals = new HashMap<String, Object>();
-        vals.put(name, value);
-        String str = buildString(vals, false, true, encodeSlashInPath);
-        return fromTemplate(str);
-    }
-
-    public KeycloakUriBuilder resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) throws IllegalArgumentException {
-        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
-        String str = buildString(templateValues, false, true, encodeSlashInPath);
-        return fromTemplate(str);
-    }
-
-    public KeycloakUriBuilder resolveTemplatesFromEncoded(Map<String, Object> templateValues) throws IllegalArgumentException {
-        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
-        String str = buildString(templateValues, true, true, true);
-        return fromTemplate(str);
-    }
-}
+package org.keycloak.util;
+
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakUriBuilder {
+
+    private String host;
+    private String scheme;
+    private int port = -1;
+
+    private String userInfo;
+    private String path;
+    private String query;
+    private String fragment;
+    private String ssp;
+    private String authority;
+
+    public static KeycloakUriBuilder fromUri(URI uri) {
+        return new KeycloakUriBuilder().uri(uri);
+    }
+
+    public static KeycloakUriBuilder fromUri(String uriTemplate) {
+        return new KeycloakUriBuilder().uri(uriTemplate);
+    }
+
+    public static KeycloakUriBuilder fromPath(String path) throws IllegalArgumentException {
+        return new KeycloakUriBuilder().path(path);
+    }
+
+
+    public KeycloakUriBuilder clone() {
+        KeycloakUriBuilder impl = new KeycloakUriBuilder();
+        impl.host = host;
+        impl.scheme = scheme;
+        impl.port = port;
+        impl.userInfo = userInfo;
+        impl.path = path;
+        impl.query = query;
+        impl.fragment = fragment;
+        impl.ssp = ssp;
+        impl.authority = authority;
+
+        return impl;
+    }
+
+    private static final Pattern opaqueUri = Pattern.compile("^([^:/?#]+):([^/].*)");
+    private static final Pattern hierarchicalUri = Pattern.compile("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
+    private static final Pattern hostPortPattern = Pattern.compile("([^/:]+):(\\d+)");
+
+    public static boolean compare(String s1, String s2) {
+        if (s1 == s2) return true;
+        if (s1 == null || s2 == null) return false;
+        return s1.equals(s2);
+    }
+
+    public static URI relativize(URI from, URI to) {
+        if (!compare(from.getScheme(), to.getScheme())) return to;
+        if (!compare(from.getHost(), to.getHost())) return to;
+        if (from.getPort() != to.getPort()) return to;
+        if (from.getPath() == null && to.getPath() == null) return URI.create("");
+        else if (from.getPath() == null) return URI.create(to.getPath());
+        else if (to.getPath() == null) return to;
+
+
+        String fromPath = from.getPath();
+        if (fromPath.startsWith("/")) fromPath = fromPath.substring(1);
+        String[] fsplit = fromPath.split("/");
+        String toPath = to.getPath();
+        if (toPath.startsWith("/")) toPath = toPath.substring(1);
+        String[] tsplit = toPath.split("/");
+
+        int f = 0;
+
+        for (; f < fsplit.length && f < tsplit.length; f++) {
+            if (!fsplit[f].equals(tsplit[f])) break;
+        }
+
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromPath("");
+        for (int i = f; i < fsplit.length; i++) builder.path("..");
+        for (int i = f; i < tsplit.length; i++) builder.path(tsplit[i]);
+        return builder.build();
+    }
+
+    /**
+     * You may put path parameters anywhere within the uriTemplate except port
+     *
+     * @param uriTemplate
+     * @return
+     */
+    public static KeycloakUriBuilder fromTemplate(String uriTemplate) {
+        KeycloakUriBuilder impl = new KeycloakUriBuilder();
+        impl.uriTemplate(uriTemplate);
+        return impl;
+    }
+
+    /**
+     * You may put path parameters anywhere within the uriTemplate except port
+     *
+     * @param uriTemplate
+     * @return
+     */
+    public KeycloakUriBuilder uriTemplate(String uriTemplate) {
+        if (uriTemplate == null) throw new IllegalArgumentException("uriTemplate parameter is null");
+        Matcher opaque = opaqueUri.matcher(uriTemplate);
+        if (opaque.matches()) {
+            this.authority = null;
+            this.host = null;
+            this.port = -1;
+            this.userInfo = null;
+            this.query = null;
+            this.scheme = opaque.group(1);
+            this.ssp = opaque.group(2);
+            return this;
+        } else {
+            Matcher match = hierarchicalUri.matcher(uriTemplate);
+            if (match.matches()) {
+                ssp = null;
+                return parseHierarchicalUri(uriTemplate, match);
+            }
+        }
+        throw new IllegalArgumentException("Illegal uri template: " + uriTemplate);
+    }
+
+    protected KeycloakUriBuilder parseHierarchicalUri(String uriTemplate, Matcher match) {
+        boolean scheme = match.group(2) != null;
+        if (scheme) this.scheme = match.group(2);
+        String authority = match.group(4);
+        if (authority != null) {
+            this.authority = null;
+            String host = match.group(4);
+            int at = host.indexOf('@');
+            if (at > -1) {
+                String user = host.substring(0, at);
+                host = host.substring(at + 1);
+                this.userInfo = user;
+            }
+            Matcher hostPortMatch = hostPortPattern.matcher(host);
+            if (hostPortMatch.matches()) {
+                this.host = hostPortMatch.group(1);
+                try {
+                    this.port = Integer.parseInt(hostPortMatch.group(2));
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("Illegal uri template: " + uriTemplate, e);
+                }
+            } else {
+                this.host = host;
+            }
+        }
+        if (match.group(5) != null) {
+            String group = match.group(5);
+            if (!scheme && !"".equals(group) && !group.startsWith("/") && group.indexOf(':') > -1)
+                throw new IllegalArgumentException("Illegal uri template: " + uriTemplate);
+            if (!"".equals(group)) replacePath(group);
+        }
+        if (match.group(7) != null) replaceQuery(match.group(7));
+        if (match.group(9) != null) fragment(match.group(9));
+        return this;
+    }
+
+    public KeycloakUriBuilder uri(String uriTemplate) throws IllegalArgumentException {
+        return uriTemplate(uriTemplate);
+    }
+
+    public KeycloakUriBuilder uri(URI uri) throws IllegalArgumentException {
+        if (uri == null) throw new IllegalArgumentException("URI was null");
+
+        if (uri.getRawFragment() != null) fragment = uri.getRawFragment();
+
+        if (uri.isOpaque()) {
+            scheme = uri.getScheme();
+            ssp = uri.getRawSchemeSpecificPart();
+            return this;
+        }
+
+        if (uri.getScheme() == null) {
+            if (ssp != null) {
+                if (uri.getRawSchemeSpecificPart() != null) {
+                    ssp = uri.getRawSchemeSpecificPart();
+                    return this;
+                }
+            }
+        } else {
+            scheme = uri.getScheme();
+        }
+
+        ssp = null;
+        if (uri.getRawAuthority() != null) {
+            if (uri.getRawUserInfo() == null && uri.getHost() == null && uri.getPort() == -1) {
+                authority = uri.getRawAuthority();
+                userInfo = null;
+                host = null;
+                port = -1;
+            } else {
+                authority = null;
+                if (uri.getRawUserInfo() != null) {
+                    userInfo = uri.getRawUserInfo();
+                }
+                if (uri.getHost() != null) {
+                    host = uri.getHost();
+                }
+                if (uri.getPort() != -1) {
+                    port = uri.getPort();
+                }
+            }
+        }
+
+        if (uri.getRawPath() != null && uri.getRawPath().length() > 0) {
+            path = uri.getRawPath();
+        }
+        if (uri.getRawQuery() != null && uri.getRawQuery().length() > 0) {
+            query = uri.getRawQuery();
+        }
+
+        return this;
+    }
+
+    public KeycloakUriBuilder scheme(String scheme) throws IllegalArgumentException {
+        this.scheme = scheme;
+        return this;
+    }
+
+    public KeycloakUriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException {
+        if (ssp == null) throw new IllegalArgumentException("schemeSpecificPart was null");
+
+        StringBuilder sb = new StringBuilder();
+        if (scheme != null) sb.append(scheme).append(':');
+        if (ssp != null)
+            sb.append(ssp);
+        if (fragment != null && fragment.length() > 0) sb.append('#').append(fragment);
+        URI uri = URI.create(sb.toString());
+
+        if (uri.getRawSchemeSpecificPart() != null && uri.getRawPath() == null) {
+            this.ssp = uri.getRawSchemeSpecificPart();
+        } else {
+            this.ssp = null;
+            userInfo = uri.getRawUserInfo();
+            host = uri.getHost();
+            port = uri.getPort();
+            path = uri.getRawPath();
+            query = uri.getRawQuery();
+
+        }
+        return this;
+
+    }
+
+    public KeycloakUriBuilder userInfo(String ui) {
+        this.userInfo = ui;
+        return this;
+    }
+
+    public KeycloakUriBuilder host(String host) throws IllegalArgumentException {
+        if (host != null && host.equals("")) throw new IllegalArgumentException("invalid host");
+        this.host = host;
+        return this;
+    }
+
+    public KeycloakUriBuilder port(int port) throws IllegalArgumentException {
+        if (port < -1) throw new IllegalArgumentException("Invalid port value");
+        this.port = port;
+        return this;
+    }
+
+    protected static String paths(boolean encode, String basePath, String... segments) {
+        String path = basePath;
+        if (path == null) path = "";
+        for (String segment : segments) {
+            if ("".equals(segment)) continue;
+            if (path.endsWith("/")) {
+                if (segment.startsWith("/")) {
+                    segment = segment.substring(1);
+                    if ("".equals(segment)) continue;
+                }
+                if (encode) segment = Encode.encodePath(segment);
+                path += segment;
+            } else {
+                if (encode) segment = Encode.encodePath(segment);
+                if ("".equals(path)) {
+                    path = segment;
+                } else if (segment.startsWith("/")) {
+                    path += segment;
+                } else {
+                    path += "/" + segment;
+                }
+            }
+
+        }
+        return path;
+    }
+
+    public KeycloakUriBuilder path(String segment) throws IllegalArgumentException {
+        if (segment == null) throw new IllegalArgumentException("path was null");
+        path = paths(true, path, segment);
+        return this;
+    }
+
+    public KeycloakUriBuilder replaceMatrix(String matrix) throws IllegalArgumentException {
+        if (matrix == null) matrix = "";
+        if (!matrix.startsWith(";")) matrix = ";" + matrix;
+        matrix = Encode.encodePath(matrix);
+        if (path == null) {
+            path = matrix;
+        } else {
+            int start = path.lastIndexOf('/');
+            if (start < 0) start = 0;
+            int matrixIndex = path.indexOf(';', start);
+            if (matrixIndex > -1) path = path.substring(0, matrixIndex) + matrix;
+            else path += matrix;
+
+        }
+        return this;
+    }
+
+    public KeycloakUriBuilder replaceQuery(String query) throws IllegalArgumentException {
+        if (query == null || query.length() == 0) {
+            this.query = null;
+            return this;
+        }
+        this.query = Encode.encodeQueryString(query);
+        return this;
+    }
+
+    public KeycloakUriBuilder fragment(String fragment) throws IllegalArgumentException {
+        if (fragment == null) {
+            this.fragment = null;
+            return this;
+        }
+        this.fragment = Encode.encodeFragment(fragment);
+        return this;
+    }
+
+    /**
+     * Only replace path params in path of URI.  This changes state of URIBuilder.
+     *
+     * @param name
+     * @param value
+     * @param isEncoded
+     * @return
+     */
+    public KeycloakUriBuilder substitutePathParam(String name, Object value, boolean isEncoded) {
+        if (path != null) {
+            StringBuffer buffer = new StringBuffer();
+            replacePathParameter(name, value.toString(), isEncoded, path, buffer, false);
+            path = buffer.toString();
+        }
+        return this;
+    }
+
+    public URI buildFromMap(Map<String, ?> values) throws IllegalArgumentException {
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        return buildUriFromMap(values, false, true);
+    }
+
+    public URI buildFromEncodedMap(Map<String, ?> values) throws IllegalArgumentException {
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        return buildUriFromMap(values, true, false);
+    }
+
+    public URI buildFromMap(Map<String, ?> values, boolean encodeSlashInPath) throws IllegalArgumentException {
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        return buildUriFromMap(values, false, encodeSlashInPath);
+    }
+
+    protected URI buildUriFromMap(Map<String, ?> paramMap, boolean fromEncodedMap, boolean encodeSlash) throws IllegalArgumentException {
+        String buf = buildString(paramMap, fromEncodedMap, false, encodeSlash);
+        try {
+            return URI.create(buf);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create URI: " + buf, e);
+        }
+    }
+
+    private String buildString(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, boolean encodeSlash) {
+        for (Map.Entry<String, ? extends Object> entry : paramMap.entrySet()) {
+            if (entry.getKey() == null) throw new IllegalArgumentException("map key is null");
+            if (entry.getValue() == null) throw new IllegalArgumentException("map value is null");
+        }
+        StringBuffer buffer = new StringBuffer();
+
+        if (scheme != null)
+            replaceParameter(paramMap, fromEncodedMap, isTemplate, scheme, buffer, encodeSlash).append(":");
+        if (ssp != null) {
+            buffer.append(ssp);
+        } else if (userInfo != null || host != null || port != -1) {
+            buffer.append("//");
+            if (userInfo != null)
+                replaceParameter(paramMap, fromEncodedMap, isTemplate, userInfo, buffer, encodeSlash).append("@");
+            if (host != null) {
+                if ("".equals(host)) throw new RuntimeException("empty host name");
+                replaceParameter(paramMap, fromEncodedMap, isTemplate, host, buffer, encodeSlash);
+            }
+            if (port != -1) buffer.append(":").append(Integer.toString(port));
+        } else if (authority != null) {
+            buffer.append("//");
+            replaceParameter(paramMap, fromEncodedMap, isTemplate, authority, buffer, encodeSlash);
+        }
+        if (path != null) {
+            StringBuffer tmp = new StringBuffer();
+            replaceParameter(paramMap, fromEncodedMap, isTemplate, path, tmp, encodeSlash);
+            String tmpPath = tmp.toString();
+            if (userInfo != null || host != null) {
+                if (!tmpPath.startsWith("/")) buffer.append("/");
+            }
+            buffer.append(tmpPath);
+        }
+        if (query != null) {
+            buffer.append("?");
+            replaceQueryStringParameter(paramMap, fromEncodedMap, isTemplate, query, buffer);
+        }
+        if (fragment != null) {
+            buffer.append("#");
+            replaceParameter(paramMap, fromEncodedMap, isTemplate, fragment, buffer, encodeSlash);
+        }
+        return buffer.toString();
+    }
+
+    protected StringBuffer replacePathParameter(String name, String value, boolean isEncoded, String string, StringBuffer buffer, boolean encodeSlash) {
+        Matcher matcher = createUriParamMatcher(string);
+        while (matcher.find()) {
+            String param = matcher.group(1);
+            if (!param.equals(name)) continue;
+            if (!isEncoded) {
+                if (encodeSlash) value = Encode.encodePath(value);
+                else value = Encode.encodePathSegment(value);
+
+            } else {
+                value = Encode.encodeNonCodes(value);
+            }
+            // if there is a $ then we must backslash it or it will screw up regex group substitution
+            value = value.replace("$", "\\$");
+            matcher.appendReplacement(buffer, value);
+        }
+        matcher.appendTail(buffer);
+        return buffer;
+    }
+
+    public static Matcher createUriParamMatcher(String string) {
+        return PathHelper.URI_PARAM_PATTERN.matcher(PathHelper.replaceEnclosedCurlyBraces(string));
+    }
+
+    protected StringBuffer replaceParameter(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, String string, StringBuffer buffer, boolean encodeSlash) {
+        Matcher matcher = createUriParamMatcher(string);
+        while (matcher.find()) {
+            String param = matcher.group(1);
+            Object valObj = paramMap.get(param);
+            if (valObj == null && !isTemplate) {
+                throw new IllegalArgumentException("NULL value for template parameter: " + param);
+            } else if (valObj == null && isTemplate) {
+                matcher.appendReplacement(buffer, matcher.group());
+                continue;
+            }
+            String value = valObj.toString();
+            if (value != null) {
+                if (!fromEncodedMap) {
+                    if (encodeSlash) value = Encode.encodePathSegmentAsIs(value);
+                    else value = Encode.encodePathAsIs(value);
+                } else {
+                    if (encodeSlash) value = Encode.encodePathSegmentSaveEncodings(value);
+                    else value = Encode.encodePathSaveEncodings(value);
+                }
+                matcher.appendReplacement(buffer, Matcher.quoteReplacement(value));
+            } else {
+                throw new IllegalArgumentException("path param " + param + " has not been provided by the parameter map");
+            }
+        }
+        matcher.appendTail(buffer);
+        return buffer;
+    }
+
+    protected StringBuffer replaceQueryStringParameter(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, String string, StringBuffer buffer) {
+        Matcher matcher = createUriParamMatcher(string);
+        while (matcher.find()) {
+            String param = matcher.group(1);
+            Object valObj = paramMap.get(param);
+            if (valObj == null && !isTemplate) {
+                throw new IllegalArgumentException("NULL value for template parameter: " + param);
+            } else if (valObj == null && isTemplate) {
+                matcher.appendReplacement(buffer, matcher.group());
+                continue;
+            }
+            String value = valObj.toString();
+            if (value != null) {
+                if (!fromEncodedMap) {
+                    value = Encode.encodeQueryParamAsIs(value);
+                } else {
+                    value = Encode.encodeQueryParamSaveEncodings(value);
+                }
+                matcher.appendReplacement(buffer, value);
+            } else {
+                throw new IllegalArgumentException("path param " + param + " has not been provided by the parameter map");
+            }
+        }
+        matcher.appendTail(buffer);
+        return buffer;
+    }
+
+    /**
+     * Return a unique order list of path params
+     *
+     * @return
+     */
+    public List<String> getPathParamNamesInDeclarationOrder() {
+        List<String> params = new ArrayList<String>();
+        HashSet<String> set = new HashSet<String>();
+        if (scheme != null) addToPathParamList(params, set, scheme);
+        if (userInfo != null) addToPathParamList(params, set, userInfo);
+        if (host != null) addToPathParamList(params, set, host);
+        if (path != null) addToPathParamList(params, set, path);
+        if (query != null) addToPathParamList(params, set, query);
+        if (fragment != null) addToPathParamList(params, set, fragment);
+
+        return params;
+    }
+
+    private void addToPathParamList(List<String> params, HashSet<String> set, String string) {
+        Matcher matcher = PathHelper.URI_PARAM_PATTERN.matcher(PathHelper.replaceEnclosedCurlyBraces(string));
+        while (matcher.find()) {
+            String param = matcher.group(1);
+            if (set.contains(param)) continue;
+            else {
+                set.add(param);
+                params.add(param);
+            }
+        }
+    }
+
+    public URI build(Object... values) throws IllegalArgumentException {
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        return buildFromValues(true, false, values);
+    }
+
+    protected URI buildFromValues(boolean encodeSlash, boolean encoded, Object... values) {
+        List<String> params = getPathParamNamesInDeclarationOrder();
+        if (values.length < params.size())
+            throw new IllegalArgumentException("You did not supply enough values to fill path parameters");
+
+        Map<String, Object> pathParams = new HashMap<String, Object>();
+
+
+        for (int i = 0; i < params.size(); i++) {
+            String pathParam = params.get(i);
+            Object val = values[i];
+            if (val == null) throw new IllegalArgumentException("A value was null");
+            pathParams.put(pathParam, val.toString());
+        }
+        String buf = null;
+        try {
+            buf = buildString(pathParams, encoded, false, encodeSlash);
+            return new URI(buf);
+            //return URI.create(buf);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create URI: " + buf, e);
+        }
+    }
+
+    public KeycloakUriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
+        if (name == null) throw new IllegalArgumentException("name parameter is null");
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        if (path == null) path = "";
+        for (Object val : values) {
+            if (val == null) throw new IllegalArgumentException("null value");
+            path += ";" + Encode.encodeMatrixParam(name) + "=" + Encode.encodeMatrixParam(val.toString());
+        }
+        return this;
+    }
+
+    private static final Pattern PARAM_REPLACEMENT = Pattern.compile("_resteasy_uri_parameter");
+
+
+    public KeycloakUriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
+        if (name == null) throw new IllegalArgumentException("name parameter is null");
+        if (values == null) throw new IllegalArgumentException("values parameter is null");
+        for (Object value : values) {
+            if (value == null) throw new IllegalArgumentException("A passed in value was null");
+            if (query == null) query = "";
+            else query += "&";
+            query += Encode.encodeQueryParam(name) + "=" + Encode.encodeQueryParam(value.toString());
+        }
+        return this;
+    }
+
+    public KeycloakUriBuilder replaceQueryParam(String name, Object... values) throws IllegalArgumentException {
+        if (name == null) throw new IllegalArgumentException("name parameter is null");
+        if (query == null || query.equals("")) {
+            if (values != null) return queryParam(name, values);
+            return this;
+        }
+
+        String[] params = query.split("&");
+        query = null;
+
+        String replacedName = Encode.encodeQueryParam(name);
+
+
+        for (String param : params) {
+            int pos = param.indexOf('=');
+            if (pos >= 0) {
+                String paramName = param.substring(0, pos);
+                if (paramName.equals(replacedName)) continue;
+            } else {
+                if (param.equals(replacedName)) continue;
+            }
+            if (query == null) query = "";
+            else query += "&";
+            query += param;
+        }
+        // don't set values if values is null
+        if (values == null) return this;
+        return queryParam(name, values);
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public String getScheme() {
+        return scheme;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public String getUserInfo() {
+        return userInfo;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public String getFragment() {
+        return fragment;
+    }
+
+    public KeycloakUriBuilder segment(String... segments) throws IllegalArgumentException {
+        if (segments == null) throw new IllegalArgumentException("segments parameter was null");
+        for (String segment : segments) {
+            if (segment == null) throw new IllegalArgumentException("A segment is null");
+            path(Encode.encodePathSegment(segment));
+        }
+        return this;
+    }
+
+    public KeycloakUriBuilder replacePath(String path) {
+        if (path == null) {
+            this.path = null;
+            return this;
+        }
+        this.path = Encode.encodePath(path);
+        return this;
+    }
+
+    public URI build(Object[] values, boolean encodeSlashInPath) throws IllegalArgumentException {
+        if (values == null) throw new IllegalArgumentException("values param is null");
+        return buildFromValues(encodeSlashInPath, false, values);
+    }
+
+    public String toTemplate() {
+        return buildString(new HashMap<String, Object>(), true, true, true);
+    }
+
+    public KeycloakUriBuilder resolveTemplate(String name, Object value) throws IllegalArgumentException {
+        if (name == null) throw new IllegalArgumentException("name param is null");
+        if (value == null) throw new IllegalArgumentException("value param is null");
+        HashMap<String, Object> vals = new HashMap<String, Object>();
+        vals.put(name, value);
+        return resolveTemplates(vals);
+    }
+
+    public KeycloakUriBuilder resolveTemplates(Map<String, Object> templateValues) throws IllegalArgumentException {
+        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
+        String str = buildString(templateValues, false, true, true);
+        return fromTemplate(str);
+    }
+
+    public KeycloakUriBuilder resolveTemplate(String name, Object value, boolean encodeSlashInPath) throws IllegalArgumentException {
+        if (name == null) throw new IllegalArgumentException("name param is null");
+        if (value == null) throw new IllegalArgumentException("value param is null");
+        HashMap<String, Object> vals = new HashMap<String, Object>();
+        vals.put(name, value);
+        String str = buildString(vals, false, true, encodeSlashInPath);
+        return fromTemplate(str);
+    }
+
+    public KeycloakUriBuilder resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) throws IllegalArgumentException {
+        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
+        String str = buildString(templateValues, false, true, encodeSlashInPath);
+        return fromTemplate(str);
+    }
+
+    public KeycloakUriBuilder resolveTemplatesFromEncoded(Map<String, Object> templateValues) throws IllegalArgumentException {
+        if (templateValues == null) throw new IllegalArgumentException("templateValues param null");
+        String str = buildString(templateValues, true, true, true);
+        return fromTemplate(str);
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/KeystoreUtil.java b/core/src/main/java/org/keycloak/util/KeystoreUtil.java
index ba264c0..a608572 100755
--- a/core/src/main/java/org/keycloak/util/KeystoreUtil.java
+++ b/core/src/main/java/org/keycloak/util/KeystoreUtil.java
@@ -1,25 +1,25 @@
-package org.keycloak.util;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.security.KeyStore;
-
-import org.keycloak.constants.GenericConstants;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeystoreUtil {
-
-    public static KeyStore loadKeyStore(String filename, String password) throws Exception {
-        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
-        InputStream trustStream = (filename.startsWith(GenericConstants.PROTOCOL_CLASSPATH))
-                ?KeystoreUtil.class.getResourceAsStream(filename.replace(GenericConstants.PROTOCOL_CLASSPATH, ""))
-                :new FileInputStream(new File(filename));
-        trustStore.load(trustStream, password.toCharArray());
-        trustStream.close();
-        return trustStore;
-    }
-}
+package org.keycloak.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.KeyStore;
+
+import org.keycloak.constants.GenericConstants;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeystoreUtil {
+
+    public static KeyStore loadKeyStore(String filename, String password) throws Exception {
+        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        InputStream trustStream = (filename.startsWith(GenericConstants.PROTOCOL_CLASSPATH))
+                ?KeystoreUtil.class.getResourceAsStream(filename.replace(GenericConstants.PROTOCOL_CLASSPATH, ""))
+                :new FileInputStream(new File(filename));
+        trustStore.load(trustStream, password.toCharArray());
+        trustStream.close();
+        return trustStore;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/PemUtils.java b/core/src/main/java/org/keycloak/util/PemUtils.java
index 4ba1133..90624aa 100755
--- a/core/src/main/java/org/keycloak/util/PemUtils.java
+++ b/core/src/main/java/org/keycloak/util/PemUtils.java
@@ -1,110 +1,110 @@
-package org.keycloak.util;
-
-
-import net.iharder.Base64;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-
-/**
- * Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public final class PemUtils {
-    static {
-        BouncyIntegration.init();
-    }
-
-    private PemUtils() {
-    }
-
-    public static X509Certificate decodeCertificate(InputStream is) throws Exception {
-        byte[] der = pemToDer(is);
-        ByteArrayInputStream bis = new ByteArrayInputStream(der);
-        return DerUtils.decodeCertificate(bis);
-    }
-
-    public static X509Certificate decodeCertificate(String cert) throws Exception {
-        byte[] der = pemToDer(cert);
-        ByteArrayInputStream bis = new ByteArrayInputStream(der);
-        return DerUtils.decodeCertificate(bis);
-    }
-
-
-    /**
-     * Extract a public key from a PEM string
-     *
-     * @param pem
-     * @return
-     * @throws Exception
-     */
-    public static PublicKey decodePublicKey(String pem) throws Exception {
-        byte[] der = pemToDer(pem);
-        return DerUtils.decodePublicKey(der);
-    }
-
-    /**
-     * Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
-     *
-     * @param pem
-     * @return
-     * @throws Exception
-     */
-    public static PrivateKey decodePrivateKey(String pem) throws Exception {
-        byte[] der = pemToDer(pem);
-        return DerUtils.decodePrivateKey(der);
-    }
-
-    public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
-        String pem = pemFromStream(is);
-        return decodePrivateKey(pem);
-    }
-
-    /**
-     * Decode a PEM file to DER format
-     *
-     * @param is
-     * @return
-     * @throws java.io.IOException
-     */
-    public static byte[] pemToDer(InputStream is) throws IOException {
-        String pem = pemFromStream(is);
-        return pemToDer(pem);
-    }
-
-    /**
-     * Decode a PEM string to DER format
-     *
-     * @param pem
-     * @return
-     * @throws java.io.IOException
-     */
-    public static byte[] pemToDer(String pem) throws IOException {
-        pem = removeBeginEnd(pem);
-        return Base64.decode(pem);
-    }
-
-    public static String removeBeginEnd(String pem) {
-        pem = pem.replaceAll("-----BEGIN (.*)-----", "");
-        pem = pem.replaceAll("-----END (.*)----", "");
-        pem = pem.replaceAll("\r\n", "");
-        pem = pem.replaceAll("\n", "");
-        return pem.trim();
-    }
-
-
-    public static String pemFromStream(InputStream is) throws IOException {
-        DataInputStream dis = new DataInputStream(is);
-        byte[] keyBytes = new byte[dis.available()];
-        dis.readFully(keyBytes);
-        dis.close();
-        return new String(keyBytes, "utf-8");
-    }
-}
+package org.keycloak.util;
+
+
+import net.iharder.Base64;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public final class PemUtils {
+    static {
+        BouncyIntegration.init();
+    }
+
+    private PemUtils() {
+    }
+
+    public static X509Certificate decodeCertificate(InputStream is) throws Exception {
+        byte[] der = pemToDer(is);
+        ByteArrayInputStream bis = new ByteArrayInputStream(der);
+        return DerUtils.decodeCertificate(bis);
+    }
+
+    public static X509Certificate decodeCertificate(String cert) throws Exception {
+        byte[] der = pemToDer(cert);
+        ByteArrayInputStream bis = new ByteArrayInputStream(der);
+        return DerUtils.decodeCertificate(bis);
+    }
+
+
+    /**
+     * Extract a public key from a PEM string
+     *
+     * @param pem
+     * @return
+     * @throws Exception
+     */
+    public static PublicKey decodePublicKey(String pem) throws Exception {
+        byte[] der = pemToDer(pem);
+        return DerUtils.decodePublicKey(der);
+    }
+
+    /**
+     * Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
+     *
+     * @param pem
+     * @return
+     * @throws Exception
+     */
+    public static PrivateKey decodePrivateKey(String pem) throws Exception {
+        byte[] der = pemToDer(pem);
+        return DerUtils.decodePrivateKey(der);
+    }
+
+    public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
+        String pem = pemFromStream(is);
+        return decodePrivateKey(pem);
+    }
+
+    /**
+     * Decode a PEM file to DER format
+     *
+     * @param is
+     * @return
+     * @throws java.io.IOException
+     */
+    public static byte[] pemToDer(InputStream is) throws IOException {
+        String pem = pemFromStream(is);
+        return pemToDer(pem);
+    }
+
+    /**
+     * Decode a PEM string to DER format
+     *
+     * @param pem
+     * @return
+     * @throws java.io.IOException
+     */
+    public static byte[] pemToDer(String pem) throws IOException {
+        pem = removeBeginEnd(pem);
+        return Base64.decode(pem);
+    }
+
+    public static String removeBeginEnd(String pem) {
+        pem = pem.replaceAll("-----BEGIN (.*)-----", "");
+        pem = pem.replaceAll("-----END (.*)----", "");
+        pem = pem.replaceAll("\r\n", "");
+        pem = pem.replaceAll("\n", "");
+        return pem.trim();
+    }
+
+
+    public static String pemFromStream(InputStream is) throws IOException {
+        DataInputStream dis = new DataInputStream(is);
+        byte[] keyBytes = new byte[dis.available()];
+        dis.readFully(keyBytes);
+        dis.close();
+        return new String(keyBytes, "utf-8");
+    }
+}
diff --git a/core/src/main/java/org/keycloak/util/StreamUtil.java b/core/src/main/java/org/keycloak/util/StreamUtil.java
index 4d382df..059932c 100755
--- a/core/src/main/java/org/keycloak/util/StreamUtil.java
+++ b/core/src/main/java/org/keycloak/util/StreamUtil.java
@@ -1,35 +1,35 @@
-package org.keycloak.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public final class StreamUtil {
-
-    private StreamUtil() {
-    }
-
-    public static String readString(InputStream in) throws IOException
-    {
-        char[] buffer = new char[1024];
-        StringBuilder builder = new StringBuilder();
-        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-        int wasRead;
-        do
-        {
-            wasRead = reader.read(buffer, 0, 1024);
-            if (wasRead > 0)
-            {
-                builder.append(buffer, 0, wasRead);
-            }
-        }
-        while (wasRead > -1);
-
-        return builder.toString();
-    }
-}
+package org.keycloak.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public final class StreamUtil {
+
+    private StreamUtil() {
+    }
+
+    public static String readString(InputStream in) throws IOException
+    {
+        char[] buffer = new char[1024];
+        StringBuilder builder = new StringBuilder();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+        int wasRead;
+        do
+        {
+            wasRead = reader.read(buffer, 0, 1024);
+            if (wasRead > 0)
+            {
+                builder.append(buffer, 0, wasRead);
+            }
+        }
+        while (wasRead > -1);
+
+        return builder.toString();
+    }
+}
diff --git a/core/src/main/java/org/keycloak/Version.java b/core/src/main/java/org/keycloak/Version.java
index 7b2c94f..8816843 100755
--- a/core/src/main/java/org/keycloak/Version.java
+++ b/core/src/main/java/org/keycloak/Version.java
@@ -1,48 +1,48 @@
-package org.keycloak;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class Version {
-    public static String VERSION;
-    public static String RESOURCES_VERSION;
-    public static String BUILD_TIME;
-    public static final String UNKNOWN = "UNKNOWN";
-    public static final Version SINGLETON;
-
-    private final String version = VERSION;
-    private final String buildTime = BUILD_TIME;
-
-    static {
-        Properties props = new Properties();
-        InputStream is = Version.class.getResourceAsStream("/keycloak-version.properties");
-        try {
-            props.load(is);
-            VERSION = props.getProperty("version");
-            BUILD_TIME = props.getProperty("build-time");
-            RESOURCES_VERSION = VERSION.toLowerCase();
-        } catch (IOException e) {
-            VERSION=UNKNOWN;
-            BUILD_TIME=UNKNOWN;
-        }
-
-        SINGLETON = new Version();
-    }
-
-    @JsonProperty("version")
-    public String getVersion() {
-        return version;
-    }
-
-    @JsonProperty("build-time")
-    public String getBuildTime() {
-        return buildTime;
-    }
-}
+package org.keycloak;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Version {
+    public static String VERSION;
+    public static String RESOURCES_VERSION;
+    public static String BUILD_TIME;
+    public static final String UNKNOWN = "UNKNOWN";
+    public static final Version SINGLETON;
+
+    private final String version = VERSION;
+    private final String buildTime = BUILD_TIME;
+
+    static {
+        Properties props = new Properties();
+        InputStream is = Version.class.getResourceAsStream("/keycloak-version.properties");
+        try {
+            props.load(is);
+            VERSION = props.getProperty("version");
+            BUILD_TIME = props.getProperty("build-time");
+            RESOURCES_VERSION = VERSION.toLowerCase();
+        } catch (IOException e) {
+            VERSION=UNKNOWN;
+            BUILD_TIME=UNKNOWN;
+        }
+
+        SINGLETON = new Version();
+    }
+
+    @JsonProperty("version")
+    public String getVersion() {
+        return version;
+    }
+
+    @JsonProperty("build-time")
+    public String getBuildTime() {
+        return buildTime;
+    }
+}
diff --git a/core/src/main/resources/keycloak-version.properties b/core/src/main/resources/keycloak-version.properties
index 9d6f352..35a5d57 100755
--- a/core/src/main/resources/keycloak-version.properties
+++ b/core/src/main/resources/keycloak-version.properties
@@ -1,2 +1,2 @@
-version=${project.version}
+version=${project.version}
 build-time=${timestamp}
\ No newline at end of file
diff --git a/core/src/test/java/org/keycloak/RSAVerifierTest.java b/core/src/test/java/org/keycloak/RSAVerifierTest.java
index 5382866..eaa689c 100755
--- a/core/src/test/java/org/keycloak/RSAVerifierTest.java
+++ b/core/src/test/java/org/keycloak/RSAVerifierTest.java
@@ -1,231 +1,231 @@
-package org.keycloak;
-
-import junit.framework.Assert;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMWriter;
-import org.bouncycastle.x509.X509V1CertificateGenerator;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.util.Time;
-
-import javax.security.auth.x500.X500Principal;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.SignatureException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RSAVerifierTest {
-    private static X509Certificate[] idpCertificates;
-    private static KeyPair idpPair;
-    private static KeyPair badPair;
-    private static KeyPair clientPair;
-    private static X509Certificate[] clientCertificateChain;
-    private AccessToken token;
-
-    static {
-        if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
-    }
-
-    public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair) throws InvalidKeyException,
-            NoSuchProviderException, SignatureException {
-
-        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
-
-        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
-        certGen.setIssuerDN(new X500Principal(issuer));
-        certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));
-        certGen.setNotAfter(new Date(System.currentTimeMillis() + 10000));
-        certGen.setSubjectDN(new X500Principal(subject));
-        certGen.setPublicKey(pair.getPublic());
-        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
-
-        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
-    }
-
-    @BeforeClass
-    public static void setupCerts() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
-        badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-        idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-        idpCertificates = new X509Certificate[]{generateTestCertificate("CN=IDP", "CN=IDP", idpPair)};
-        clientPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-        clientCertificateChain = new X509Certificate[]{generateTestCertificate("CN=Client", "CN=IDP", idpPair)};
-    }
-
-    @Before
-    public void initTest() {
-
-        token = new AccessToken();
-        token.subject("CN=Client")
-                .issuer("http://localhost:8080/auth/realm")
-                .addAccess("service").addRole("admin");
-    }
-
-    @Test
-    public void testPemWriter() throws Exception {
-        PublicKey realmPublicKey = idpPair.getPublic();
-        StringWriter sw = new StringWriter();
-        PEMWriter writer = new PEMWriter(sw);
-        try {
-            writer.writeObject(realmPublicKey);
-            writer.flush();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        System.out.println(sw.toString());
-    }
-
-
-    @Test
-    public void testSimpleVerification() throws Exception {
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-        AccessToken token = verifySkeletonKeyToken(encoded);
-        Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
-        Assert.assertEquals("CN=Client", token.getSubject());
-    }
-
-    private AccessToken verifySkeletonKeyToken(String encoded) throws VerificationException {
-        return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm");
-    }
-
-   /*
-   @Test
-   public void testSpeed() throws Exception
-   {
-
-      byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
-
-      String encoded = new JWSBuilder()
-              .content(tokenBytes)
-              .rsa256(idpPair.getPrivate());
-
-      long start = System.currentTimeMillis();
-      int count = 10000;
-      for (int i = 0; i < count; i++)
-      {
-         SkeletonKeyTokenVerification v = RSATokenVerifier.verify(null, encoded, metadata);
-
-      }
-      long end = System.currentTimeMillis() - start;
-      System.out.println("rate: " + ((double)end/(double)count));
-   }
-   */
-
-
-    @Test
-    public void testBadSignature() throws Exception {
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(badPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-            Assert.fail();
-        } catch (VerificationException ignored) {
-        }
-    }
-
-    @Test
-    public void testNotBeforeGood() throws Exception {
-        token.notBefore(Time.currentTime() - 100);
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-        } catch (VerificationException ignored) {
-            throw ignored;
-        }
-    }
-
-    @Test
-    public void testNotBeforeBad() throws Exception {
-        token.notBefore(Time.currentTime() + 100);
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-            Assert.fail();
-        } catch (VerificationException ignored) {
-            System.out.println(ignored.getMessage());
-        }
-    }
-
-    @Test
-    public void testExpirationGood() throws Exception {
-        token.expiration(Time.currentTime() + 100);
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-        } catch (VerificationException ignored) {
-            throw ignored;
-        }
-    }
-
-    @Test
-    public void testExpirationBad() throws Exception {
-        token.expiration(Time.currentTime() - 100);
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-            Assert.fail();
-        } catch (VerificationException ignored) {
-        }
-    }
-
-    @Test
-    public void testTokenAuth() throws Exception {
-        token = new AccessToken();
-        token.subject("CN=Client")
-                .issuer("domain")
-                .addAccess("service").addRole("admin").verifyCaller(true);
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(idpPair.getPrivate());
-
-        AccessToken v = null;
-        try {
-            v = verifySkeletonKeyToken(encoded);
-        } catch (VerificationException ignored) {
-        }
-    }
-
-
-}
+package org.keycloak;
+
+import junit.framework.Assert;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMWriter;
+import org.bouncycastle.x509.X509V1CertificateGenerator;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.util.Time;
+
+import javax.security.auth.x500.X500Principal;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RSAVerifierTest {
+    private static X509Certificate[] idpCertificates;
+    private static KeyPair idpPair;
+    private static KeyPair badPair;
+    private static KeyPair clientPair;
+    private static X509Certificate[] clientCertificateChain;
+    private AccessToken token;
+
+    static {
+        if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
+    }
+
+    public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair) throws InvalidKeyException,
+            NoSuchProviderException, SignatureException {
+
+        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
+
+        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
+        certGen.setIssuerDN(new X500Principal(issuer));
+        certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));
+        certGen.setNotAfter(new Date(System.currentTimeMillis() + 10000));
+        certGen.setSubjectDN(new X500Principal(subject));
+        certGen.setPublicKey(pair.getPublic());
+        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
+
+        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
+    }
+
+    @BeforeClass
+    public static void setupCerts() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
+        badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+        idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+        idpCertificates = new X509Certificate[]{generateTestCertificate("CN=IDP", "CN=IDP", idpPair)};
+        clientPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+        clientCertificateChain = new X509Certificate[]{generateTestCertificate("CN=Client", "CN=IDP", idpPair)};
+    }
+
+    @Before
+    public void initTest() {
+
+        token = new AccessToken();
+        token.subject("CN=Client")
+                .issuer("http://localhost:8080/auth/realm")
+                .addAccess("service").addRole("admin");
+    }
+
+    @Test
+    public void testPemWriter() throws Exception {
+        PublicKey realmPublicKey = idpPair.getPublic();
+        StringWriter sw = new StringWriter();
+        PEMWriter writer = new PEMWriter(sw);
+        try {
+            writer.writeObject(realmPublicKey);
+            writer.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        System.out.println(sw.toString());
+    }
+
+
+    @Test
+    public void testSimpleVerification() throws Exception {
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+        AccessToken token = verifySkeletonKeyToken(encoded);
+        Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
+        Assert.assertEquals("CN=Client", token.getSubject());
+    }
+
+    private AccessToken verifySkeletonKeyToken(String encoded) throws VerificationException {
+        return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm");
+    }
+
+   /*
+   @Test
+   public void testSpeed() throws Exception
+   {
+
+      byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
+
+      String encoded = new JWSBuilder()
+              .content(tokenBytes)
+              .rsa256(idpPair.getPrivate());
+
+      long start = System.currentTimeMillis();
+      int count = 10000;
+      for (int i = 0; i < count; i++)
+      {
+         SkeletonKeyTokenVerification v = RSATokenVerifier.verify(null, encoded, metadata);
+
+      }
+      long end = System.currentTimeMillis() - start;
+      System.out.println("rate: " + ((double)end/(double)count));
+   }
+   */
+
+
+    @Test
+    public void testBadSignature() throws Exception {
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(badPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+            Assert.fail();
+        } catch (VerificationException ignored) {
+        }
+    }
+
+    @Test
+    public void testNotBeforeGood() throws Exception {
+        token.notBefore(Time.currentTime() - 100);
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+        } catch (VerificationException ignored) {
+            throw ignored;
+        }
+    }
+
+    @Test
+    public void testNotBeforeBad() throws Exception {
+        token.notBefore(Time.currentTime() + 100);
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+            Assert.fail();
+        } catch (VerificationException ignored) {
+            System.out.println(ignored.getMessage());
+        }
+    }
+
+    @Test
+    public void testExpirationGood() throws Exception {
+        token.expiration(Time.currentTime() + 100);
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+        } catch (VerificationException ignored) {
+            throw ignored;
+        }
+    }
+
+    @Test
+    public void testExpirationBad() throws Exception {
+        token.expiration(Time.currentTime() - 100);
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+            Assert.fail();
+        } catch (VerificationException ignored) {
+        }
+    }
+
+    @Test
+    public void testTokenAuth() throws Exception {
+        token = new AccessToken();
+        token.subject("CN=Client")
+                .issuer("domain")
+                .addAccess("service").addRole("admin").verifyCaller(true);
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(idpPair.getPrivate());
+
+        AccessToken v = null;
+        try {
+            v = verifySkeletonKeyToken(encoded);
+        } catch (VerificationException ignored) {
+        }
+    }
+
+
+}
diff --git a/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java b/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java
index 789b944..4dc26cf 100755
--- a/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java
+++ b/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java
@@ -1,112 +1,112 @@
-package org.keycloak;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SkeletonKeyTokenTest {
-    @Test
-    public void testToken() throws Exception {
-        AccessToken token = createSimpleToken();
-
-        String json = JsonSerialization.writeValueAsString(token);
-        token = JsonSerialization.readValue(json, AccessToken.class);
-        Assert.assertEquals("111", token.getId());
-        AccessToken.Access foo = token.getResourceAccess("foo");
-        Assert.assertNotNull(foo);
-        Assert.assertTrue(foo.isUserInRole("admin"));
-
-    }
-
-    @Test
-    public void testRSA() throws Exception {
-        AccessToken token = createSimpleToken();
-        token.id("111");
-        token.addAccess("foo").addRole("admin");
-        token.addAccess("bar").addRole("user");
-
-        KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(keyPair.getPrivate());
-
-        JWSInput input = new JWSInput(encoded);
-
-        token = input.readJsonContent(AccessToken.class);
-        Assert.assertEquals("111", token.getId());
-        Assert.assertTrue(RSAProvider.verify(input, keyPair.getPublic()));
-    }
-
-    @Test
-    public void testSerialization() throws Exception {
-        AccessToken token = createSimpleToken();
-        IDToken idToken = new IDToken();
-
-        idToken.setEmail("joe@email.cz");
-
-        KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-
-        String encoded = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(keyPair.getPrivate());
-        String encodedIdToken = new JWSBuilder()
-                .jsonContent(idToken)
-                .rsa256(keyPair.getPrivate());
-
-        KeycloakSecurityContext ctx = new KeycloakSecurityContext(encoded, token, encodedIdToken, idToken);
-        KeycloakPrincipal principal = new KeycloakPrincipal("joe", ctx);
-
-        // Serialize
-        ByteArrayOutputStream bso = new ByteArrayOutputStream();
-        ObjectOutputStream oos = new ObjectOutputStream(bso);
-        oos.writeObject(principal);
-        oos.close();
-
-        // Deserialize
-        byte[] bytes = bso.toByteArray();
-        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
-        ObjectInputStream ois = new ObjectInputStream(bis);
-        principal = (KeycloakPrincipal)ois.readObject();
-        ctx = principal.getKeycloakSecurityContext();
-        token = ctx.getToken();
-        idToken = ctx.getIdToken();
-
-        System.out.println("Size of serialized principal: " + bytes.length);
-
-        Assert.assertEquals(encoded, ctx.getTokenString());
-        Assert.assertEquals(encodedIdToken, ctx.getIdTokenString());
-        Assert.assertEquals("111", token.getId());
-        Assert.assertEquals("111", token.getId());
-        Assert.assertTrue(token.getResourceAccess("foo").isUserInRole("admin"));
-        Assert.assertTrue(token.getResourceAccess("bar").isUserInRole("user"));
-        Assert.assertEquals("joe@email.cz", idToken.getEmail());
-        Assert.assertEquals("acme", ctx.getRealm());
-        ois.close();
-    }
-
-    private AccessToken createSimpleToken() {
-        AccessToken token = new AccessToken();
-        token.id("111");
-        token.issuer("http://localhost:8080/auth/acme");
-        token.addAccess("foo").addRole("admin");
-        token.addAccess("bar").addRole("user");
-        return token;
-    }
-}
+package org.keycloak;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SkeletonKeyTokenTest {
+    @Test
+    public void testToken() throws Exception {
+        AccessToken token = createSimpleToken();
+
+        String json = JsonSerialization.writeValueAsString(token);
+        token = JsonSerialization.readValue(json, AccessToken.class);
+        Assert.assertEquals("111", token.getId());
+        AccessToken.Access foo = token.getResourceAccess("foo");
+        Assert.assertNotNull(foo);
+        Assert.assertTrue(foo.isUserInRole("admin"));
+
+    }
+
+    @Test
+    public void testRSA() throws Exception {
+        AccessToken token = createSimpleToken();
+        token.id("111");
+        token.addAccess("foo").addRole("admin");
+        token.addAccess("bar").addRole("user");
+
+        KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(keyPair.getPrivate());
+
+        JWSInput input = new JWSInput(encoded);
+
+        token = input.readJsonContent(AccessToken.class);
+        Assert.assertEquals("111", token.getId());
+        Assert.assertTrue(RSAProvider.verify(input, keyPair.getPublic()));
+    }
+
+    @Test
+    public void testSerialization() throws Exception {
+        AccessToken token = createSimpleToken();
+        IDToken idToken = new IDToken();
+
+        idToken.setEmail("joe@email.cz");
+
+        KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+
+        String encoded = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(keyPair.getPrivate());
+        String encodedIdToken = new JWSBuilder()
+                .jsonContent(idToken)
+                .rsa256(keyPair.getPrivate());
+
+        KeycloakSecurityContext ctx = new KeycloakSecurityContext(encoded, token, encodedIdToken, idToken);
+        KeycloakPrincipal principal = new KeycloakPrincipal("joe", ctx);
+
+        // Serialize
+        ByteArrayOutputStream bso = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bso);
+        oos.writeObject(principal);
+        oos.close();
+
+        // Deserialize
+        byte[] bytes = bso.toByteArray();
+        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+        ObjectInputStream ois = new ObjectInputStream(bis);
+        principal = (KeycloakPrincipal)ois.readObject();
+        ctx = principal.getKeycloakSecurityContext();
+        token = ctx.getToken();
+        idToken = ctx.getIdToken();
+
+        System.out.println("Size of serialized principal: " + bytes.length);
+
+        Assert.assertEquals(encoded, ctx.getTokenString());
+        Assert.assertEquals(encodedIdToken, ctx.getIdTokenString());
+        Assert.assertEquals("111", token.getId());
+        Assert.assertEquals("111", token.getId());
+        Assert.assertTrue(token.getResourceAccess("foo").isUserInRole("admin"));
+        Assert.assertTrue(token.getResourceAccess("bar").isUserInRole("user"));
+        Assert.assertEquals("joe@email.cz", idToken.getEmail());
+        Assert.assertEquals("acme", ctx.getRealm());
+        ois.close();
+    }
+
+    private AccessToken createSimpleToken() {
+        AccessToken token = new AccessToken();
+        token.id("111");
+        token.issuer("http://localhost:8080/auth/acme");
+        token.addAccess("foo").addRole("admin");
+        token.addAccess("bar").addRole("user");
+        return token;
+    }
+}

core-jaxrs/pom.xml 132(+66 -66)

diff --git a/core-jaxrs/pom.xml b/core-jaxrs/pom.xml
index 78bf93d..d2329eb 100755
--- a/core-jaxrs/pom.xml
+++ b/core-jaxrs/pom.xml
@@ -1,66 +1,66 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-core-jaxrs</artifactId>
-    <name>Keycloak Core JAX-RS</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-core-jaxrs</artifactId>
+    <name>Keycloak Core JAX-RS</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/core-jaxrs/src/main/java/org/keycloak/SkeletonKeyContextResolver.java b/core-jaxrs/src/main/java/org/keycloak/SkeletonKeyContextResolver.java
index 8c99cad..d17bfd2 100755
--- a/core-jaxrs/src/main/java/org/keycloak/SkeletonKeyContextResolver.java
+++ b/core-jaxrs/src/main/java/org/keycloak/SkeletonKeyContextResolver.java
@@ -1,37 +1,37 @@
-package org.keycloak;
-
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-
-import javax.ws.rs.ext.ContextResolver;
-import javax.ws.rs.ext.Provider;
-
-/**
- * Any class with package org.jboss.resteasy.skeleton.key will use NON_DEFAULT inclusion
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Provider
-public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper> {
-    protected ObjectMapper mapper = new ObjectMapper();
-
-    public SkeletonKeyContextResolver() {
-        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
-    }
-
-    public SkeletonKeyContextResolver(boolean indent) {
-        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
-        if (indent) {
-            mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
-        }
-    }
-
-
-    @Override
-    public ObjectMapper getContext(Class<?> type) {
-        if (type.getPackage() != null && type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
-        return null;
-    }
-}
+package org.keycloak;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Any class with package org.jboss.resteasy.skeleton.key will use NON_DEFAULT inclusion
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Provider
+public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper> {
+    protected ObjectMapper mapper = new ObjectMapper();
+
+    public SkeletonKeyContextResolver() {
+        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
+    }
+
+    public SkeletonKeyContextResolver(boolean indent) {
+        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
+        if (indent) {
+            mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
+        }
+    }
+
+
+    @Override
+    public ObjectMapper getContext(Class<?> type) {
+        if (type.getPackage() != null && type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
+        return null;
+    }
+}

dependencies/pom.xml 64(+32 -32)

diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index 692d4a5..27c67ed 100755
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -1,32 +1,32 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>keycloak-dependencies-parent</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Dependencies Parent</name>
-    <description/>
-
-    <modules>
-        <module>server-min</module>
-        <module>server-all</module>
-    </modules>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>keycloak-dependencies-parent</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Dependencies Parent</name>
+    <description/>
+
+    <modules>
+        <module>server-min</module>
+        <module>server-all</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml
index c813be8..2a3d557 100755
--- a/dependencies/server-all/pom.xml
+++ b/dependencies/server-all/pom.xml
@@ -1,184 +1,184 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-dependencies-server-all</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Dependencies Server All</name>
-	<description />
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-min</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa-liquibase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-infinispan</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-file</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-sessions-mem</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-sessions-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-sessions-mongo</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-sessions-infinispan</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-email</artifactId>
-        </dependency>
-
-        <!-- identity providers -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-oidc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-saml</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-github</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-google</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-twitter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.twitter4j</groupId>
-            <artifactId>twitter4j-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-facebook</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-linkedin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-stackoverflow</artifactId>
-        </dependency>
-
-        <!-- ldap federation api -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-kerberos-federation</artifactId>
-        </dependency>
-
-        <!-- saml -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-protocol</artifactId>
-        </dependency>
-
-        <!-- mongo -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-mongo</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-mongo-update</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-mongo</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-mongo</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-        </dependency>
-
-        <!-- export/import -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-export-import-zip</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>de.idyl</groupId>
-            <artifactId>winzipaes</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.bouncycastle</groupId>
-                    <artifactId>bcprov-jdk16</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.liquibase</groupId>
-            <artifactId>liquibase-core</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.yaml</groupId>
-                    <artifactId>snakeyaml</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-    </dependencies>
-
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-dependencies-server-all</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Dependencies Server All</name>
+	<description />
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-min</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa-liquibase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-infinispan</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-file</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-sessions-mem</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-sessions-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-sessions-mongo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-sessions-infinispan</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-email</artifactId>
+        </dependency>
+
+        <!-- identity providers -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-oidc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-saml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-github</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-google</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-twitter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.twitter4j</groupId>
+            <artifactId>twitter4j-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-facebook</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-linkedin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-stackoverflow</artifactId>
+        </dependency>
+
+        <!-- ldap federation api -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-kerberos-federation</artifactId>
+        </dependency>
+
+        <!-- saml -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-protocol</artifactId>
+        </dependency>
+
+        <!-- mongo -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-mongo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-mongo-update</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-mongo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-mongo</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+        </dependency>
+
+        <!-- export/import -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-export-import-zip</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.idyl</groupId>
+            <artifactId>winzipaes</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>bcprov-jdk16</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.liquibase</groupId>
+            <artifactId>liquibase-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.yaml</groupId>
+                    <artifactId>snakeyaml</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
 </project>
\ No newline at end of file
diff --git a/dependencies/server-min/pom.xml b/dependencies/server-min/pom.xml
index 009742e..21a8d25 100755
--- a/dependencies/server-min/pom.xml
+++ b/dependencies/server-min/pom.xml
@@ -1,145 +1,145 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-dependencies-server-min</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Dependencies Server Min</name>
-	<description />
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core-jaxrs</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-invalidation-cache-model</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-js-adapter</artifactId>
-        </dependency>
-
-        <!-- social -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-core</artifactId>
-        </dependency>
-
-        <!-- forms -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.freemarker</groupId>
-            <artifactId>freemarker</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-themes</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-account-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-account-freemarker</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-freemarker</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-login-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-login-freemarker</artifactId>
-        </dependency>
-
-        <!-- timer -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-timer-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-timer-basic</artifactId>
-        </dependency>
-
-        <!-- export/import -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-export-import-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-export-import-dir</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-export-import-single-file</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-http-client</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-dependencies-server-min</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Dependencies Server Min</name>
+	<description />
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core-jaxrs</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-js-adapter</artifactId>
+        </dependency>
+
+        <!-- social -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+        </dependency>
+
+        <!-- forms -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-themes</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-account-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-account-freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-login-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-login-freemarker</artifactId>
+        </dependency>
+
+        <!-- timer -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-timer-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-timer-basic</artifactId>
+        </dependency>
+
+        <!-- export/import -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-export-import-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-export-import-dir</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-export-import-single-file</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/distribution/adapters/jetty81-adapter-zip/assembly.xml b/distribution/adapters/jetty81-adapter-zip/assembly.xml
index dac7e92..5ba77b9 100755
--- a/distribution/adapters/jetty81-adapter-zip/assembly.xml
+++ b/distribution/adapters/jetty81-adapter-zip/assembly.xml
@@ -1,26 +1,26 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-jetty81-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.eclipse.jetty:jetty-server</exclude>
-                <exclude>org.eclipse.jetty:jetty-util</exclude>
-                <exclude>org.eclipse.jetty:jetty-security</exclude>
-            </excludes>
-            <outputDirectory>lib/keycloak</outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-jetty81-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.eclipse.jetty:jetty-server</exclude>
+                <exclude>org.eclipse.jetty:jetty-util</exclude>
+                <exclude>org.eclipse.jetty:jetty-security</exclude>
+            </excludes>
+            <outputDirectory>lib/keycloak</outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/jetty81-adapter-zip/pom.xml b/distribution/adapters/jetty81-adapter-zip/pom.xml
index 18e3a3b..233a09b 100755
--- a/distribution/adapters/jetty81-adapter-zip/pom.xml
+++ b/distribution/adapters/jetty81-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-jetty81-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Jetty 8.1.x Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty81-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-jetty81-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Jetty 8.1.x Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty81-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/jetty91-adapter-zip/assembly.xml b/distribution/adapters/jetty91-adapter-zip/assembly.xml
index 1d938be..9faeb32 100755
--- a/distribution/adapters/jetty91-adapter-zip/assembly.xml
+++ b/distribution/adapters/jetty91-adapter-zip/assembly.xml
@@ -1,39 +1,39 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory></directory>
-            <includes>
-                <include>keycloak.mod</include>
-            </includes>
-            <outputDirectory>modules</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/modules</directory>
-            <outputDirectory></outputDirectory>
-        </fileSet>
-    </fileSets>
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-jetty91-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.eclipse.jetty:jetty-server</exclude>
-                <exclude>org.eclipse.jetty:jetty-util</exclude>
-                <exclude>org.eclipse.jetty:jetty-security</exclude>
-            </excludes>
-            <outputDirectory>lib/keycloak</outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory></directory>
+            <includes>
+                <include>keycloak.mod</include>
+            </includes>
+            <outputDirectory>modules</outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/modules</directory>
+            <outputDirectory></outputDirectory>
+        </fileSet>
+    </fileSets>
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-jetty91-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.eclipse.jetty:jetty-server</exclude>
+                <exclude>org.eclipse.jetty:jetty-util</exclude>
+                <exclude>org.eclipse.jetty:jetty-security</exclude>
+            </excludes>
+            <outputDirectory>lib/keycloak</outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/jetty91-adapter-zip/keycloak.mod b/distribution/adapters/jetty91-adapter-zip/keycloak.mod
index 130f4e9..10550d8 100755
--- a/distribution/adapters/jetty91-adapter-zip/keycloak.mod
+++ b/distribution/adapters/jetty91-adapter-zip/keycloak.mod
@@ -1,11 +1,11 @@
-#
-# Keycloak Jetty Adapter
-#
-
-[depend]
-server
-security
-
-[lib]
-lib/keycloak/*.jar
-
+#
+# Keycloak Jetty Adapter
+#
+
+[depend]
+server
+security
+
+[lib]
+lib/keycloak/*.jar
+
diff --git a/distribution/adapters/jetty91-adapter-zip/pom.xml b/distribution/adapters/jetty91-adapter-zip/pom.xml
index 5c47600..552de5f 100755
--- a/distribution/adapters/jetty91-adapter-zip/pom.xml
+++ b/distribution/adapters/jetty91-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-jetty91-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Jetty 9.1.x Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty91-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-jetty91-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Jetty 9.1.x Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty91-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/jetty92-adapter-zip/assembly.xml b/distribution/adapters/jetty92-adapter-zip/assembly.xml
index 4858ff1..89d3709 100755
--- a/distribution/adapters/jetty92-adapter-zip/assembly.xml
+++ b/distribution/adapters/jetty92-adapter-zip/assembly.xml
@@ -1,39 +1,39 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory></directory>
-            <includes>
-                <include>keycloak.mod</include>
-            </includes>
-            <outputDirectory>modules</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/modules</directory>
-            <outputDirectory></outputDirectory>
-        </fileSet>
-    </fileSets>
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-jetty92-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.eclipse.jetty:jetty-server</exclude>
-                <exclude>org.eclipse.jetty:jetty-util</exclude>
-                <exclude>org.eclipse.jetty:jetty-security</exclude>
-            </excludes>
-            <outputDirectory>lib/keycloak</outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory></directory>
+            <includes>
+                <include>keycloak.mod</include>
+            </includes>
+            <outputDirectory>modules</outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/modules</directory>
+            <outputDirectory></outputDirectory>
+        </fileSet>
+    </fileSets>
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-jetty92-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.eclipse.jetty:jetty-server</exclude>
+                <exclude>org.eclipse.jetty:jetty-util</exclude>
+                <exclude>org.eclipse.jetty:jetty-security</exclude>
+            </excludes>
+            <outputDirectory>lib/keycloak</outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/jetty92-adapter-zip/keycloak.mod b/distribution/adapters/jetty92-adapter-zip/keycloak.mod
index 130f4e9..10550d8 100755
--- a/distribution/adapters/jetty92-adapter-zip/keycloak.mod
+++ b/distribution/adapters/jetty92-adapter-zip/keycloak.mod
@@ -1,11 +1,11 @@
-#
-# Keycloak Jetty Adapter
-#
-
-[depend]
-server
-security
-
-[lib]
-lib/keycloak/*.jar
-
+#
+# Keycloak Jetty Adapter
+#
+
+[depend]
+server
+security
+
+[lib]
+lib/keycloak/*.jar
+
diff --git a/distribution/adapters/jetty92-adapter-zip/pom.xml b/distribution/adapters/jetty92-adapter-zip/pom.xml
index c3aeac0..ffe5102 100755
--- a/distribution/adapters/jetty92-adapter-zip/pom.xml
+++ b/distribution/adapters/jetty92-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-jetty92-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Jetty 9.2.x Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty92-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-jetty92-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Jetty 9.2.x Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty92-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/js-adapter-zip/assembly.xml b/distribution/adapters/js-adapter-zip/assembly.xml
index 4382d91..933f469 100755
--- a/distribution/adapters/js-adapter-zip/assembly.xml
+++ b/distribution/adapters/js-adapter-zip/assembly.xml
@@ -1,20 +1,20 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/js-adapter</directory>
-            <outputDirectory></outputDirectory>
-            <includes>
-                <include>**/*.js</include>
-                <include>**/*.html</include>
-            </includes>
-        </fileSet>
-    </fileSets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/js-adapter</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>**/*.js</include>
+                <include>**/*.html</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/distribution/adapters/js-adapter-zip/pom.xml b/distribution/adapters/js-adapter-zip/pom.xml
index 6934300..b5af6f2 100755
--- a/distribution/adapters/js-adapter-zip/pom.xml
+++ b/distribution/adapters/js-adapter-zip/pom.xml
@@ -1,71 +1,71 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-js-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak JS Adapter Distribution</name>
-    <description/>
-
-    <dependencies>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>unpack</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-js-adapter</artifactId>
-                                    <outputDirectory>${project.build.directory}/unpacked/js-adapter</outputDirectory>
-                                    <includes>*.js</includes>                                    
-                                </artifactItem>
-                            </artifactItems>
-                            <excludes>**/welcome-content/*</excludes>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-js-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak JS Adapter Distribution</name>
+    <description/>
+
+    <dependencies>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-js-adapter</artifactId>
+                                    <outputDirectory>${project.build.directory}/unpacked/js-adapter</outputDirectory>
+                                    <includes>*.js</includes>                                    
+                                </artifactItem>
+                            </artifactItems>
+                            <excludes>**/welcome-content/*</excludes>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/pom.xml b/distribution/adapters/pom.xml
index 2bbf342..00faf0f 100755
--- a/distribution/adapters/pom.xml
+++ b/distribution/adapters/pom.xml
@@ -1,30 +1,30 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <name>Adapters Distribution Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-adapters-distribution-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>as7-eap6-adapter</module>
-        <module>jetty81-adapter-zip</module>
-        <module>jetty91-adapter-zip</module>
-        <module>jetty92-adapter-zip</module>
-        <module>js-adapter-zip</module>
-        <module>osgi</module>
-        <module>tomcat6-adapter-zip</module>
-        <module>tomcat7-adapter-zip</module>
-        <module>tomcat8-adapter-zip</module>
-        <module>wf8-adapter</module>
-        <module>wf9-adapter</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <name>Adapters Distribution Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-adapters-distribution-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>as7-eap6-adapter</module>
+        <module>jetty81-adapter-zip</module>
+        <module>jetty91-adapter-zip</module>
+        <module>jetty92-adapter-zip</module>
+        <module>js-adapter-zip</module>
+        <module>osgi</module>
+        <module>tomcat6-adapter-zip</module>
+        <module>tomcat7-adapter-zip</module>
+        <module>tomcat8-adapter-zip</module>
+        <module>wf8-adapter</module>
+        <module>wf9-adapter</module>
+    </modules>
+</project>
diff --git a/distribution/adapters/tomcat6-adapter-zip/assembly.xml b/distribution/adapters/tomcat6-adapter-zip/assembly.xml
index dbb4741..9229fce 100755
--- a/distribution/adapters/tomcat6-adapter-zip/assembly.xml
+++ b/distribution/adapters/tomcat6-adapter-zip/assembly.xml
@@ -1,24 +1,24 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-tomcat6-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.apache.tomcat:catalina</exclude>
-            </excludes>
-            <outputDirectory></outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-tomcat6-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.apache.tomcat:catalina</exclude>
+            </excludes>
+            <outputDirectory></outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/tomcat6-adapter-zip/pom.xml b/distribution/adapters/tomcat6-adapter-zip/pom.xml
index 26d555c..578fd70 100755
--- a/distribution/adapters/tomcat6-adapter-zip/pom.xml
+++ b/distribution/adapters/tomcat6-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-tomcat6-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Tomcat 6 Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat6-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-tomcat6-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Tomcat 6 Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat6-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/tomcat7-adapter-zip/assembly.xml b/distribution/adapters/tomcat7-adapter-zip/assembly.xml
index 3084225..efde454 100755
--- a/distribution/adapters/tomcat7-adapter-zip/assembly.xml
+++ b/distribution/adapters/tomcat7-adapter-zip/assembly.xml
@@ -1,25 +1,25 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-tomcat7-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
-                <exclude>org.apache.tomcat:tomcat-catalina</exclude>
-            </excludes>
-            <outputDirectory></outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-tomcat7-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
+                <exclude>org.apache.tomcat:tomcat-catalina</exclude>
+            </excludes>
+            <outputDirectory></outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/tomcat7-adapter-zip/pom.xml b/distribution/adapters/tomcat7-adapter-zip/pom.xml
index edb5ea7..a80ce63 100755
--- a/distribution/adapters/tomcat7-adapter-zip/pom.xml
+++ b/distribution/adapters/tomcat7-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-tomcat7-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Tomcat 7 Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat7-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-tomcat7-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Tomcat 7 Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat7-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/adapters/tomcat8-adapter-zip/assembly.xml b/distribution/adapters/tomcat8-adapter-zip/assembly.xml
index c6c2f2a..c67ed24 100755
--- a/distribution/adapters/tomcat8-adapter-zip/assembly.xml
+++ b/distribution/adapters/tomcat8-adapter-zip/assembly.xml
@@ -1,25 +1,25 @@
-<assembly>
-    <id>war-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-    <includeBaseDirectory>false</includeBaseDirectory>
-
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-tomcat8-adapter</include>
-            </includes>
-            <excludes>
-                <exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
-                <exclude>org.apache.tomcat:tomcat-catalina</exclude>
-            </excludes>
-            <outputDirectory></outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>war-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-tomcat8-adapter</include>
+            </includes>
+            <excludes>
+                <exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
+                <exclude>org.apache.tomcat:tomcat-catalina</exclude>
+            </excludes>
+            <outputDirectory></outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/adapters/tomcat8-adapter-zip/pom.xml b/distribution/adapters/tomcat8-adapter-zip/pom.xml
index ce7a4f5..8a62ee4 100755
--- a/distribution/adapters/tomcat8-adapter-zip/pom.xml
+++ b/distribution/adapters/tomcat8-adapter-zip/pom.xml
@@ -1,51 +1,51 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-tomcat8-adapter-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Tomcat 8 Adapter Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat8-adapter</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-tomcat8-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Tomcat 8 Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat8-adapter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/demo-dist/assembly.xml b/distribution/demo-dist/assembly.xml
index cdd484d..c6f4664 100755
--- a/distribution/demo-dist/assembly.xml
+++ b/distribution/demo-dist/assembly.xml
@@ -1,58 +1,58 @@
-<assembly>
-    <id>demo-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/wildfly-${wildfly.version}</directory>
-            <outputDirectory>keycloak</outputDirectory>
-            <excludes>
-                <exclude>**/*.sh</exclude>
-                <exclude>**/standalone.xml</exclude>
-            </excludes>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/wildfly-${wildfly.version}</directory>
-            <outputDirectory>keycloak</outputDirectory>
-            <includes>
-                <include>**/*.sh</include>
-            </includes>
-            <fileMode>0755</fileMode>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/keycloak-server-overlay-${project.version}</directory>
-            <outputDirectory>keycloak</outputDirectory>
-            <excludes>
-                <exclude>standalone/configuration/standalone-keycloak.xml</exclude>
-            </excludes>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/keycloak-wf9-adapter-${project.version}</directory>
-            <outputDirectory>keycloak</outputDirectory>
-            <excludes>
-                <exclude>standalone/configuration/standalone-keycloak.xml</exclude>
-            </excludes>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/keycloak-docs-${project.version}</directory>
-            <outputDirectory>docs</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>${project.build.directory}/unpacked/keycloak-examples-${project.version}</directory>
-            <outputDirectory>examples</outputDirectory>
-        </fileSet>
-    </fileSets>
-    <files>
-        <file>
-            <source>${project.build.directory}/unpacked/standalone.xml</source>
-            <outputDirectory>keycloak/standalone/configuration</outputDirectory>
-        </file>
-    </files>
-
-</assembly>
+<assembly>
+    <id>demo-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/wildfly-${wildfly.version}</directory>
+            <outputDirectory>keycloak</outputDirectory>
+            <excludes>
+                <exclude>**/*.sh</exclude>
+                <exclude>**/standalone.xml</exclude>
+            </excludes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/wildfly-${wildfly.version}</directory>
+            <outputDirectory>keycloak</outputDirectory>
+            <includes>
+                <include>**/*.sh</include>
+            </includes>
+            <fileMode>0755</fileMode>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/keycloak-server-overlay-${project.version}</directory>
+            <outputDirectory>keycloak</outputDirectory>
+            <excludes>
+                <exclude>standalone/configuration/standalone-keycloak.xml</exclude>
+            </excludes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/keycloak-wf9-adapter-${project.version}</directory>
+            <outputDirectory>keycloak</outputDirectory>
+            <excludes>
+                <exclude>standalone/configuration/standalone-keycloak.xml</exclude>
+            </excludes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/keycloak-docs-${project.version}</directory>
+            <outputDirectory>docs</outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/unpacked/keycloak-examples-${project.version}</directory>
+            <outputDirectory>examples</outputDirectory>
+        </fileSet>
+    </fileSets>
+    <files>
+        <file>
+            <source>${project.build.directory}/unpacked/standalone.xml</source>
+            <outputDirectory>keycloak/standalone/configuration</outputDirectory>
+        </file>
+    </files>
+
+</assembly>
diff --git a/distribution/demo-dist/pom.xml b/distribution/demo-dist/pom.xml
index 67f426e..3269d1e 100755
--- a/distribution/demo-dist/pom.xml
+++ b/distribution/demo-dist/pom.xml
@@ -1,191 +1,191 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-demo-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Demo Distribution</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-server-overlay</artifactId>
-            <type>zip</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-wf9-adapter-dist</artifactId>
-            <type>zip</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-examples-dist</artifactId>
-            <type>zip</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-docs-dist</artifactId>
-            <type>zip</type>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>keycloak-demo-${project.version}</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>unpack-wildfly</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.wildfly</groupId>
-                                    <artifactId>wildfly-dist</artifactId>
-                                    <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>unpack-server</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-server-overlay</artifactId>
-                                    <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-server-overlay-${project.version}</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>unpack-adapter</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-wf9-adapter-dist</artifactId>
-                                    <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-wf9-adapter-${project.version}</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>unpack-docs</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-docs-dist</artifactId>
-                                    <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>unpack-examples</id>
-                        <phase>prepare-package</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-examples-dist</artifactId>
-                                    <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>xml-maven-plugin</artifactId>
-                <version>1.0</version>
-                <executions>
-                    <execution>
-                        <id>generate-resources</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>transform</goal>
-                        </goals>
-                        <configuration>
-                            <transformationSets>
-                                <transformationSet>
-                                    <dir>${project.build.directory}/unpacked/wildfly-${wildfly.version}/standalone/configuration</dir>
-                                    <stylesheet>src/main/xslt/standalone.xsl</stylesheet>
-                                    <includes>
-                                        <include>standalone.xml</include>
-                                    </includes>
-                                    <outputDir>${project.build.directory}/unpacked/</outputDir>
-                                </transformationSet>
-                            </transformationSets>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>target</outputDirectory>
-                            <workDirectory>target/assembly/work</workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                            <tarLongFileMode>gnu</tarLongFileMode>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-demo-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Demo Distribution</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-server-overlay</artifactId>
+            <type>zip</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-wf9-adapter-dist</artifactId>
+            <type>zip</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-examples-dist</artifactId>
+            <type>zip</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-docs-dist</artifactId>
+            <type>zip</type>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>keycloak-demo-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack-wildfly</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.wildfly</groupId>
+                                    <artifactId>wildfly-dist</artifactId>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>unpack-server</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-server-overlay</artifactId>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-server-overlay-${project.version}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>unpack-adapter</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-wf9-adapter-dist</artifactId>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-wf9-adapter-${project.version}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>unpack-docs</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-docs-dist</artifactId>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>unpack-examples</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-examples-dist</artifactId>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>xml-maven-plugin</artifactId>
+                <version>1.0</version>
+                <executions>
+                    <execution>
+                        <id>generate-resources</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>transform</goal>
+                        </goals>
+                        <configuration>
+                            <transformationSets>
+                                <transformationSet>
+                                    <dir>${project.build.directory}/unpacked/wildfly-${wildfly.version}/standalone/configuration</dir>
+                                    <stylesheet>src/main/xslt/standalone.xsl</stylesheet>
+                                    <includes>
+                                        <include>standalone.xml</include>
+                                    </includes>
+                                    <outputDir>${project.build.directory}/unpacked/</outputDir>
+                                </transformationSet>
+                            </transformationSets>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>target</outputDirectory>
+                            <workDirectory>target/assembly/work</workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                            <tarLongFileMode>gnu</tarLongFileMode>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/docs-dist/assembly.xml b/distribution/docs-dist/assembly.xml
index dbdfb3a..879e92c 100755
--- a/distribution/docs-dist/assembly.xml
+++ b/distribution/docs-dist/assembly.xml
@@ -1,32 +1,32 @@
-<assembly>
-    <id>docs-dist</id>
-
-    <formats>
-        <format>zip</format>
-    </formats>
-
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>../../target/site/apidocs</directory>
-            <outputDirectory>javadocs</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>../../services/target/apidocs</directory>
-            <outputDirectory>rest-api</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>../../docbook/target/docbook/publish/en-US</directory>
-            <outputDirectory>userguide</outputDirectory>
-        </fileSet>
-    </fileSets>
-
-    <files>
-        <file>
-            <source>src/index.html</source>
-            <outputDirectory></outputDirectory>
-        </file>
-    </files>
-
-</assembly>
+<assembly>
+    <id>docs-dist</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>../../target/site/apidocs</directory>
+            <outputDirectory>javadocs</outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>../../services/target/apidocs</directory>
+            <outputDirectory>rest-api</outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>../../docbook/target/docbook/publish/en-US</directory>
+            <outputDirectory>userguide</outputDirectory>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            <source>src/index.html</source>
+            <outputDirectory></outputDirectory>
+        </file>
+    </files>
+
+</assembly>
diff --git a/distribution/docs-dist/build.xml b/distribution/docs-dist/build.xml
index 96fce23..3f8d82c 100755
--- a/distribution/docs-dist/build.xml
+++ b/distribution/docs-dist/build.xml
@@ -1,122 +1,122 @@
-<project name="example-dist" basedir="." default="all">
-
-    <target name="all">
-        <delete dir="target/examples"/>
-        <copy todir="target/examples/cors" overwrite="true">
-            <fileset dir="../../examples/cors">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/cordova" overwrite="true">
-            <fileset dir="../../examples/cordova">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/providers" overwrite="true">
-            <fileset dir="../../examples/providers">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/saml" overwrite="true">
-            <fileset dir="../../examples/saml">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/broker/saml-broker-authentication" overwrite="true">
-            <fileset dir="../../examples/broker/saml-broker-authentication">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/js-console" overwrite="true">
-            <fileset dir="../../examples/js-console">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/multi-tenant" overwrite="true">
-            <fileset dir="../../examples/multi-tenant">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/basic-auth" overwrite="true">
-            <fileset dir="../../examples/basic-auth">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/admin-client" overwrite="true">
-            <fileset dir="../../examples/admin-client">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/themes" overwrite="true">
-            <fileset dir="../../examples/themes">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/preconfigured-demo" overwrite="true">
-            <fileset dir="../../examples/demo-template">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/unconfigured-demo" overwrite="true">
-            <fileset dir="../../examples/demo-template">
-                <exclude name="**/*.wildfly"/>
-                <exclude name="**/*.as7"/>
-                <exclude name="**/WEB-INF/jboss-web.xml"/>
-                <exclude name="**/keycloak.json"/>
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/README.md"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/fuse" overwrite="true">
-            <fileset dir="../../examples/fuse">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/kerberos" overwrite="true">
-            <fileset dir="../../examples/kerberos">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-            </fileset>
-        </copy>
-        <copy file="../../examples/README.md" tofile="target/examples/README.md"/>
-        <move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
-        <move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
-        <move file="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml"/>
-        <move file="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml"/>
-    </target>
-</project>
+<project name="example-dist" basedir="." default="all">
+
+    <target name="all">
+        <delete dir="target/examples"/>
+        <copy todir="target/examples/cors" overwrite="true">
+            <fileset dir="../../examples/cors">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/cordova" overwrite="true">
+            <fileset dir="../../examples/cordova">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/providers" overwrite="true">
+            <fileset dir="../../examples/providers">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/saml" overwrite="true">
+            <fileset dir="../../examples/saml">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/broker/saml-broker-authentication" overwrite="true">
+            <fileset dir="../../examples/broker/saml-broker-authentication">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/js-console" overwrite="true">
+            <fileset dir="../../examples/js-console">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/multi-tenant" overwrite="true">
+            <fileset dir="../../examples/multi-tenant">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/basic-auth" overwrite="true">
+            <fileset dir="../../examples/basic-auth">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/admin-client" overwrite="true">
+            <fileset dir="../../examples/admin-client">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/themes" overwrite="true">
+            <fileset dir="../../examples/themes">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/preconfigured-demo" overwrite="true">
+            <fileset dir="../../examples/demo-template">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/unconfigured-demo" overwrite="true">
+            <fileset dir="../../examples/demo-template">
+                <exclude name="**/*.wildfly"/>
+                <exclude name="**/*.as7"/>
+                <exclude name="**/WEB-INF/jboss-web.xml"/>
+                <exclude name="**/keycloak.json"/>
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/README.md"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/fuse" overwrite="true">
+            <fileset dir="../../examples/fuse">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/kerberos" overwrite="true">
+            <fileset dir="../../examples/kerberos">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+            </fileset>
+        </copy>
+        <copy file="../../examples/README.md" tofile="target/examples/README.md"/>
+        <move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
+        <move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
+        <move file="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml"/>
+        <move file="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml"/>
+    </target>
+</project>
diff --git a/distribution/docs-dist/pom.xml b/distribution/docs-dist/pom.xml
index 4cf67a5..d8edc33 100755
--- a/distribution/docs-dist/pom.xml
+++ b/distribution/docs-dist/pom.xml
@@ -1,55 +1,55 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-docs-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Docs Distribution</name>
-    <description/>
-
-    <dependencies>
-    </dependencies>
-    <build>
-        <finalName>keycloak-docs-${project.version}</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-docs-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Docs Distribution</name>
+    <description/>
+
+    <dependencies>
+    </dependencies>
+    <build>
+        <finalName>keycloak-docs-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/docs-dist/src/index.html b/distribution/docs-dist/src/index.html
index b43299a..891f778 100755
--- a/distribution/docs-dist/src/index.html
+++ b/distribution/docs-dist/src/index.html
@@ -1,8 +1,8 @@
-<h1>Keyloak Documentation</h1>
-<ul>
-    <li><a href="userguide/html/index.html">Userguide HTML</a></li>
-    <li><a href="userguide/html_single/index.html">Userguide HTML Single Page</a></li>
-    <li><a href="userguide/pdf/keycloak-reference-guide-en-US.pdf">Userguide PDF</a></li>
-    <li><a href="rest-api/overview-index.html">Admin REST API</a></li>
-    <li><a href="javadocs/index.html">Javadocs</a></li>
+<h1>Keyloak Documentation</h1>
+<ul>
+    <li><a href="userguide/html/index.html">Userguide HTML</a></li>
+    <li><a href="userguide/html_single/index.html">Userguide HTML Single Page</a></li>
+    <li><a href="userguide/pdf/keycloak-reference-guide-en-US.pdf">Userguide PDF</a></li>
+    <li><a href="rest-api/overview-index.html">Admin REST API</a></li>
+    <li><a href="javadocs/index.html">Javadocs</a></li>
 </ul>
\ No newline at end of file
diff --git a/distribution/examples-dist/assembly.xml b/distribution/examples-dist/assembly.xml
index 2d249b1..d3b249c 100755
--- a/distribution/examples-dist/assembly.xml
+++ b/distribution/examples-dist/assembly.xml
@@ -1,21 +1,21 @@
-<assembly>
-    <id>examples</id>
-
-    <formats>
-        <format>zip</format>
-    </formats>
-
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>target/examples</directory>
-            <outputDirectory></outputDirectory>
-            <excludes>
-                <exclude>**/.svn/**</exclude>
-                <exclude>**/target/**</exclude>
-                <exclude>**/*.iml</exclude>
-            </excludes>
-        </fileSet>
-    </fileSets>
-</assembly>
+<assembly>
+    <id>examples</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target/examples</directory>
+            <outputDirectory></outputDirectory>
+            <excludes>
+                <exclude>**/.svn/**</exclude>
+                <exclude>**/target/**</exclude>
+                <exclude>**/*.iml</exclude>
+            </excludes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/distribution/examples-dist/build.xml b/distribution/examples-dist/build.xml
index dd2b86f..35ccd42 100755
--- a/distribution/examples-dist/build.xml
+++ b/distribution/examples-dist/build.xml
@@ -1,129 +1,129 @@
-<project name="example-dist" basedir="." default="all">
-
-    <target name="all">
-        <delete dir="target/examples"/>
-        <copy todir="target/examples/cors" overwrite="true">
-            <fileset dir="../../examples/cors">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/cordova" overwrite="true">
-            <fileset dir="../../examples/cordova">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/providers" overwrite="true">
-            <fileset dir="../../examples/providers">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/saml" overwrite="true">
-            <fileset dir="../../examples/saml">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/broker/saml-broker-authentication" overwrite="true">
-            <fileset dir="../../examples/broker/saml-broker-authentication">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/js-console" overwrite="true">
-            <fileset dir="../../examples/js-console">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/multi-tenant" overwrite="true">
-            <fileset dir="../../examples/multi-tenant">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/basic-auth" overwrite="true">
-            <fileset dir="../../examples/basic-auth">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/admin-client" overwrite="true">
-            <fileset dir="../../examples/admin-client">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/themes" overwrite="true">
-            <fileset dir="../../examples/themes">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/preconfigured-demo" overwrite="true">
-            <fileset dir="../../examples/demo-template">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/*.unconfigured"/>
-                <exclude name="**/subsystem-config.xml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/unconfigured-demo" overwrite="true">
-            <fileset dir="../../examples/demo-template">
-                <exclude name="**/*.wildfly"/>
-                <exclude name="**/*.as7"/>
-                <exclude name="**/WEB-INF/jboss-web.xml"/>
-                <exclude name="**/keycloak.json"/>
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-                <exclude name="**/README.md"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/fuse" overwrite="true">
-            <fileset dir="../../examples/fuse">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/ldap" overwrite="true">
-            <fileset dir="../../examples/ldap">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-            </fileset>
-        </copy>
-        <copy todir="target/examples/kerberos" overwrite="true">
-            <fileset dir="../../examples/kerberos">
-                <exclude name="**/target/**"/>
-                <exclude name="**/*.iml"/>
-            </fileset>
-        </copy>
-        <copy file="../../examples/pom.xml" tofile="target/examples/pom.xml"/>
-        <copy file="../../examples/README.md" tofile="target/examples/README.md"/>
-        <move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
-        <move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
-        <move file="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml"/>
-        <move file="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml"/>
-    </target>
-</project>
+<project name="example-dist" basedir="." default="all">
+
+    <target name="all">
+        <delete dir="target/examples"/>
+        <copy todir="target/examples/cors" overwrite="true">
+            <fileset dir="../../examples/cors">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/cordova" overwrite="true">
+            <fileset dir="../../examples/cordova">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/providers" overwrite="true">
+            <fileset dir="../../examples/providers">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/saml" overwrite="true">
+            <fileset dir="../../examples/saml">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/broker/saml-broker-authentication" overwrite="true">
+            <fileset dir="../../examples/broker/saml-broker-authentication">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/js-console" overwrite="true">
+            <fileset dir="../../examples/js-console">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/multi-tenant" overwrite="true">
+            <fileset dir="../../examples/multi-tenant">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/basic-auth" overwrite="true">
+            <fileset dir="../../examples/basic-auth">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/admin-client" overwrite="true">
+            <fileset dir="../../examples/admin-client">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/themes" overwrite="true">
+            <fileset dir="../../examples/themes">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/preconfigured-demo" overwrite="true">
+            <fileset dir="../../examples/demo-template">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/unconfigured-demo" overwrite="true">
+            <fileset dir="../../examples/demo-template">
+                <exclude name="**/*.wildfly"/>
+                <exclude name="**/*.as7"/>
+                <exclude name="**/WEB-INF/jboss-web.xml"/>
+                <exclude name="**/keycloak.json"/>
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/README.md"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/fuse" overwrite="true">
+            <fileset dir="../../examples/fuse">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/ldap" overwrite="true">
+            <fileset dir="../../examples/ldap">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+            </fileset>
+        </copy>
+        <copy todir="target/examples/kerberos" overwrite="true">
+            <fileset dir="../../examples/kerberos">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+            </fileset>
+        </copy>
+        <copy file="../../examples/pom.xml" tofile="target/examples/pom.xml"/>
+        <copy file="../../examples/README.md" tofile="target/examples/README.md"/>
+        <move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
+        <move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
+        <move file="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml"/>
+        <move file="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml"/>
+    </target>
+</project>
diff --git a/distribution/examples-dist/pom.xml b/distribution/examples-dist/pom.xml
index ae8dd06..4f988f5 100755
--- a/distribution/examples-dist/pom.xml
+++ b/distribution/examples-dist/pom.xml
@@ -1,89 +1,89 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-examples-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Examples Distribution</name>
-    <description/>
-
-    <dependencies>
-    </dependencies>
-    <build>
-        <finalName>keycloak-examples-${project.version}</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-antrun-plugin</artifactId>
-                <inherited>false</inherited>
-                <executions>
-                    <execution>
-                        <id>build-example</id>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                        <phase>compile</phase>
-                        <configuration>
-                            <target>
-                                <ant antfile="build.xml" inheritRefs="true">
-                                    <target name="all"/>
-                                </ant>
-                            </target>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>ant-contrib</groupId>
-                        <artifactId>ant-contrib</artifactId>
-                        <version>1.0b3</version>
-                        <exclusions>
-                            <exclusion>
-                                <groupId>ant</groupId>
-                                <artifactId>ant</artifactId>
-                            </exclusion>
-                        </exclusions>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-examples-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Examples Distribution</name>
+    <description/>
+
+    <dependencies>
+    </dependencies>
+    <build>
+        <finalName>keycloak-examples-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <inherited>false</inherited>
+                <executions>
+                    <execution>
+                        <id>build-example</id>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <target>
+                                <ant antfile="build.xml" inheritRefs="true">
+                                    <target name="all"/>
+                                </ant>
+                            </target>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>ant-contrib</groupId>
+                        <artifactId>ant-contrib</artifactId>
+                        <version>1.0b3</version>
+                        <exclusions>
+                            <exclusion>
+                                <groupId>ant</groupId>
+                                <artifactId>ant</artifactId>
+                            </exclusion>
+                        </exclusions>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

distribution/pom.xml 56(+28 -28)

diff --git a/distribution/pom.xml b/distribution/pom.xml
index 979f5d6..7cb853d 100755
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -1,28 +1,28 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <name>Distribution Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>distribution-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>adapters</module>
-        <module>demo-dist</module>
-        <module>docs-dist</module>
-        <module>examples-dist</module>
-        <module>proxy-dist</module>
-        <module>server-dist</module>
-        <module>server-overlay</module>
-        <module>src-dist</module>
-        <module>feature-packs</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <name>Distribution Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>distribution-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>adapters</module>
+        <module>demo-dist</module>
+        <module>docs-dist</module>
+        <module>examples-dist</module>
+        <module>proxy-dist</module>
+        <module>server-dist</module>
+        <module>server-overlay</module>
+        <module>src-dist</module>
+        <module>feature-packs</module>
+    </modules>
+</project>
diff --git a/distribution/proxy-dist/assembly.xml b/distribution/proxy-dist/assembly.xml
index 89ba584..e864e5f 100755
--- a/distribution/proxy-dist/assembly.xml
+++ b/distribution/proxy-dist/assembly.xml
@@ -1,41 +1,41 @@
-<assembly>
-    <id>proxy-dist</id>
-
-    <formats>
-        <format>zip</format>
-    </formats>
-
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>../../</directory>
-            <includes>
-                <include>License.html</include>
-            </includes>
-            <outputDirectory></outputDirectory>
-        </fileSet>
-    </fileSets>
-
-    <dependencySets>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:launcher</include>
-            </includes>
-            <outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>
-            <outputDirectory>bin</outputDirectory>
-        </dependencySet>
-        <dependencySet>
-            <unpack>false</unpack>
-            <useTransitiveDependencies>true</useTransitiveDependencies>
-            <useTransitiveFiltering>true</useTransitiveFiltering>
-            <includes>
-                <include>org.keycloak:keycloak-proxy-server</include>
-            </includes>
-            <outputDirectory>lib</outputDirectory>
-        </dependencySet>
-    </dependencySets>
-</assembly>
+<assembly>
+    <id>proxy-dist</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>../../</directory>
+            <includes>
+                <include>License.html</include>
+            </includes>
+            <outputDirectory></outputDirectory>
+        </fileSet>
+    </fileSets>
+
+    <dependencySets>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:launcher</include>
+            </includes>
+            <outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>
+            <outputDirectory>bin</outputDirectory>
+        </dependencySet>
+        <dependencySet>
+            <unpack>false</unpack>
+            <useTransitiveDependencies>true</useTransitiveDependencies>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>org.keycloak:keycloak-proxy-server</include>
+            </includes>
+            <outputDirectory>lib</outputDirectory>
+        </dependencySet>
+    </dependencySets>
+</assembly>
diff --git a/distribution/proxy-dist/pom.xml b/distribution/proxy-dist/pom.xml
index 4aa5555..d020f96 100755
--- a/distribution/proxy-dist/pom.xml
+++ b/distribution/proxy-dist/pom.xml
@@ -1,57 +1,57 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-proxy-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Proxy Distro</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>launcher</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-proxy-server</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>keycloak-proxy-${project.version}</finalName>
-        <plugins>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-proxy-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Proxy Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>launcher</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-proxy-server</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>keycloak-proxy-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/server-dist/assembly.xml b/distribution/server-dist/assembly.xml
index 6a846af..05de7d9 100755
--- a/distribution/server-dist/assembly.xml
+++ b/distribution/server-dist/assembly.xml
@@ -1,41 +1,41 @@
-<assembly>
-    <id>server-dist</id>
-
-    <formats>
-        <format>zip</format>
-        <format>tar.gz</format>
-    </formats>
-
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <fileSets>
-        <fileSet>
-            <directory>target/${project.build.finalName}</directory>
-            <outputDirectory/>
-            <filtered>true</filtered>
-            <includes>
-                <include>**/module.xml</include>
-            </includes>
-        </fileSet>
-        <fileSet>
-            <directory>target/${project.build.finalName}</directory>
-            <outputDirectory/>
-            <filtered>false</filtered>
-            <excludes>
-                <exclude>**/module.xml</exclude>
-                <exclude>welcome-content/**</exclude>
-                <exclude>appclient</exclude>
-                <exclude>appclient/*</exclude>
-                <exclude>standalone/deployments</exclude>
-                <exclude>standalone/deployments/*</exclude>
-            </excludes>
-        </fileSet>
-        <fileSet>
-            <directory>src/main/welcome-content</directory>
-            <outputDirectory>welcome-content</outputDirectory>
-            <includes>
-                <include>*.*</include>
-            </includes>
-        </fileSet>
-    </fileSets>
-</assembly>
+<assembly>
+    <id>server-dist</id>
+
+    <formats>
+        <format>zip</format>
+        <format>tar.gz</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target/${project.build.finalName}</directory>
+            <outputDirectory/>
+            <filtered>true</filtered>
+            <includes>
+                <include>**/module.xml</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/${project.build.finalName}</directory>
+            <outputDirectory/>
+            <filtered>false</filtered>
+            <excludes>
+                <exclude>**/module.xml</exclude>
+                <exclude>welcome-content/**</exclude>
+                <exclude>appclient</exclude>
+                <exclude>appclient/*</exclude>
+                <exclude>standalone/deployments</exclude>
+                <exclude>standalone/deployments/*</exclude>
+            </excludes>
+        </fileSet>
+        <fileSet>
+            <directory>src/main/welcome-content</directory>
+            <outputDirectory>welcome-content</outputDirectory>
+            <includes>
+                <include>*.*</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/distribution/server-dist/pom.xml b/distribution/server-dist/pom.xml
index be3ab5b..2f54d92 100755
--- a/distribution/server-dist/pom.xml
+++ b/distribution/server-dist/pom.xml
@@ -1,71 +1,71 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-server-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Server Distribution</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-server-feature-pack</artifactId>
-            <type>zip</type>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>keycloak-${project.version}</finalName>
-
-        <plugins>
-            <plugin>
-                <groupId>org.wildfly.build</groupId>
-                <artifactId>wildfly-server-provisioning-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>server-provisioning</id>
-                        <goals>
-                            <goal>build</goal>
-                        </goals>
-                        <phase>compile</phase>
-                        <configuration>
-                            <config-file>server-provisioning.xml</config-file>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <recompressZippedFiles>true</recompressZippedFiles>
-                            <finalName>${project.build.finalName}</finalName>
-                            <appendAssemblyId>false</appendAssemblyId>
-                            <outputDirectory>${project.build.directory}</outputDirectory>
-                            <workDirectory>${project.build.directory}/assembly/work</workDirectory>
-                            <tarLongFileMode>gnu</tarLongFileMode>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-server-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Server Distribution</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-server-feature-pack</artifactId>
+            <type>zip</type>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>keycloak-${project.version}</finalName>
+
+        <plugins>
+            <plugin>
+                <groupId>org.wildfly.build</groupId>
+                <artifactId>wildfly-server-provisioning-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>server-provisioning</id>
+                        <goals>
+                            <goal>build</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <config-file>server-provisioning.xml</config-file>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <recompressZippedFiles>true</recompressZippedFiles>
+                            <finalName>${project.build.finalName}</finalName>
+                            <appendAssemblyId>false</appendAssemblyId>
+                            <outputDirectory>${project.build.directory}</outputDirectory>
+                            <workDirectory>${project.build.directory}/assembly/work</workDirectory>
+                            <tarLongFileMode>gnu</tarLongFileMode>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/distribution/src-dist/pom.xml b/distribution/src-dist/pom.xml
index 028d156..b0890b2 100755
--- a/distribution/src-dist/pom.xml
+++ b/distribution/src-dist/pom.xml
@@ -1,53 +1,53 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-src-dist</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak Source Distribution</name>
-    <description/>
-
-    <build>
-        <finalName>keycloak-src-${project.version}</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>assemble</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <descriptors>
-                                <descriptor>assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>
-                                target
-                            </outputDirectory>
-                            <workDirectory>
-                                target/assembly/work
-                            </workDirectory>
-                            <appendAssemblyId>false</appendAssemblyId>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-src-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Source Distribution</name>
+    <description/>
+
+    <build>
+        <finalName>keycloak-src-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>
+                                target
+                            </outputDirectory>
+                            <workDirectory>
+                                target/assembly/work
+                            </workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

docbook/pom.xml 268(+134 -134)

diff --git a/docbook/pom.xml b/docbook/pom.xml
index f97e203..02c837e 100755
--- a/docbook/pom.xml
+++ b/docbook/pom.xml
@@ -1,134 +1,134 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>keycloak-reference-guide-${translation}</artifactId>
-    <packaging>jdocbook</packaging>
-    <name>Keycloak Reference Guide (${translation})</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-        <!--
-       <repository>
-           <id>repo1.maven.org</id>
-           <url>http://repo1.maven.org/maven2</url>
-       </repository> -->
-    </repositories>
-    <pluginRepositories>
-        <pluginRepository>
-            <id>jboss</id>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </pluginRepository>
-        <!--
-        <pluginRepository>
-            <id>maven2-repository.dev.java.net</id>
-            <url>http://download.java.net/maven/2</url>
-        </pluginRepository>
-        <pluginRepository>
-            <id>plugin repo1.maven.org</id>
-            <url>http://repo1.maven.org/maven2</url>
-        </pluginRepository>
-        -->
-    </pluginRepositories>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.jboss.maven.plugins</groupId>
-                <artifactId>maven-jdocbook-plugin</artifactId>
-                <version>2.3.8</version>
-                <extensions>true</extensions>
-
-                <dependencies>
-                    <dependency>
-                        <groupId>org.jboss.pressgang</groupId>
-                        <artifactId>pressgang-xslt-ns</artifactId>
-                        <version>2.0.2</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.jboss.pressgang</groupId>
-                        <artifactId>pressgang-jdocbook-style</artifactId>
-                        <type>jdocbook-style</type>
-                        <version>2.0.2</version>
-                    </dependency>
-                </dependencies>
-
-                <configuration>
-                    <sourceDocumentName>master.xml</sourceDocumentName>
-                    <masterTranslation>en-US</masterTranslation>
-                    <sourceDirectory>${project.basedir}/reference/en</sourceDirectory>
-                    <imageResource>
-                        <directory>${project.basedir}/reference/en</directory>
-                        <includes>
-                            <include>images/*</include>
-                        </includes>
-                    </imageResource>
-                    <formats>
-                        <format>
-                            <formatName>html_single</formatName>
-                            <stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
-                            <finalName>index.html</finalName>
-                            <!-- <profilingTypeName>two_pass</profilingTypeName> -->
-                        </format>
-                        <format>
-                            <formatName>html</formatName>
-                            <stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
-                            <finalName>index.html</finalName>
-                            <!-- <profilingTypeName>two_pass</profilingTypeName> -->
-                        </format>
-                        <format>
-                            <formatName>pdf</formatName>
-                            <stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
-                            <finalName>${project.artifactId}.pdf</finalName>
-                        </format>
-                        <!--<format>-->
-                        <!--<formatName>eclipse</formatName>-->
-                        <!--<stylesheetResource>classpath:/xslt/org/jboss/eclipse.xsl</stylesheetResource>-->
-                        <!--<finalName>${project.artifactId}.html</finalName>-->
-                        <!--</format>-->
-                    </formats>
-                    <injections>
-                        <injection>
-                            <name>project.version</name>
-                            <value>${project.version}</value>
-                        </injection>
-                        <injection>
-                            <name>picketlink.version</name>
-                            <value>${picketlink.version}</value>
-                        </injection>
-                    </injections>
-                    <options>
-                        <xmlTransformerType>saxon</xmlTransformerType>
-                        <xincludeSupported>true</xincludeSupported>
-                        <useRelativeImageUris>true</useRelativeImageUris>
-                        <!-- TODO Probably obsolete after the upgrade to maven-jdocbook-plugin 2.3.0 -->
-                        <docbookVersion>1.72.0</docbookVersion>
-                        <!-- <localeSeparator>-</localeSeparator> -->
-                    </options>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <properties>
-        <translation>en-US</translation>
-    </properties>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-reference-guide-${translation}</artifactId>
+    <packaging>jdocbook</packaging>
+    <name>Keycloak Reference Guide (${translation})</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+        <!--
+       <repository>
+           <id>repo1.maven.org</id>
+           <url>http://repo1.maven.org/maven2</url>
+       </repository> -->
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>jboss</id>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </pluginRepository>
+        <!--
+        <pluginRepository>
+            <id>maven2-repository.dev.java.net</id>
+            <url>http://download.java.net/maven/2</url>
+        </pluginRepository>
+        <pluginRepository>
+            <id>plugin repo1.maven.org</id>
+            <url>http://repo1.maven.org/maven2</url>
+        </pluginRepository>
+        -->
+    </pluginRepositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.jboss.maven.plugins</groupId>
+                <artifactId>maven-jdocbook-plugin</artifactId>
+                <version>2.3.8</version>
+                <extensions>true</extensions>
+
+                <dependencies>
+                    <dependency>
+                        <groupId>org.jboss.pressgang</groupId>
+                        <artifactId>pressgang-xslt-ns</artifactId>
+                        <version>2.0.2</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.jboss.pressgang</groupId>
+                        <artifactId>pressgang-jdocbook-style</artifactId>
+                        <type>jdocbook-style</type>
+                        <version>2.0.2</version>
+                    </dependency>
+                </dependencies>
+
+                <configuration>
+                    <sourceDocumentName>master.xml</sourceDocumentName>
+                    <masterTranslation>en-US</masterTranslation>
+                    <sourceDirectory>${project.basedir}/reference/en</sourceDirectory>
+                    <imageResource>
+                        <directory>${project.basedir}/reference/en</directory>
+                        <includes>
+                            <include>images/*</include>
+                        </includes>
+                    </imageResource>
+                    <formats>
+                        <format>
+                            <formatName>html_single</formatName>
+                            <stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
+                            <finalName>index.html</finalName>
+                            <!-- <profilingTypeName>two_pass</profilingTypeName> -->
+                        </format>
+                        <format>
+                            <formatName>html</formatName>
+                            <stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
+                            <finalName>index.html</finalName>
+                            <!-- <profilingTypeName>two_pass</profilingTypeName> -->
+                        </format>
+                        <format>
+                            <formatName>pdf</formatName>
+                            <stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
+                            <finalName>${project.artifactId}.pdf</finalName>
+                        </format>
+                        <!--<format>-->
+                        <!--<formatName>eclipse</formatName>-->
+                        <!--<stylesheetResource>classpath:/xslt/org/jboss/eclipse.xsl</stylesheetResource>-->
+                        <!--<finalName>${project.artifactId}.html</finalName>-->
+                        <!--</format>-->
+                    </formats>
+                    <injections>
+                        <injection>
+                            <name>project.version</name>
+                            <value>${project.version}</value>
+                        </injection>
+                        <injection>
+                            <name>picketlink.version</name>
+                            <value>${picketlink.version}</value>
+                        </injection>
+                    </injections>
+                    <options>
+                        <xmlTransformerType>saxon</xmlTransformerType>
+                        <xincludeSupported>true</xincludeSupported>
+                        <useRelativeImageUris>true</useRelativeImageUris>
+                        <!-- TODO Probably obsolete after the upgrade to maven-jdocbook-plugin 2.3.0 -->
+                        <docbookVersion>1.72.0</docbookVersion>
+                        <!-- <localeSeparator>-</localeSeparator> -->
+                    </options>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <translation>en-US</translation>
+    </properties>
+</project>
diff --git a/docbook/reference/en/en-US/master.xml b/docbook/reference/en/en-US/master.xml
index 59b2be1..fe6ee0c 100755
--- a/docbook/reference/en/en-US/master.xml
+++ b/docbook/reference/en/en-US/master.xml
@@ -1,145 +1,145 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
-                         "http://www.docbook.org/xml/4.4/docbookx.dtd"
-        [
-                <!ENTITY License SYSTEM "modules/License.xml">
-                <!ENTITY Overview SYSTEM "modules/Overview.xml">
-                <!ENTITY Installation SYSTEM "modules/server-installation.xml">
-                <!ENTITY Providers SYSTEM "modules/providers.xml">
-                <!ENTITY OpenShift SYSTEM "modules/openshift.xml">
-                <!ENTITY AdminPermissions SYSTEM "modules/admin-permissions.xml">
-                <!ENTITY PerRealmAdminPermissions SYSTEM "modules/per-realm-admin-permissions.xml">
-                <!ENTITY AccessTypes SYSTEM "modules/access-types.xml">
-                <!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
-                <!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
-                <!ENTITY JavascriptAdapter SYSTEM "modules/javascript-adapter.xml">
-                <!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
-                <!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
-                <!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
-                <!ENTITY FuseAdapter SYSTEM "modules/fuse-adapter.xml">
-                <!ENTITY SpringBootAdapter SYSTEM "modules/spring-boot-adapter.xml">
-                <!ENTITY SpringSecurityAdapter SYSTEM "modules/spring-security-adapter.xml">
-                <!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
-                <!ENTITY Logout SYSTEM "modules/logout.xml">
-                <!ENTITY SAML SYSTEM "modules/saml.xml">
-                <!ENTITY JAAS SYSTEM "modules/jaas.xml">
-                <!ENTITY IdentityBroker SYSTEM "modules/identity-broker.xml">
-                <!ENTITY Themes SYSTEM "modules/themes.xml">
-                <!ENTITY Migration SYSTEM "modules/MigrationFromOlderVersions.xml">
-                <!ENTITY Email SYSTEM "modules/email.xml">
-                <!ENTITY Roles SYSTEM "modules/roles.xml">
-                <!ENTITY DirectAccess SYSTEM "modules/direct-access.xml">
-                <!ENTITY CORS SYSTEM "modules/cors.xml">
-                <!ENTITY Timeouts SYSTEM "modules/timeouts.xml">
-                <!ENTITY Events SYSTEM "modules/events.xml">
-                <!ENTITY AdminApi SYSTEM "modules/admin-rest-api.xml">
-                <!ENTITY UserFederation SYSTEM "modules/user-federation.xml">
-                <!ENTITY Kerberos SYSTEM "modules/kerberos.xml">
-                <!ENTITY ExportImport SYSTEM "modules/export-import.xml">
-                <!ENTITY AdminRecovery SYSTEM "modules/admin-recovery.xml">
-                <!ENTITY ServerCache SYSTEM "modules/cache.xml">
-                <!ENTITY SecurityVulnerabilities SYSTEM "modules/security-vulnerabilities.xml">
-                <!ENTITY Clustering SYSTEM "modules/clustering.xml">
-                <!ENTITY ApplicationClustering SYSTEM "modules/application-clustering.xml">
-                <!ENTITY MultiTenancy SYSTEM "modules/multi-tenancy.xml">
-                <!ENTITY Proxy SYSTEM "modules/proxy.xml">
-                <!ENTITY CustomAttributes SYSTEM "modules/custom-attributes.xml">
-                <!ENTITY ProtocolMappers SYSTEM "modules/protocol-mappers.xml">
-                <!ENTITY Recaptcha SYSTEM "modules/recaptcha.xml">
-                ]>
-
-<book>
-
-   <bookinfo>
-      <title>Keycloak Reference Guide</title>
-      <subtitle>SSO for Web Apps and REST Services</subtitle>
-      <releaseinfo>&project.version;</releaseinfo>
-   </bookinfo>
-
-   <toc/>
-
-   <preface id="preface" revision="1">
-      <title>Preface</title>
-      <para>
-         In some of the example listings, what is meant to be displayed on one line does not fit
-         inside the available page width. These lines have been broken up. A '\' at the end of a
-         line means that a break has been introduced to fit in the page, with the following lines
-         indented. So:
-<programlisting>
-Let's pretend to have an extremely \
-long line that \
-does not fit
-This one is short
-</programlisting>
-         Is really:
-<programlisting>
-Let's pretend to have an extremely long line that does not fit
-This one is short
-</programlisting>
-      </para>
-   </preface>
-
-    &License;
-    &Overview;
-    &Installation;
-    &Providers;
-    &OpenShift;
-    &AdminPermissions;
-    &PerRealmAdminPermissions;
-    <chapter>
-        <title>Adapters</title>
-        <para>
-            Keycloak can secure a wide variety of application types. This section defines which application
-            types are supported and how to configure and install them so that you can use Keycloak to secure
-            your applications.
-        </para>
-        &AdapterConfig;
-        &JBossAdapter;
-        &TomcatAdapter;
-        &Jetty9Adapter;
-        &Jetty8Adapter;
-        &FuseAdapter;
-        &JavascriptAdapter;
-        &SpringBootAdapter;
-        &SpringSecurityAdapter;
-        &InstalledApplications;
-        &Logout;
-        &MultiTenancy;
-        &JAAS;
-    </chapter>
-
-    &IdentityBroker;
-    &Themes;
-    &Recaptcha;
-
-    <chapter>
-        <title>Email</title>
-        <para>
-            Keycloak sends emails to users to verify their email address. Emails are also used to allow users to
-            safely restore their username and passwords.
-        </para>
-        &Email;
-    </chapter>
-    &AccessTypes;
-    &Roles;
-    &DirectAccess;
-    &CORS;
-    &Timeouts;
-    &AdminApi;
-    &Events;
-    &UserFederation;
-    &Kerberos;
-    &ExportImport;
-    &AdminRecovery;
-    &ServerCache;
-    &SAML;
-    &SecurityVulnerabilities;
-    &Clustering;
-    &ApplicationClustering;
-    &Proxy;
-    &CustomAttributes;
-    &ProtocolMappers;
-    &Migration;
-
-</book>
-
-
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+                         "http://www.docbook.org/xml/4.4/docbookx.dtd"
+        [
+                <!ENTITY License SYSTEM "modules/License.xml">
+                <!ENTITY Overview SYSTEM "modules/Overview.xml">
+                <!ENTITY Installation SYSTEM "modules/server-installation.xml">
+                <!ENTITY Providers SYSTEM "modules/providers.xml">
+                <!ENTITY OpenShift SYSTEM "modules/openshift.xml">
+                <!ENTITY AdminPermissions SYSTEM "modules/admin-permissions.xml">
+                <!ENTITY PerRealmAdminPermissions SYSTEM "modules/per-realm-admin-permissions.xml">
+                <!ENTITY AccessTypes SYSTEM "modules/access-types.xml">
+                <!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
+                <!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
+                <!ENTITY JavascriptAdapter SYSTEM "modules/javascript-adapter.xml">
+                <!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
+                <!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
+                <!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
+                <!ENTITY FuseAdapter SYSTEM "modules/fuse-adapter.xml">
+                <!ENTITY SpringBootAdapter SYSTEM "modules/spring-boot-adapter.xml">
+                <!ENTITY SpringSecurityAdapter SYSTEM "modules/spring-security-adapter.xml">
+                <!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
+                <!ENTITY Logout SYSTEM "modules/logout.xml">
+                <!ENTITY SAML SYSTEM "modules/saml.xml">
+                <!ENTITY JAAS SYSTEM "modules/jaas.xml">
+                <!ENTITY IdentityBroker SYSTEM "modules/identity-broker.xml">
+                <!ENTITY Themes SYSTEM "modules/themes.xml">
+                <!ENTITY Migration SYSTEM "modules/MigrationFromOlderVersions.xml">
+                <!ENTITY Email SYSTEM "modules/email.xml">
+                <!ENTITY Roles SYSTEM "modules/roles.xml">
+                <!ENTITY DirectAccess SYSTEM "modules/direct-access.xml">
+                <!ENTITY CORS SYSTEM "modules/cors.xml">
+                <!ENTITY Timeouts SYSTEM "modules/timeouts.xml">
+                <!ENTITY Events SYSTEM "modules/events.xml">
+                <!ENTITY AdminApi SYSTEM "modules/admin-rest-api.xml">
+                <!ENTITY UserFederation SYSTEM "modules/user-federation.xml">
+                <!ENTITY Kerberos SYSTEM "modules/kerberos.xml">
+                <!ENTITY ExportImport SYSTEM "modules/export-import.xml">
+                <!ENTITY AdminRecovery SYSTEM "modules/admin-recovery.xml">
+                <!ENTITY ServerCache SYSTEM "modules/cache.xml">
+                <!ENTITY SecurityVulnerabilities SYSTEM "modules/security-vulnerabilities.xml">
+                <!ENTITY Clustering SYSTEM "modules/clustering.xml">
+                <!ENTITY ApplicationClustering SYSTEM "modules/application-clustering.xml">
+                <!ENTITY MultiTenancy SYSTEM "modules/multi-tenancy.xml">
+                <!ENTITY Proxy SYSTEM "modules/proxy.xml">
+                <!ENTITY CustomAttributes SYSTEM "modules/custom-attributes.xml">
+                <!ENTITY ProtocolMappers SYSTEM "modules/protocol-mappers.xml">
+                <!ENTITY Recaptcha SYSTEM "modules/recaptcha.xml">
+                ]>
+
+<book>
+
+   <bookinfo>
+      <title>Keycloak Reference Guide</title>
+      <subtitle>SSO for Web Apps and REST Services</subtitle>
+      <releaseinfo>&project.version;</releaseinfo>
+   </bookinfo>
+
+   <toc/>
+
+   <preface id="preface" revision="1">
+      <title>Preface</title>
+      <para>
+         In some of the example listings, what is meant to be displayed on one line does not fit
+         inside the available page width. These lines have been broken up. A '\' at the end of a
+         line means that a break has been introduced to fit in the page, with the following lines
+         indented. So:
+<programlisting>
+Let's pretend to have an extremely \
+long line that \
+does not fit
+This one is short
+</programlisting>
+         Is really:
+<programlisting>
+Let's pretend to have an extremely long line that does not fit
+This one is short
+</programlisting>
+      </para>
+   </preface>
+
+    &License;
+    &Overview;
+    &Installation;
+    &Providers;
+    &OpenShift;
+    &AdminPermissions;
+    &PerRealmAdminPermissions;
+    <chapter>
+        <title>Adapters</title>
+        <para>
+            Keycloak can secure a wide variety of application types. This section defines which application
+            types are supported and how to configure and install them so that you can use Keycloak to secure
+            your applications.
+        </para>
+        &AdapterConfig;
+        &JBossAdapter;
+        &TomcatAdapter;
+        &Jetty9Adapter;
+        &Jetty8Adapter;
+        &FuseAdapter;
+        &JavascriptAdapter;
+        &SpringBootAdapter;
+        &SpringSecurityAdapter;
+        &InstalledApplications;
+        &Logout;
+        &MultiTenancy;
+        &JAAS;
+    </chapter>
+
+    &IdentityBroker;
+    &Themes;
+    &Recaptcha;
+
+    <chapter>
+        <title>Email</title>
+        <para>
+            Keycloak sends emails to users to verify their email address. Emails are also used to allow users to
+            safely restore their username and passwords.
+        </para>
+        &Email;
+    </chapter>
+    &AccessTypes;
+    &Roles;
+    &DirectAccess;
+    &CORS;
+    &Timeouts;
+    &AdminApi;
+    &Events;
+    &UserFederation;
+    &Kerberos;
+    &ExportImport;
+    &AdminRecovery;
+    &ServerCache;
+    &SAML;
+    &SecurityVulnerabilities;
+    &Clustering;
+    &ApplicationClustering;
+    &Proxy;
+    &CustomAttributes;
+    &ProtocolMappers;
+    &Migration;
+
+</book>
+
+
diff --git a/docbook/reference/en/en-US/modules/access-types.xml b/docbook/reference/en/en-US/modules/access-types.xml
index ce6cf5d..007c1fb 100755
--- a/docbook/reference/en/en-US/modules/access-types.xml
+++ b/docbook/reference/en/en-US/modules/access-types.xml
@@ -1,54 +1,54 @@
-<chapter id="access-types">
-    <title>Client Access Types</title>
-    <para>
-        When you create a Client in admin console you may be wondering what the "Access Types" are.
-    </para>
-    <para>
-        <variablelist>
-            <varlistentry>
-                <term>confidential</term>
-                <listitem>
-                    <para>
-                        Confidential access type is for clients that need to perform a browser login and that you want
-                        to require a client secret when they turn an access code into an access token, (see
-                        <ulink url="http://tools.ietf.org/html/rfc6749#section-4.1.3">Access Token Request</ulink> in
-                        the OAuth 2.0 spec for more details).  The advantages of this is that it is a little extra security.
-                        Since Keycloak requires you to register valid redirect-uris, I'm not exactly sure what this little
-                        extra security is though. :)
-                        The disadvantages of this access type is that confidential access type is pointless for pure
-                        Javascript clients as anybody could easily figure out your client's secret!
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>public</term>
-                <listitem>
-                    <para>
-                        Public access type is for clients that need to perform a browser login and that you feel
-                        that the added extra security of confidential access type is not needed.  FYI, Pure javascript
-                        clients are by nature public.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>bearer-only</term>
-                <listitem>
-                    <para>
-                        Bearer-only access type means that the application only allows bearer token requests.  If this
-                        is turned on, this application cannot participate in browser logins.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>direct access only</term>
-                <listitem>
-                    <para>
-                        You would also see a "Direct Access Only" switch when creating the Client.
-                        This switch is for clients that only use the  <link linkend='direct-access-grants'>Direct Access Grant</link>
-                        protocol to obtain access tokens.
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </para>
+<chapter id="access-types">
+    <title>Client Access Types</title>
+    <para>
+        When you create a Client in admin console you may be wondering what the "Access Types" are.
+    </para>
+    <para>
+        <variablelist>
+            <varlistentry>
+                <term>confidential</term>
+                <listitem>
+                    <para>
+                        Confidential access type is for clients that need to perform a browser login and that you want
+                        to require a client secret when they turn an access code into an access token, (see
+                        <ulink url="http://tools.ietf.org/html/rfc6749#section-4.1.3">Access Token Request</ulink> in
+                        the OAuth 2.0 spec for more details).  The advantages of this is that it is a little extra security.
+                        Since Keycloak requires you to register valid redirect-uris, I'm not exactly sure what this little
+                        extra security is though. :)
+                        The disadvantages of this access type is that confidential access type is pointless for pure
+                        Javascript clients as anybody could easily figure out your client's secret!
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>public</term>
+                <listitem>
+                    <para>
+                        Public access type is for clients that need to perform a browser login and that you feel
+                        that the added extra security of confidential access type is not needed.  FYI, Pure javascript
+                        clients are by nature public.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>bearer-only</term>
+                <listitem>
+                    <para>
+                        Bearer-only access type means that the application only allows bearer token requests.  If this
+                        is turned on, this application cannot participate in browser logins.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>direct access only</term>
+                <listitem>
+                    <para>
+                        You would also see a "Direct Access Only" switch when creating the Client.
+                        This switch is for clients that only use the  <link linkend='direct-access-grants'>Direct Access Grant</link>
+                        protocol to obtain access tokens.
+                    </para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </para>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/adapter-config.xml b/docbook/reference/en/en-US/modules/adapter-config.xml
index 21cc77a..f0f6c99 100755
--- a/docbook/reference/en/en-US/modules/adapter-config.xml
+++ b/docbook/reference/en/en-US/modules/adapter-config.xml
@@ -1,384 +1,384 @@
-<section id="adapter-config">
-    <title>General Adapter Config</title>
-    <para>
-        Each adapter supported by Keycloak can be configured by a simple JSON text file.  This is what one might
-        look like:
-    </para>
-    <para>
-<programlisting><![CDATA[{
-  "realm" : "demo",
-  "resource" : "customer-portal",
-  "realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB",
-  "auth-server-url" : "https://localhost:8443/auth",
-  "ssl-required" : "external",
-  "use-resource-role-mappings" : false,
-  "enable-cors" : true,
-  "cors-max-age" : 1000,
-  "cors-allowed-methods" : "POST, PUT, DELETE, GET",
-  "bearer-only" : false,
-  "enable-basic-auth" : false,
-  "expose-token" : true,
-   "credentials" : {
-      "secret" : "234234-234234-234234"
-   },
-
-   "connection-pool-size" : 20,
-   "disable-trust-manager": false,
-   "allow-any-hostname" : false,
-   "truststore" : "path/to/truststore.jks",
-   "truststore-password" : "geheim",
-   "client-keystore" : "path/to/client-keystore.jks",
-   "client-keystore-password" : "geheim",
-   "client-key-password" : "geheim"
-}]]>
-
-</programlisting>
-    </para>
-    <para>
-        Some of these configuration switches may be adapter specific and some are common across all adapters.
-        For Java adapters you can use <literal>${...}</literal> enclosure as System property replacement.
-        For example <literal>${jboss.server.config.dir}</literal>.  Also, you can obtain a template
-        for this config file from the admin console.  Go to the realm and select the application you want a template for.
-        Go to the <literal>Installation</literal> tab and this will provide you with a template that includes
-        the public key of the realm.
-    </para>
-    <para>
-        Here is a description of each item:
-    </para>
-    <para>
-        <variablelist>
-            <varlistentry>
-                <term>realm</term>
-                <listitem>
-                    <para>
-                        Name of the realm representing the users of your distributed applications and services.
-                        This is
-                        <emphasis>REQUIRED.</emphasis>
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>resource</term>
-                <listitem>
-                    <para>
-                        Username of the application. Each application has a username that is used when the
-                        application connects with the Keycloak server to turn an access code into an access token
-                        (part of the OAuth 2.0 protocol). This is
-                        <emphasis>REQUIRED.</emphasis>
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>realm-public-key</term>
-                <listitem>
-                    <para>
-                        PEM format of public key. You can obtain this from the administration console.
-                        This is
-                        <emphasis>REQUIRED.</emphasis>
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>auth-server-url</term>
-                <listitem>
-                    <para>
-                        The base URL of the Keycloak Server.  All other Keycloak pages and REST services are derived
-                        from this.  It is usually of the form <literal>https://host:port/auth</literal>
-                        This is
-                        <emphasis>REQUIRED.</emphasis>
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>ssl-required</term>
-                <listitem>
-                    <para>
-                        Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is
-                        <emphasis>external</emphasis>
-                        meaning that HTTPS is required by default for external requests. Valid values are 'all', 'external'
-                        and 'none'.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>use-resource-role-mappings</term>
-                <listitem>
-                    <para>
-                        If set to true, the adapter will look inside the token for application level role mappings for
-                        the
-                        user. If false, it will look at the realm level for user role mappings.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>public-client</term>
-                <listitem>
-                    <para>
-                        If set to true, the adapter will not send credentials for the client to Keycloak.
-                        The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>enable-cors</term>
-                <listitem>
-                    <para>
-                        This enables CORS support. It will handle CORS preflight requests. It will also look into
-                        the access token to determine valid origins.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>cors-max-age</term>
-                <listitem>
-                    <para>
-                        If CORS is enabled, this sets the value of the
-                        <literal>Access-Control-Max-Age</literal>
-                        header.
-                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
-                        responses.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>cors-allowed-methods</term>
-                <listitem>
-                    <para>
-                        If CORS is enabled, this sets the value of the
-                        <literal>Access-Control-Allow-Methods</literal>
-                        header. This should be a comma-separated string.
-                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
-                        responses.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>cors-allowed-headers</term>
-                <listitem>
-                    <para>
-                        If CORS is enabled, this sets the value of the
-                        <literal>Access-Control-Allow-Headers</literal>
-                        header. This should be a comma-separated string.
-                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
-                        responses.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>bearer-only</term>
-                <listitem>
-                    <para>
-                        This tells the adapter to only do bearer token authentication. That is, it will not do
-                        OAuth 2.0 redirects, but only accept bearer tokens through the
-                        <literal>Authorization</literal>
-                        header.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>enable-basic-auth</term>
-                <listitem>
-                    <para>
-                        This tells the adapter to also support basic authentication. If this option is enabled,
-                        then <emphasis>secret</emphasis> must also be provided.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>expose-token</term>
-                <listitem>
-                    <para>
-                        If <literal>true</literal>, an authenticated browser client (via a Javascript HTTP invocation)
-                        can obtain the signed access token via the URL <literal>root/k_query_bearer_token</literal>.
-                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>credentials</term>
-                <listitem>
-                    <para>
-                        Specify the credentials of the application. This is an object notation where the key
-                        is the credential type and the value is the value of the credential type. Currently only
-                        <literal>password</literal>
-                        is supported.
-                        This is <emphasis>REQUIRED</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-
-            <varlistentry>
-                <term>connection-pool-size</term>
-                <listitem>
-                    <para>
-                        Adapters will make separate HTTP invocations to the Keycloak Server to turn an access code
-                        into an access token.  This config option defines how many connections to the Keycloak Server
-                        should be pooled.
-                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>20</literal>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>disable-trust-manager</term>
-                <listitem>
-                    <para>
-                        If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
-                        you do not have to specify a truststore.  While convenient,  this setting is not recommended
-                        as you will not be verifying the host name of the Keycloak Server.
-                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>false</literal>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>allow-any-hostname</term>
-                <listitem>
-                    <para>
-                        If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
-                        the Keycloak Server's certificate is validated via the truststore, but host name validation is
-                        not done.  This is not a recommended.  This seting may be useful in test environments
-                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>false</literal>.
-                    </para>
-                </listitem>
-            </varlistentry>
-
-            <varlistentry>
-                <term>truststore</term>
-                <listitem>
-                    <para>
-                        This setting is for Java adapters. The value is the file path to a Java keystore file.  If
-                        you prefix the path with <literal>classpath:</literal>, then the truststore will be obtained
-                        from the deployment's classpath instead.
-                        Used for outgoing HTTPS communications to the Keycloak server. Client making HTTPS
-                        requests need a way to verify the host of the server they are talking to. This is
-                        what the trustore does. The keystore contains one or more trusted
-                        host certificates or certificate authorities. You can
-                        create this truststore by extracting the public certificate of the Keycloak server's SSL
-                        keystore.
-                        This is
-                        <emphasis>OPTIONAL</emphasis>
-                        if
-                        <literal>ssl-required</literal>
-                        is
-                        <literal>none</literal>
-                        or
-                        <literal>disable-trust-manager</literal>
-                        is <literal>true</literal>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>truststore-password</term>
-                <listitem>
-                    <para>
-                        Password for the truststore keystore.
-                        This is
-                        <emphasis>REQUIRED</emphasis>
-                        if
-                        <literal>truststore</literal>
-                        is set.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>client-keystore</term>
-                <listitem>
-                    <para>
-                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
-
-                        This setting is for Java adapters. This is the file path to a Java keystore file.
-                        This keystore contains client certificate for two-way SSL when the adapter makes
-                        HTTPS requests to the Keycloak server.
-                        This is <emphasis>OPTIONAL</emphasis>.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>client-keystore-password</term>
-                <listitem>
-                    <para>
-                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
-                        Password for the client keystore.
-                        This is
-                        <emphasis>REQUIRED</emphasis>
-                        if
-                        <literal>client-keystore</literal>
-                        is set.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>client-key-password</term>
-                <listitem>
-                    <para>
-                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
-                        Password for the client's key.
-                        This is
-                        <emphasis>REQUIRED</emphasis>
-                        if
-                        <literal>client-keystore</literal>
-                        is set.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>auth-server-url-for-backend-requests</term>
-                <listitem>
-                    <para>
-                        Alternative location of auth-server-url used just for backend requests. It must be absolute URI. Useful
-                        especially in cluster (see <link linkend="relative-uri-optimization">Relative URI Optimization</link>) or if you would like to use <emphasis>https</emphasis> for browser requests
-                        but stick with <emphasis>http</emphasis> for backend requests etc.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>always-refresh-token</term>
-                <listitem>
-                    <para>
-                        If <emphasis>true</emphasis>, Keycloak will refresh token in every request. More info in <link linkend="refresh-token-each-req">Refresh token in each request</link> .
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>register-node-at-startup</term>
-                <listitem>
-                    <para>
-                        If <emphasis>true</emphasis>, then adapter will send registration request to Keycloak. It's <emphasis>false</emphasis>
-                        by default and useful just in cluster (See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link>)
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>register-node-period</term>
-                <listitem>
-                    <para>
-                        Period for re-registration adapter to Keycloak. Useful in cluster. See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link> for details.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>token-store</term>
-                <listitem>
-                    <para>
-                        Possible values are <emphasis>session</emphasis> and <emphasis>cookie</emphasis>. Default is <emphasis>session</emphasis>,
-                        which means that adapter stores account info in HTTP Session. Alternative <emphasis>cookie</emphasis> means storage of info in cookie.
-                        See <link linkend="stateless-token-store">Stateless token store</link> for details.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>principal-attribute</term>
-                <listitem>
-                    <para>
-                        OpenID Connection ID Token attribute to populate the UserPrincipal name with.  If token attribute is null, defaults to <literal>sub</literal>.
-                        Possible values are <literal>sub</literal>, <literal>preferred_username</literal>, <literal>email</literal>, <literal>name</literal>, <literal>nickname</literal>, <literal>given_name</literal>, <literal>family_name</literal>.
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </para>
-</section>
+<section id="adapter-config">
+    <title>General Adapter Config</title>
+    <para>
+        Each adapter supported by Keycloak can be configured by a simple JSON text file.  This is what one might
+        look like:
+    </para>
+    <para>
+<programlisting><![CDATA[{
+  "realm" : "demo",
+  "resource" : "customer-portal",
+  "realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB",
+  "auth-server-url" : "https://localhost:8443/auth",
+  "ssl-required" : "external",
+  "use-resource-role-mappings" : false,
+  "enable-cors" : true,
+  "cors-max-age" : 1000,
+  "cors-allowed-methods" : "POST, PUT, DELETE, GET",
+  "bearer-only" : false,
+  "enable-basic-auth" : false,
+  "expose-token" : true,
+   "credentials" : {
+      "secret" : "234234-234234-234234"
+   },
+
+   "connection-pool-size" : 20,
+   "disable-trust-manager": false,
+   "allow-any-hostname" : false,
+   "truststore" : "path/to/truststore.jks",
+   "truststore-password" : "geheim",
+   "client-keystore" : "path/to/client-keystore.jks",
+   "client-keystore-password" : "geheim",
+   "client-key-password" : "geheim"
+}]]>
+
+</programlisting>
+    </para>
+    <para>
+        Some of these configuration switches may be adapter specific and some are common across all adapters.
+        For Java adapters you can use <literal>${...}</literal> enclosure as System property replacement.
+        For example <literal>${jboss.server.config.dir}</literal>.  Also, you can obtain a template
+        for this config file from the admin console.  Go to the realm and select the application you want a template for.
+        Go to the <literal>Installation</literal> tab and this will provide you with a template that includes
+        the public key of the realm.
+    </para>
+    <para>
+        Here is a description of each item:
+    </para>
+    <para>
+        <variablelist>
+            <varlistentry>
+                <term>realm</term>
+                <listitem>
+                    <para>
+                        Name of the realm representing the users of your distributed applications and services.
+                        This is
+                        <emphasis>REQUIRED.</emphasis>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>resource</term>
+                <listitem>
+                    <para>
+                        Username of the application. Each application has a username that is used when the
+                        application connects with the Keycloak server to turn an access code into an access token
+                        (part of the OAuth 2.0 protocol). This is
+                        <emphasis>REQUIRED.</emphasis>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>realm-public-key</term>
+                <listitem>
+                    <para>
+                        PEM format of public key. You can obtain this from the administration console.
+                        This is
+                        <emphasis>REQUIRED.</emphasis>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>auth-server-url</term>
+                <listitem>
+                    <para>
+                        The base URL of the Keycloak Server.  All other Keycloak pages and REST services are derived
+                        from this.  It is usually of the form <literal>https://host:port/auth</literal>
+                        This is
+                        <emphasis>REQUIRED.</emphasis>
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>ssl-required</term>
+                <listitem>
+                    <para>
+                        Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is
+                        <emphasis>external</emphasis>
+                        meaning that HTTPS is required by default for external requests. Valid values are 'all', 'external'
+                        and 'none'.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>use-resource-role-mappings</term>
+                <listitem>
+                    <para>
+                        If set to true, the adapter will look inside the token for application level role mappings for
+                        the
+                        user. If false, it will look at the realm level for user role mappings.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>public-client</term>
+                <listitem>
+                    <para>
+                        If set to true, the adapter will not send credentials for the client to Keycloak.
+                        The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>enable-cors</term>
+                <listitem>
+                    <para>
+                        This enables CORS support. It will handle CORS preflight requests. It will also look into
+                        the access token to determine valid origins.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>cors-max-age</term>
+                <listitem>
+                    <para>
+                        If CORS is enabled, this sets the value of the
+                        <literal>Access-Control-Max-Age</literal>
+                        header.
+                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
+                        responses.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>cors-allowed-methods</term>
+                <listitem>
+                    <para>
+                        If CORS is enabled, this sets the value of the
+                        <literal>Access-Control-Allow-Methods</literal>
+                        header. This should be a comma-separated string.
+                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
+                        responses.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>cors-allowed-headers</term>
+                <listitem>
+                    <para>
+                        If CORS is enabled, this sets the value of the
+                        <literal>Access-Control-Allow-Headers</literal>
+                        header. This should be a comma-separated string.
+                        This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
+                        responses.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>bearer-only</term>
+                <listitem>
+                    <para>
+                        This tells the adapter to only do bearer token authentication. That is, it will not do
+                        OAuth 2.0 redirects, but only accept bearer tokens through the
+                        <literal>Authorization</literal>
+                        header.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>enable-basic-auth</term>
+                <listitem>
+                    <para>
+                        This tells the adapter to also support basic authentication. If this option is enabled,
+                        then <emphasis>secret</emphasis> must also be provided.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>expose-token</term>
+                <listitem>
+                    <para>
+                        If <literal>true</literal>, an authenticated browser client (via a Javascript HTTP invocation)
+                        can obtain the signed access token via the URL <literal>root/k_query_bearer_token</literal>.
+                        This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>credentials</term>
+                <listitem>
+                    <para>
+                        Specify the credentials of the application. This is an object notation where the key
+                        is the credential type and the value is the value of the credential type. Currently only
+                        <literal>password</literal>
+                        is supported.
+                        This is <emphasis>REQUIRED</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>connection-pool-size</term>
+                <listitem>
+                    <para>
+                        Adapters will make separate HTTP invocations to the Keycloak Server to turn an access code
+                        into an access token.  This config option defines how many connections to the Keycloak Server
+                        should be pooled.
+                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>20</literal>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>disable-trust-manager</term>
+                <listitem>
+                    <para>
+                        If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
+                        you do not have to specify a truststore.  While convenient,  this setting is not recommended
+                        as you will not be verifying the host name of the Keycloak Server.
+                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>false</literal>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>allow-any-hostname</term>
+                <listitem>
+                    <para>
+                        If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
+                        the Keycloak Server's certificate is validated via the truststore, but host name validation is
+                        not done.  This is not a recommended.  This seting may be useful in test environments
+                        This is <emphasis>OPTIONAL</emphasis>.  The default value is <literal>false</literal>.
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>truststore</term>
+                <listitem>
+                    <para>
+                        This setting is for Java adapters. The value is the file path to a Java keystore file.  If
+                        you prefix the path with <literal>classpath:</literal>, then the truststore will be obtained
+                        from the deployment's classpath instead.
+                        Used for outgoing HTTPS communications to the Keycloak server. Client making HTTPS
+                        requests need a way to verify the host of the server they are talking to. This is
+                        what the trustore does. The keystore contains one or more trusted
+                        host certificates or certificate authorities. You can
+                        create this truststore by extracting the public certificate of the Keycloak server's SSL
+                        keystore.
+                        This is
+                        <emphasis>OPTIONAL</emphasis>
+                        if
+                        <literal>ssl-required</literal>
+                        is
+                        <literal>none</literal>
+                        or
+                        <literal>disable-trust-manager</literal>
+                        is <literal>true</literal>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>truststore-password</term>
+                <listitem>
+                    <para>
+                        Password for the truststore keystore.
+                        This is
+                        <emphasis>REQUIRED</emphasis>
+                        if
+                        <literal>truststore</literal>
+                        is set.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>client-keystore</term>
+                <listitem>
+                    <para>
+                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
+
+                        This setting is for Java adapters. This is the file path to a Java keystore file.
+                        This keystore contains client certificate for two-way SSL when the adapter makes
+                        HTTPS requests to the Keycloak server.
+                        This is <emphasis>OPTIONAL</emphasis>.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>client-keystore-password</term>
+                <listitem>
+                    <para>
+                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
+                        Password for the client keystore.
+                        This is
+                        <emphasis>REQUIRED</emphasis>
+                        if
+                        <literal>client-keystore</literal>
+                        is set.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>client-key-password</term>
+                <listitem>
+                    <para>
+                        <emphasis>Not supported yet, but we will support in future versions.</emphasis>
+                        Password for the client's key.
+                        This is
+                        <emphasis>REQUIRED</emphasis>
+                        if
+                        <literal>client-keystore</literal>
+                        is set.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>auth-server-url-for-backend-requests</term>
+                <listitem>
+                    <para>
+                        Alternative location of auth-server-url used just for backend requests. It must be absolute URI. Useful
+                        especially in cluster (see <link linkend="relative-uri-optimization">Relative URI Optimization</link>) or if you would like to use <emphasis>https</emphasis> for browser requests
+                        but stick with <emphasis>http</emphasis> for backend requests etc.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>always-refresh-token</term>
+                <listitem>
+                    <para>
+                        If <emphasis>true</emphasis>, Keycloak will refresh token in every request. More info in <link linkend="refresh-token-each-req">Refresh token in each request</link> .
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>register-node-at-startup</term>
+                <listitem>
+                    <para>
+                        If <emphasis>true</emphasis>, then adapter will send registration request to Keycloak. It's <emphasis>false</emphasis>
+                        by default and useful just in cluster (See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link>)
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>register-node-period</term>
+                <listitem>
+                    <para>
+                        Period for re-registration adapter to Keycloak. Useful in cluster. See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link> for details.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>token-store</term>
+                <listitem>
+                    <para>
+                        Possible values are <emphasis>session</emphasis> and <emphasis>cookie</emphasis>. Default is <emphasis>session</emphasis>,
+                        which means that adapter stores account info in HTTP Session. Alternative <emphasis>cookie</emphasis> means storage of info in cookie.
+                        See <link linkend="stateless-token-store">Stateless token store</link> for details.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>principal-attribute</term>
+                <listitem>
+                    <para>
+                        OpenID Connection ID Token attribute to populate the UserPrincipal name with.  If token attribute is null, defaults to <literal>sub</literal>.
+                        Possible values are <literal>sub</literal>, <literal>preferred_username</literal>, <literal>email</literal>, <literal>name</literal>, <literal>nickname</literal>, <literal>given_name</literal>, <literal>family_name</literal>.
+                    </para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </para>
+</section>
diff --git a/docbook/reference/en/en-US/modules/admin-permissions.xml b/docbook/reference/en/en-US/modules/admin-permissions.xml
index d1e8faf..833d390 100755
--- a/docbook/reference/en/en-US/modules/admin-permissions.xml
+++ b/docbook/reference/en/en-US/modules/admin-permissions.xml
@@ -1,82 +1,82 @@
-<chapter id="admin-permissions">
-    <title>Master Admin Access Control</title>
-    <para>
-        You can create and manage multiple realms by logging into the <literal>master</literal> Keycloak admin console
-        at <literal>/{keycloak-root}/admin/index.html</literal>
-    </para>
-    <para>
-        Users in the Keycloak <literal>master</literal> realm can be granted permission to manage zero or more realms that are
-        deployed on the Keycloak server.  When a realm is created, Keycloak automatically creates various roles that grant fine-grain
-        permissions to access that new realm.
-        Access to The Admin Console and REST endpoints can be controlled by mapping these roles to users in the <literal>master</literal> realm.
-        It's possible to create multiple super users as well as users that have only access to certain operations in specific realms.
-    </para>
-    <section>
-        <title>Global Roles</title>
-        <para>
-            There are two realm roles in the <literal>master</literal> realm. These are:
-            <itemizedlist>
-                <listitem>
-                    <literal>admin</literal> - This is the super-user role and grants permissions to all operations on all realms
-                </listitem>
-                <listitem>
-                    <literal>create-realm</literal> - This grants the user permission to create new realms. A user that creates a realm is granted all permissions to the newly created realm.
-                </listitem>
-            </itemizedlist>
-        </para>
-        <para>
-            To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
-            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
-            <literal>Realm Roles</literal> assign any of the above roles to the user by selecting it and clicking on the right-arrow.
-        </para>
-    </section>
-
-    <section>
-        <title>Realm Specific Roles</title>
-        <para>
-            Each realm in Keycloak is represented by an application in the <literal>master</literal> realm. The name of the application
-            is <literal>&lt;realm name&gt;-realm</literal>. This allows assigning access to users for individual realms. The
-            roles available are:
-            <itemizedlist>
-                <listitem>
-                    <literal>view-realm</literal> - View the realm configuration
-                </listitem>
-                <listitem>
-                    <literal>view-users</literal> - View users (including details for specific user) in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-applications</literal> - View applications in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-clients</literal> - View clients in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-events</literal> - View events in the realm
-                </listitem>
-
-                <listitem>
-                    <literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
-                </listitem>
-                <listitem>
-                    <literal>manage-users</literal> - Create, modify and delete users in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-applications</literal> - Create, modify and delete applications in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-clients</literal> - Create, modify and delete clients in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
-                </listitem>
-            </itemizedlist>
-            Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
-        </para>
-        <para>
-            To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
-            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
-            <literal>Application Roles</literal> select the application that represents the realm you're adding permissions to
-            (<literal>&lt;realm name&gt;-realm</literal>), then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
-        </para>
-    </section>
-</chapter>
+<chapter id="admin-permissions">
+    <title>Master Admin Access Control</title>
+    <para>
+        You can create and manage multiple realms by logging into the <literal>master</literal> Keycloak admin console
+        at <literal>/{keycloak-root}/admin/index.html</literal>
+    </para>
+    <para>
+        Users in the Keycloak <literal>master</literal> realm can be granted permission to manage zero or more realms that are
+        deployed on the Keycloak server.  When a realm is created, Keycloak automatically creates various roles that grant fine-grain
+        permissions to access that new realm.
+        Access to The Admin Console and REST endpoints can be controlled by mapping these roles to users in the <literal>master</literal> realm.
+        It's possible to create multiple super users as well as users that have only access to certain operations in specific realms.
+    </para>
+    <section>
+        <title>Global Roles</title>
+        <para>
+            There are two realm roles in the <literal>master</literal> realm. These are:
+            <itemizedlist>
+                <listitem>
+                    <literal>admin</literal> - This is the super-user role and grants permissions to all operations on all realms
+                </listitem>
+                <listitem>
+                    <literal>create-realm</literal> - This grants the user permission to create new realms. A user that creates a realm is granted all permissions to the newly created realm.
+                </listitem>
+            </itemizedlist>
+        </para>
+        <para>
+            To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
+            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
+            <literal>Realm Roles</literal> assign any of the above roles to the user by selecting it and clicking on the right-arrow.
+        </para>
+    </section>
+
+    <section>
+        <title>Realm Specific Roles</title>
+        <para>
+            Each realm in Keycloak is represented by an application in the <literal>master</literal> realm. The name of the application
+            is <literal>&lt;realm name&gt;-realm</literal>. This allows assigning access to users for individual realms. The
+            roles available are:
+            <itemizedlist>
+                <listitem>
+                    <literal>view-realm</literal> - View the realm configuration
+                </listitem>
+                <listitem>
+                    <literal>view-users</literal> - View users (including details for specific user) in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-applications</literal> - View applications in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-clients</literal> - View clients in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-events</literal> - View events in the realm
+                </listitem>
+
+                <listitem>
+                    <literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
+                </listitem>
+                <listitem>
+                    <literal>manage-users</literal> - Create, modify and delete users in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-applications</literal> - Create, modify and delete applications in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-clients</literal> - Create, modify and delete clients in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
+                </listitem>
+            </itemizedlist>
+            Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
+        </para>
+        <para>
+            To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
+            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
+            <literal>Application Roles</literal> select the application that represents the realm you're adding permissions to
+            (<literal>&lt;realm name&gt;-realm</literal>), then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
+        </para>
+    </section>
+</chapter>
diff --git a/docbook/reference/en/en-US/modules/admin-rest-api.xml b/docbook/reference/en/en-US/modules/admin-rest-api.xml
index 93e5423..0ad7aee 100755
--- a/docbook/reference/en/en-US/modules/admin-rest-api.xml
+++ b/docbook/reference/en/en-US/modules/admin-rest-api.xml
@@ -1,18 +1,18 @@
-<chapter id="admin-rest-api">
-    <title>Admin REST API</title>
-    <para>
-        The Keycloak Admin Console is implemented entirely with a fully functional REST admin API.  You can invoke this
-        REST API from your Java applications by obtaining an access token.  You must have the appropriate
-        permissions set up as described in <xref linkend="admin-permissions" /> and <xref linkend="per-realm-admin-permissions" />
-    </para>
-    <para>
-        The documentation for this REST API is auto-generated and is contained in the distribution of keycloak under
-        the docs/rest-api/overview-index.html directory, or directly from the docs page at the keycloak website.
-    </para>
-    <para>
-        There are a number of examples that come with the keycloak distribution that show you how to invoke on this REST API.
-        <literal>examples/preconfigured-demo/admin-access-app</literal> shows you how to access this api from java.
-        <literal>examples/cors/angular-product-app</literal> shows you how to invoke on it from Javascript. Finally there is example in
-        <literal>example/admin-client</literal>, which contains example for Admin client, that can be used to invoke REST endpoints easily as Java methods.
-    </para>
+<chapter id="admin-rest-api">
+    <title>Admin REST API</title>
+    <para>
+        The Keycloak Admin Console is implemented entirely with a fully functional REST admin API.  You can invoke this
+        REST API from your Java applications by obtaining an access token.  You must have the appropriate
+        permissions set up as described in <xref linkend="admin-permissions" /> and <xref linkend="per-realm-admin-permissions" />
+    </para>
+    <para>
+        The documentation for this REST API is auto-generated and is contained in the distribution of keycloak under
+        the docs/rest-api/overview-index.html directory, or directly from the docs page at the keycloak website.
+    </para>
+    <para>
+        There are a number of examples that come with the keycloak distribution that show you how to invoke on this REST API.
+        <literal>examples/preconfigured-demo/admin-access-app</literal> shows you how to access this api from java.
+        <literal>examples/cors/angular-product-app</literal> shows you how to invoke on it from Javascript. Finally there is example in
+        <literal>example/admin-client</literal>, which contains example for Admin client, that can be used to invoke REST endpoints easily as Java methods.
+    </para>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/cache.xml b/docbook/reference/en/en-US/modules/cache.xml
index 6d001b1..1be4fa6 100755
--- a/docbook/reference/en/en-US/modules/cache.xml
+++ b/docbook/reference/en/en-US/modules/cache.xml
@@ -1,68 +1,68 @@
-<chapter id="server_cache">
-    <title>Server Cache</title>
-    <para>
-        By default, Keycloak caches realm metadata and users.  There are two separate caches, one for realm metadata
-        (realm, application, client, roles, etc...) and one for users.  These caches greatly improves the performance of the server.
-    </para>
-
-    <section>
-        <title>Disabling Caches</title>
-        <para>
-            The realm and user caches can be disabled through configuration or through the management console.  To
-            manally disable the realm or user cache, you must edit the <literal>keycloak-server.json</literal> file
-            in your distribution.  Here's what the config looks like initially.
-        </para>
-        <para>
-            <programlisting><![CDATA[
-    "realmCache": {
-        "provider": "${keycloak.realm.cache.provider:mem}"
-    },
-
-    "userCache": {
-        "provider": "${keycloak.user.cache.provider:mem}",
-        "mem": {
-            "maxSize": 20000
-        }
-    },
-]]></programlisting>
-        </para>
-        <para>You must then change it to:
-            <programlisting><![CDATA[
-    "realmCache": {
-        "provider": "${keycloak.realm.cache.provider:none}"
-    },
-
-    "userCache": {
-        "provider": "${keycloak.user.cache.provider:none}"
-    },
-]]></programlisting>
-        </para>
-        <para>
-           You can also disable either of the caches at runtime through the Keycloak admin console Realm Settings page.
-           This will not permanently disable the cache.  If you reboot the server, the cache will be re-enabled unless
-            you manualy disable the cache in the <literal>keycloak-server.json</literal> file.
-        </para>
-    </section>
-    <section>
-        <title>Clear Caches</title>
-        <para>
-            To clear the realm or user cache, go to the Keycloak admin console Realm Settings->Cache Config page.  Disable the cache
-            you want.  Save the settings.  Then re-enable the cache.  This will cause the cache to be cleared.
-        </para>
-    </section>
-    <section>
-        <title>Cache Config</title>
-        <para>
-            Cache configuration is done within <literal>keycloak-server.json</literal>.  Changes to this file will not
-            be seen by the server until you reboot.  Currently you can only configure the max size of the user cache.
-            <programlisting><![CDATA[
-    "userCache": {
-        "provider": "${keycloak.user.cache.provider:mem}",
-        "mem": {
-            "maxSize": 20000
-        }
-    },
-]]></programlisting>
-        </para>
-    </section>
+<chapter id="server_cache">
+    <title>Server Cache</title>
+    <para>
+        By default, Keycloak caches realm metadata and users.  There are two separate caches, one for realm metadata
+        (realm, application, client, roles, etc...) and one for users.  These caches greatly improves the performance of the server.
+    </para>
+
+    <section>
+        <title>Disabling Caches</title>
+        <para>
+            The realm and user caches can be disabled through configuration or through the management console.  To
+            manally disable the realm or user cache, you must edit the <literal>keycloak-server.json</literal> file
+            in your distribution.  Here's what the config looks like initially.
+        </para>
+        <para>
+            <programlisting><![CDATA[
+    "realmCache": {
+        "provider": "${keycloak.realm.cache.provider:mem}"
+    },
+
+    "userCache": {
+        "provider": "${keycloak.user.cache.provider:mem}",
+        "mem": {
+            "maxSize": 20000
+        }
+    },
+]]></programlisting>
+        </para>
+        <para>You must then change it to:
+            <programlisting><![CDATA[
+    "realmCache": {
+        "provider": "${keycloak.realm.cache.provider:none}"
+    },
+
+    "userCache": {
+        "provider": "${keycloak.user.cache.provider:none}"
+    },
+]]></programlisting>
+        </para>
+        <para>
+           You can also disable either of the caches at runtime through the Keycloak admin console Realm Settings page.
+           This will not permanently disable the cache.  If you reboot the server, the cache will be re-enabled unless
+            you manualy disable the cache in the <literal>keycloak-server.json</literal> file.
+        </para>
+    </section>
+    <section>
+        <title>Clear Caches</title>
+        <para>
+            To clear the realm or user cache, go to the Keycloak admin console Realm Settings->Cache Config page.  Disable the cache
+            you want.  Save the settings.  Then re-enable the cache.  This will cause the cache to be cleared.
+        </para>
+    </section>
+    <section>
+        <title>Cache Config</title>
+        <para>
+            Cache configuration is done within <literal>keycloak-server.json</literal>.  Changes to this file will not
+            be seen by the server until you reboot.  Currently you can only configure the max size of the user cache.
+            <programlisting><![CDATA[
+    "userCache": {
+        "provider": "${keycloak.user.cache.provider:mem}",
+        "mem": {
+            "maxSize": 20000
+        }
+    },
+]]></programlisting>
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/cors.xml b/docbook/reference/en/en-US/modules/cors.xml
index 99ced70..1788cd0 100755
--- a/docbook/reference/en/en-US/modules/cors.xml
+++ b/docbook/reference/en/en-US/modules/cors.xml
@@ -1,25 +1,25 @@
-<chapter id="cors">
-    <title>CORS</title>
-    <para>
-        CORS stands for Cross-Origin Resource Sharing.  If executing browser Javascript tries to make an AJAX HTTP request
-        to a server's whose domain is different than the one the Javascript code came from, then the request uses the
-        <ulink url="http://www.w3.org/TR/cors/">CORS protocol</ulink>.  The server must handle CORS requests in a special
-        way, otherwise the browser will not display or allow the request to be processed.  This protocol exists to protect
-        against XSS and other Javascript-based attacks.  Keycloak has support for validated CORS requests.
-    </para>
-    <para>
-        Keycloak's CORS support is configured per client.  You specify the allowed origins
-        in the client's configuration page in the admin console.  You can add as many you want.  The value
-        must be what the browser would send as a value in the <literal>Origin</literal> header.  For example <literal>http://example.com</literal>
-        is what you must specify to allow CORS requests from <literal>example.com</literal>.  When an access token is
-        created for the client, these allowed origins are embedded within the token.  On authenticated
-        CORS requests, your application's Keycloak adapter will handle the CORS protocol and validate the <literal>Origin</literal>
-        header against the allowed origins embedded in the token.  If there is no match, then the request is denied.
-    </para>
-    <para>
-        To enable CORS processing in your application's server, you must set the <literal>enable-cors</literal> setting
-        to <literal>true</literal> in your <link linkend='adapter-config'>adapter's configuration file</link>.  When this
-        setting is enabled, the Keycloak adapter will handle all CORS preflight requests.  It will validate authenticated
-        requests (protected resource requests), but will let unauthenticated requests (unprotected resource requests) pass through.
-    </para>
+<chapter id="cors">
+    <title>CORS</title>
+    <para>
+        CORS stands for Cross-Origin Resource Sharing.  If executing browser Javascript tries to make an AJAX HTTP request
+        to a server's whose domain is different than the one the Javascript code came from, then the request uses the
+        <ulink url="http://www.w3.org/TR/cors/">CORS protocol</ulink>.  The server must handle CORS requests in a special
+        way, otherwise the browser will not display or allow the request to be processed.  This protocol exists to protect
+        against XSS and other Javascript-based attacks.  Keycloak has support for validated CORS requests.
+    </para>
+    <para>
+        Keycloak's CORS support is configured per client.  You specify the allowed origins
+        in the client's configuration page in the admin console.  You can add as many you want.  The value
+        must be what the browser would send as a value in the <literal>Origin</literal> header.  For example <literal>http://example.com</literal>
+        is what you must specify to allow CORS requests from <literal>example.com</literal>.  When an access token is
+        created for the client, these allowed origins are embedded within the token.  On authenticated
+        CORS requests, your application's Keycloak adapter will handle the CORS protocol and validate the <literal>Origin</literal>
+        header against the allowed origins embedded in the token.  If there is no match, then the request is denied.
+    </para>
+    <para>
+        To enable CORS processing in your application's server, you must set the <literal>enable-cors</literal> setting
+        to <literal>true</literal> in your <link linkend='adapter-config'>adapter's configuration file</link>.  When this
+        setting is enabled, the Keycloak adapter will handle all CORS preflight requests.  It will validate authenticated
+        requests (protected resource requests), but will let unauthenticated requests (unprotected resource requests) pass through.
+    </para>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/custom-attributes.xml b/docbook/reference/en/en-US/modules/custom-attributes.xml
index 338cdf2..7aefdb6 100755
--- a/docbook/reference/en/en-US/modules/custom-attributes.xml
+++ b/docbook/reference/en/en-US/modules/custom-attributes.xml
@@ -1,150 +1,150 @@
-<chapter id="custom-user-attributes">
-    <title>Custom User Attributes</title>
-    <para>If you have custom user data you want to store and manage in the admin console, registration page, and user account service, you can easily add
-    support for it by extending and modifying various Keycloak <link linkend="themes">themes</link>.</para>
-    <section>
-        <title>In admin console</title>
-    <para>To be able to enter custom attributes in the admin console, take the following steps</para>
-    <para>
-        <orderedlist>
-            <listitem>
-                Create a new theme within the <literal>themes/admin/mytheme</literal> directory in your distribution.
-                Where <literal>mytheme</literal> is whatever you want to name your theme.
-            </listitem>
-            <listitem>
-                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
-                theme.
-                <programlisting><![CDATA[parent=keycloak
-import=common/keycloak
-]]></programlisting>
-            </listitem>
-            <listitem>
-                Copy the file <literal>themes/admin/base/resources/partials/user-attribute-entry.html</literal> into the
-                a mirror directory in your theme: <literal>themes/admin/mytheme/resources/partials/user-attribute-entry.html</literal>.
-                What you are doing here is overriding the user attribute entry page in the admin console and putting in
-                what attributes you want.  This file already contains an example of entering address data.  You can remove
-                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
-                of creating a new theme, you can.
-            </listitem>
-            <listitem>
-                In the <literal>user-attribute-entry.html</literal> file add your custom user attribute entry form item.  For example
-<programlisting><![CDATA[    <div class="form-group clearfix block">
-        <label class="col-sm-2 control-label" for="mobile">Mobile</label>
-        <div class="col-sm-6">
-            <input ng-model="user.attributes.mobile" class="form-control" type="text" name="mobile" id="mobile" />
-        </div>
-        <span tooltip-placement="right" tooltip="Mobile number." class="fa fa-info-circle"></span>
-    </div>
-]]></programlisting>
-                The <literal>ng-model</literal> names the user attribute you will store in the database and must have the
-                form of <literal>user.attributes.ATTR_NAME</literal>.
-            </listitem>
-            <listitem>
-                Change the theme for the admin console.  Save it, then refresh your browser, and you should
-                now see these fields in the User detail page for any user.
-            </listitem>
-        </orderedlist>
-    </para>
-    </section>
-    <section>
-        <title>In registration page</title>
-    <para>To be able to enter custom attributes in the registration page, take the following steps</para>
-    <para>
-        <orderedlist>
-            <listitem>
-                Create a new theme within the <literal>themes/login/mytheme</literal> directory in your distribution.
-                Where <literal>mytheme</literal> is whatever you want to name your theme.
-            </listitem>
-            <listitem>
-                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
-                theme.
-                <programlisting><![CDATA[parent=keycloak
-import=common/keycloak
-styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/login.css ../patternfly/lib/zocial/zocial.css css/login.css]]></programlisting>
-            </listitem>
-            <listitem>
-                Copy the file <literal>themes/login/base/register.ftl</literal> into the
-                a mirror directory in your theme: <literal>themes/login/mytheme/register.ftl</literal>.
-                What you are doing here is overriding the registration page and adding
-                what attributes you want.  This file already contains an example of entering address data.  You can remove
-                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
-                of creating a new theme, you can.
-            </listitem>
-            <listitem>
-                In the <literal>register.ftl</literal> file add your custom user attribute entry form item.  For example
-<programlisting><![CDATA[
-<div class="form-group">
-   <div class="${properties.kcLabelWrapperClass!}">
-       <label for="user.attributes.mobile" class="${properties.kcLabelClass!}">Mobile number</label>
-   </div>
-
-   <div class="col-sm-10 col-md-10">
-       <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.mobile" name="user.attributes.mobile"/>
-   </div>
-</div>
-]]></programlisting>
-                Make sure the input field id ane name match the user attribute you want to store in the database.
-                This must have the
-                form of <literal>user.attributes.ATTR_NAME</literal>.  You might also want to replace the label text
-                with a message property.  This will help later if you want to internationalize your pages.
-            </listitem>
-            <listitem>
-                Change the theme for the login to your new theme.  Save it, then refresh your browser, and you should
-                now see these fields in the registration.
-            </listitem>
-        </orderedlist>
-    </para>
-    </section>
-    <section>
-        <title>In user account profile page</title>
-    <para>To be able to manage custom attributes in the user account profile page, take the following steps</para>
-    <para>
-        <orderedlist>
-            <listitem>
-                Create a new theme within the <literal>themes/account/mytheme</literal> directory in your distribution.
-                Where <literal>mytheme</literal> is whatever you want to name your theme.
-            </listitem>
-            <listitem>
-                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
-                theme.
-                <programlisting><![CDATA[parent=patternfly
-import=common/keycloak
-
-styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/account.css css/account.css]]></programlisting>
-            </listitem>
-            <listitem>
-                Copy the file <literal>themes/account/base/account.ftl</literal> into the
-                a mirror directory in your theme: <literal>themes/account/mytheme/account.ftl</literal>.
-                What you are doing here is overriding the profile page and adding
-                what attributes you want to manage.  This file already contains an example of entering address data.  You can remove
-                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
-                of creating a new theme, you can.
-            </listitem>
-            <listitem>
-                In the <literal>account.ftl</literal> file add your custom user attribute entry form item.  For example
-<programlisting><![CDATA[
-<div class="form-group">
-   <div class="col-sm-2 col-md-2">
-       <label for="user.attributes.mobile" class="control-label">Mobile number</label>
-   </div>
-
-   <div class="col-sm-10 col-md-10">
-       <input type="text" class="form-control" id="user.attributes.mobile" name="user.attributes.mobile" value="${(account.attributes.mobile!'')?html}"/>
-   </div>
-</div>]]></programlisting>
-                Make sure the input field id ane name match the user attribute you want to store in the database.
-                This must have the
-                form of <literal>user.attributes.ATTR_NAME</literal>.  You might also want to replace the label text
-                with a message property.  This will help later if you want to internationalize your pages.
-            </listitem>
-            <listitem>
-                Change the theme for the account to your new theme.  Save it, then refresh your browser, and you should
-                now see these fields in the account profile page.
-            </listitem>
-        </orderedlist>
-    </para>
-    </section>
-
-
-
+<chapter id="custom-user-attributes">
+    <title>Custom User Attributes</title>
+    <para>If you have custom user data you want to store and manage in the admin console, registration page, and user account service, you can easily add
+    support for it by extending and modifying various Keycloak <link linkend="themes">themes</link>.</para>
+    <section>
+        <title>In admin console</title>
+    <para>To be able to enter custom attributes in the admin console, take the following steps</para>
+    <para>
+        <orderedlist>
+            <listitem>
+                Create a new theme within the <literal>themes/admin/mytheme</literal> directory in your distribution.
+                Where <literal>mytheme</literal> is whatever you want to name your theme.
+            </listitem>
+            <listitem>
+                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
+                theme.
+                <programlisting><![CDATA[parent=keycloak
+import=common/keycloak
+]]></programlisting>
+            </listitem>
+            <listitem>
+                Copy the file <literal>themes/admin/base/resources/partials/user-attribute-entry.html</literal> into the
+                a mirror directory in your theme: <literal>themes/admin/mytheme/resources/partials/user-attribute-entry.html</literal>.
+                What you are doing here is overriding the user attribute entry page in the admin console and putting in
+                what attributes you want.  This file already contains an example of entering address data.  You can remove
+                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
+                of creating a new theme, you can.
+            </listitem>
+            <listitem>
+                In the <literal>user-attribute-entry.html</literal> file add your custom user attribute entry form item.  For example
+<programlisting><![CDATA[    <div class="form-group clearfix block">
+        <label class="col-sm-2 control-label" for="mobile">Mobile</label>
+        <div class="col-sm-6">
+            <input ng-model="user.attributes.mobile" class="form-control" type="text" name="mobile" id="mobile" />
+        </div>
+        <span tooltip-placement="right" tooltip="Mobile number." class="fa fa-info-circle"></span>
+    </div>
+]]></programlisting>
+                The <literal>ng-model</literal> names the user attribute you will store in the database and must have the
+                form of <literal>user.attributes.ATTR_NAME</literal>.
+            </listitem>
+            <listitem>
+                Change the theme for the admin console.  Save it, then refresh your browser, and you should
+                now see these fields in the User detail page for any user.
+            </listitem>
+        </orderedlist>
+    </para>
+    </section>
+    <section>
+        <title>In registration page</title>
+    <para>To be able to enter custom attributes in the registration page, take the following steps</para>
+    <para>
+        <orderedlist>
+            <listitem>
+                Create a new theme within the <literal>themes/login/mytheme</literal> directory in your distribution.
+                Where <literal>mytheme</literal> is whatever you want to name your theme.
+            </listitem>
+            <listitem>
+                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
+                theme.
+                <programlisting><![CDATA[parent=keycloak
+import=common/keycloak
+styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/login.css ../patternfly/lib/zocial/zocial.css css/login.css]]></programlisting>
+            </listitem>
+            <listitem>
+                Copy the file <literal>themes/login/base/register.ftl</literal> into the
+                a mirror directory in your theme: <literal>themes/login/mytheme/register.ftl</literal>.
+                What you are doing here is overriding the registration page and adding
+                what attributes you want.  This file already contains an example of entering address data.  You can remove
+                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
+                of creating a new theme, you can.
+            </listitem>
+            <listitem>
+                In the <literal>register.ftl</literal> file add your custom user attribute entry form item.  For example
+<programlisting><![CDATA[
+<div class="form-group">
+   <div class="${properties.kcLabelWrapperClass!}">
+       <label for="user.attributes.mobile" class="${properties.kcLabelClass!}">Mobile number</label>
+   </div>
+
+   <div class="col-sm-10 col-md-10">
+       <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.mobile" name="user.attributes.mobile"/>
+   </div>
+</div>
+]]></programlisting>
+                Make sure the input field id ane name match the user attribute you want to store in the database.
+                This must have the
+                form of <literal>user.attributes.ATTR_NAME</literal>.  You might also want to replace the label text
+                with a message property.  This will help later if you want to internationalize your pages.
+            </listitem>
+            <listitem>
+                Change the theme for the login to your new theme.  Save it, then refresh your browser, and you should
+                now see these fields in the registration.
+            </listitem>
+        </orderedlist>
+    </para>
+    </section>
+    <section>
+        <title>In user account profile page</title>
+    <para>To be able to manage custom attributes in the user account profile page, take the following steps</para>
+    <para>
+        <orderedlist>
+            <listitem>
+                Create a new theme within the <literal>themes/account/mytheme</literal> directory in your distribution.
+                Where <literal>mytheme</literal> is whatever you want to name your theme.
+            </listitem>
+            <listitem>
+                Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
+                theme.
+                <programlisting><![CDATA[parent=patternfly
+import=common/keycloak
+
+styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/account.css css/account.css]]></programlisting>
+            </listitem>
+            <listitem>
+                Copy the file <literal>themes/account/base/account.ftl</literal> into the
+                a mirror directory in your theme: <literal>themes/account/mytheme/account.ftl</literal>.
+                What you are doing here is overriding the profile page and adding
+                what attributes you want to manage.  This file already contains an example of entering address data.  You can remove
+                this if you want and replace it with something else.  Also, if you want to edit this file directly instead
+                of creating a new theme, you can.
+            </listitem>
+            <listitem>
+                In the <literal>account.ftl</literal> file add your custom user attribute entry form item.  For example
+<programlisting><![CDATA[
+<div class="form-group">
+   <div class="col-sm-2 col-md-2">
+       <label for="user.attributes.mobile" class="control-label">Mobile number</label>
+   </div>
+
+   <div class="col-sm-10 col-md-10">
+       <input type="text" class="form-control" id="user.attributes.mobile" name="user.attributes.mobile" value="${(account.attributes.mobile!'')?html}"/>
+   </div>
+</div>]]></programlisting>
+                Make sure the input field id ane name match the user attribute you want to store in the database.
+                This must have the
+                form of <literal>user.attributes.ATTR_NAME</literal>.  You might also want to replace the label text
+                with a message property.  This will help later if you want to internationalize your pages.
+            </listitem>
+            <listitem>
+                Change the theme for the account to your new theme.  Save it, then refresh your browser, and you should
+                now see these fields in the account profile page.
+            </listitem>
+        </orderedlist>
+    </para>
+    </section>
+
+
+
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/direct-access.xml b/docbook/reference/en/en-US/modules/direct-access.xml
index e7a189b..c715aee 100755
--- a/docbook/reference/en/en-US/modules/direct-access.xml
+++ b/docbook/reference/en/en-US/modules/direct-access.xml
@@ -1,162 +1,162 @@
-<chapter id="direct-access-grants">
-    <title>Direct Access Grants</title>
-    <para>
-        Keycloak allows you to make direct REST invocations to obtain an access token.
-        (See <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3">Resource Owner Password Credentials Grant</ulink>
-        from OAuth 2.0 spec).  To use it you must also have
-        registered a valid Client to use as the "client_id" for this grant request.
-    </para>
-    <warning>
-        <para>
-            It is highly recommended that you do not use Direct Access Grants to write your own login pages for your application.
-            You will lose a lot of features that Keycloak has if you do this.  Specifically all the account management, remember me,
-            lost password, account reset features of Keycloak.  Instead, if you want to tailor the look and feel of Keycloak login
-            pages, you should create your own <link linkend="themes">theme</link>. There are also security implications
-            to using Direct Access Grants compared to the redirect based flows as you are exposing plain text passwords
-            to applications directly.
-        </para>
-        <para>
-            It is even highly recommended that you use the browser to log in for native mobile applications!  Android
-            and iPhone applications allow you to redirect to and from the browser.  You can use this to redirect the user
-            from your native mobile app to the web browser to perform login, then the browser will redirect back to your
-            native application.
-        </para>
-    </warning>
-
-
-    <para>
-        The REST URL to invoke on is <literal>/{keycloak-root}/realms/{realm-name}/protocol/openid-connect/token</literal>.
-        Invoking on this URL is a POST request and requires you to post the username and credentials of the user you want
-        an access token for.  You must also pass along the "client_id" of the client you are creating
-        an access token for.  This "client_id" is the Client Id specified in admin console (not it's id from DB!).  Depending on
-        whether your client is <link linkend='access-types'>"public" or "confidential"</link>, you may also have to pass along
-        it's client secret as well. Finally you need to pass "grant_type" parameter with value "password" .
-    </para>
-    <para>
-        For public client's, the POST invocation requires form parameters that contain the username,
-        credentials, and client_id of your application.  For example:
-<programlisting><![CDATA[
-    POST /auth/realms/demo/protocol/openid-connect/token
-    Content-Type: application/x-www-form-urlencoded
-
-    username=bburke&password=geheim&client_id=customer-portal&grant_type=password]]>
-</programlisting>
-        The response would be this <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3.3">standard JSON document</ulink> from the OAuth 2.0 specification.
-<programlisting><![CDATA[
-HTTP/1.1 200 OK
-Content-Type: application/json;charset=UTF-8
-Cache-Control: no-store
-Pragma: no-cache
-
-{
-    "access_token":"2YotnFZFEjr1zCsicMWpAA",
-    "token_type":"bearer",
-    "expires_in":3600,
-    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
-    "id_token":"tGzv3JOkF0XG5Qx2TlKWIA",
-    "session-state":"234234-234234-234234"
-}]]>
-</programlisting>
-    </para>
-    <para>
-        For confidential client's, you must create a Basic Auth <literal>Authorization</literal>
-        header that contains the client_id and client secret.  And pass in the form parameters for username and for
-        each user credential.  For example:
-<programlisting><![CDATA[
-    POST /auth/realms/demo/protocol/openid-connect/token
-    Authorization: Basic atasdf023l2312023
-    Content-Type: application/x-www-form-urlencoded
-
-    username=bburke&password=geheim&grant_type=password]]>
-</programlisting>
-
-    </para>
-    <para>
-        Here's a Java example using Apache HTTP Client and some Keycloak utility classes.:
-<programlisting><![CDATA[
-HttpClient client = new HttpClientBuilder()
-                .disableTrustManager().build();
-
-
-try {
-   HttpPost post = new HttpPost(
-           KeycloakUriBuilder.fromUri("http://localhost:8080/auth")
-           .path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
-   List <NameValuePair> formparams = new ArrayList <NameValuePair>();
-   formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "password"));
-   formparams.add(new BasicNameValuePair("username", "bburke"));
-   formparams.add(new BasicNameValuePair("password", "password"));
-
-   if (isPublic()) { // if client is public access type
-       formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
-   } else {
-       String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
-       post.setHeader("Authorization", authorization);
-   }
-   UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-   post.setEntity(form);
-
-   HttpResponse response = client.execute(post);
-   int status = response.getStatusLine().getStatusCode();
-   HttpEntity entity = response.getEntity();
-   if (status != 200) {
-      throw new IOException("Bad status: " + status);
-   }
-   if (entity == null) {
-      throw new IOException("No Entity");
-   }
-   InputStream is = entity.getContent();
-   try {
-      AccessTokenResponse tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
-   } finally {
-      try {
-          is.close();
-      } catch (IOException ignored) { }
-      }
-} finally {
-   client.getConnectionManager().shutdown();
-}
-]]>
-
-</programlisting>
-    </para>
-    <para>
-        Once you have the access token string, you can use it in REST HTTP bearer token authorized requests, i.e
-<programlisting>
-GET /my/rest/api
-Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
-</programlisting>
-    </para>
-    <para>
-        To logout you must use the refresh token contained in the AccessTokenResponse object.
-    </para>
-<programlisting>
-    <![CDATA[
-List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-if (isPublic()) { // if client is public access type
-    formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
-} else {
-    String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
-    post.setHeader("Authorization", authorization);
-}
-formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, tokenResponse.getRefreshToken()));
-HttpResponse response = null;
-URI logoutUri = KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
-                    .path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
-                    .build("demo");
-HttpPost post = new HttpPost(logoutUri);
-UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-post.setEntity(form);
-response = client.execute(post);
-int status = response.getStatusLine().getStatusCode();
-HttpEntity entity = response.getEntity();
-if (status != 204) {
-   error(status, entity);
-}
-if (entity == null) {
-   return;
-}
-InputStream is = entity.getContent();
-if (is != null) is.close();
-]]></programlisting>
+<chapter id="direct-access-grants">
+    <title>Direct Access Grants</title>
+    <para>
+        Keycloak allows you to make direct REST invocations to obtain an access token.
+        (See <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3">Resource Owner Password Credentials Grant</ulink>
+        from OAuth 2.0 spec).  To use it you must also have
+        registered a valid Client to use as the "client_id" for this grant request.
+    </para>
+    <warning>
+        <para>
+            It is highly recommended that you do not use Direct Access Grants to write your own login pages for your application.
+            You will lose a lot of features that Keycloak has if you do this.  Specifically all the account management, remember me,
+            lost password, account reset features of Keycloak.  Instead, if you want to tailor the look and feel of Keycloak login
+            pages, you should create your own <link linkend="themes">theme</link>. There are also security implications
+            to using Direct Access Grants compared to the redirect based flows as you are exposing plain text passwords
+            to applications directly.
+        </para>
+        <para>
+            It is even highly recommended that you use the browser to log in for native mobile applications!  Android
+            and iPhone applications allow you to redirect to and from the browser.  You can use this to redirect the user
+            from your native mobile app to the web browser to perform login, then the browser will redirect back to your
+            native application.
+        </para>
+    </warning>
+
+
+    <para>
+        The REST URL to invoke on is <literal>/{keycloak-root}/realms/{realm-name}/protocol/openid-connect/token</literal>.
+        Invoking on this URL is a POST request and requires you to post the username and credentials of the user you want
+        an access token for.  You must also pass along the "client_id" of the client you are creating
+        an access token for.  This "client_id" is the Client Id specified in admin console (not it's id from DB!).  Depending on
+        whether your client is <link linkend='access-types'>"public" or "confidential"</link>, you may also have to pass along
+        it's client secret as well. Finally you need to pass "grant_type" parameter with value "password" .
+    </para>
+    <para>
+        For public client's, the POST invocation requires form parameters that contain the username,
+        credentials, and client_id of your application.  For example:
+<programlisting><![CDATA[
+    POST /auth/realms/demo/protocol/openid-connect/token
+    Content-Type: application/x-www-form-urlencoded
+
+    username=bburke&password=geheim&client_id=customer-portal&grant_type=password]]>
+</programlisting>
+        The response would be this <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3.3">standard JSON document</ulink> from the OAuth 2.0 specification.
+<programlisting><![CDATA[
+HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+    "access_token":"2YotnFZFEjr1zCsicMWpAA",
+    "token_type":"bearer",
+    "expires_in":3600,
+    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
+    "id_token":"tGzv3JOkF0XG5Qx2TlKWIA",
+    "session-state":"234234-234234-234234"
+}]]>
+</programlisting>
+    </para>
+    <para>
+        For confidential client's, you must create a Basic Auth <literal>Authorization</literal>
+        header that contains the client_id and client secret.  And pass in the form parameters for username and for
+        each user credential.  For example:
+<programlisting><![CDATA[
+    POST /auth/realms/demo/protocol/openid-connect/token
+    Authorization: Basic atasdf023l2312023
+    Content-Type: application/x-www-form-urlencoded
+
+    username=bburke&password=geheim&grant_type=password]]>
+</programlisting>
+
+    </para>
+    <para>
+        Here's a Java example using Apache HTTP Client and some Keycloak utility classes.:
+<programlisting><![CDATA[
+HttpClient client = new HttpClientBuilder()
+                .disableTrustManager().build();
+
+
+try {
+   HttpPost post = new HttpPost(
+           KeycloakUriBuilder.fromUri("http://localhost:8080/auth")
+           .path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
+   List <NameValuePair> formparams = new ArrayList <NameValuePair>();
+   formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "password"));
+   formparams.add(new BasicNameValuePair("username", "bburke"));
+   formparams.add(new BasicNameValuePair("password", "password"));
+
+   if (isPublic()) { // if client is public access type
+       formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
+   } else {
+       String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
+       post.setHeader("Authorization", authorization);
+   }
+   UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+   post.setEntity(form);
+
+   HttpResponse response = client.execute(post);
+   int status = response.getStatusLine().getStatusCode();
+   HttpEntity entity = response.getEntity();
+   if (status != 200) {
+      throw new IOException("Bad status: " + status);
+   }
+   if (entity == null) {
+      throw new IOException("No Entity");
+   }
+   InputStream is = entity.getContent();
+   try {
+      AccessTokenResponse tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
+   } finally {
+      try {
+          is.close();
+      } catch (IOException ignored) { }
+      }
+} finally {
+   client.getConnectionManager().shutdown();
+}
+]]>
+
+</programlisting>
+    </para>
+    <para>
+        Once you have the access token string, you can use it in REST HTTP bearer token authorized requests, i.e
+<programlisting>
+GET /my/rest/api
+Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
+</programlisting>
+    </para>
+    <para>
+        To logout you must use the refresh token contained in the AccessTokenResponse object.
+    </para>
+<programlisting>
+    <![CDATA[
+List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+if (isPublic()) { // if client is public access type
+    formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
+} else {
+    String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
+    post.setHeader("Authorization", authorization);
+}
+formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, tokenResponse.getRefreshToken()));
+HttpResponse response = null;
+URI logoutUri = KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
+                    .path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
+                    .build("demo");
+HttpPost post = new HttpPost(logoutUri);
+UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+post.setEntity(form);
+response = client.execute(post);
+int status = response.getStatusLine().getStatusCode();
+HttpEntity entity = response.getEntity();
+if (status != 204) {
+   error(status, entity);
+}
+if (entity == null) {
+   return;
+}
+InputStream is = entity.getContent();
+if (is != null) is.close();
+]]></programlisting>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/events.xml b/docbook/reference/en/en-US/modules/events.xml
index 57cac03..bb25a28 100755
--- a/docbook/reference/en/en-US/modules/events.xml
+++ b/docbook/reference/en/en-US/modules/events.xml
@@ -1,103 +1,103 @@
-<chapter id="events">
-    <title>Events</title>
-    <para>
-        Keycloak provides an Events SPI that makes it possible to register listeners for user related events, for example
-        user logins. There are two interfaces that can be implemented, the first is a pure listener, the second is a events
-        store which listens for events, but is also required to store events. An events store provides a way for the admin
-        and account management consoles to view events.
-    </para>
-    <section>
-        <title>Event types</title>
-        <para>
-            Login events:
-            <itemizedlist>
-                <listitem>Login - A user has logged in</listitem>
-                <listitem>Register - A user has registered</listitem>
-                <listitem>Logout - A user has logged out</listitem>
-                <listitem>Code to Token - An application/client has exchanged a code for a token</listitem>
-                <listitem>Refresh Token - An application/client has refreshed a token</listitem>
-            </itemizedlist>
-        </para>
-        <para>
-            Account events:
-            <itemizedlist>
-                <listitem>Social Link - An account has been linked to a social provider</listitem>
-                <listitem>Remove Social Link - A social provider has been removed from an account</listitem>
-                <listitem>Update Email - The email address for an account has changed</listitem>
-                <listitem>Update Profile - The profile for an account has changed</listitem>
-                <listitem>Send Password Reset - A password reset email has been sent</listitem>
-                <listitem>Update Password - The password for an account has changed</listitem>
-                <listitem>Update TOTP - The TOTP settings for an account has changed</listitem>
-                <listitem>Remove TOTP - TOTP has been removed from an account</listitem>
-                <listitem>Send Verify Email - A email verification email has been sent</listitem>
-                <listitem>Verify Email - The email address for an account has been verified</listitem>
-            </itemizedlist>
-        </para>
-        <para>
-            For all events there is a corresponding error event.
-        </para>
-    </section>
-    <section>
-        <title>Event Listener</title>
-        <para>
-            Keycloak comes with an Email Event Listener and a JBoss Logging Event Listener. The Email Event Listener
-            sends an email to the users account when an event occurs. The JBoss Logging Event Listener writes to a log
-            file when an events occurs.
-        </para>
-        <para>
-            The Email Event Listener only supports the following events at the moment:
-            <itemizedlist>
-                <listitem>Login Error</listitem>
-                <listitem>Update Password</listitem>
-                <listitem>Update TOTP</listitem>
-                <listitem>Remove TOTP</listitem>
-            </itemizedlist>
-            You can exclude one or more events by editing <literal>standalone/configuration/keycloak-server.json</literal>
-            and adding for example:
-<programlisting><![CDATA[
-"eventListener": {
-    "email": {
-        "exclude-events": [ "UPDATE_TOTP", "REMOVE_TOTP" ]
-    }
-}
-]]></programlisting>
-        </para>
-    </section>
-
-    <section>
-        <title>Event Store</title>
-        <para>
-            Event Store listen for events and is expected to persist the events to make it possible to query for them
-            later. This is used by the admin console and account management to view events. Keycloak includes providers
-            to persist events to JPA and Mongo.
-        </para>
-        <para>
-            You can specify events to include or exclude by editing <literal>standalone/configuration/keycloak-server.json</literal>,
-        and adding for example:
-<programlisting><![CDATA[
-"eventsStore": {
-    "jpa": {
-        "exclude-events": [ "LOGIN", "REFRESH_TOKEN", "CODE_TO_TOKEN" ]
-    }
-}
-]]></programlisting>
-        </para>
-    </section>
-
-    <section>
-        <title>Configure Events Settings for Realm</title>
-        <para>
-            To enable persisting of events for a realm you first need to make sure you have a event store provider registered for Keycloak.
-            By default the JPA event store provider is registered. Once you've done that open the admin console, select the
-            realm you're configuring, select <literal>Events</literal>. Then click on <literal>Config</literal>.
-            You can enable storing events for your realm by toggling <literal>Save Events</literal> to ON. You can also set
-            an expiration on events. This will periodically delete events from the database that are older than the specified
-            time.
-        </para>
-        <para>
-            To configure listeners for a realm on the same page as above add one or more event listeners to the
-            <literal>Listeners</literal> select box. This will allow you to enable any registered event listeners with the
-            realm.
-        </para>
-    </section>
+<chapter id="events">
+    <title>Events</title>
+    <para>
+        Keycloak provides an Events SPI that makes it possible to register listeners for user related events, for example
+        user logins. There are two interfaces that can be implemented, the first is a pure listener, the second is a events
+        store which listens for events, but is also required to store events. An events store provides a way for the admin
+        and account management consoles to view events.
+    </para>
+    <section>
+        <title>Event types</title>
+        <para>
+            Login events:
+            <itemizedlist>
+                <listitem>Login - A user has logged in</listitem>
+                <listitem>Register - A user has registered</listitem>
+                <listitem>Logout - A user has logged out</listitem>
+                <listitem>Code to Token - An application/client has exchanged a code for a token</listitem>
+                <listitem>Refresh Token - An application/client has refreshed a token</listitem>
+            </itemizedlist>
+        </para>
+        <para>
+            Account events:
+            <itemizedlist>
+                <listitem>Social Link - An account has been linked to a social provider</listitem>
+                <listitem>Remove Social Link - A social provider has been removed from an account</listitem>
+                <listitem>Update Email - The email address for an account has changed</listitem>
+                <listitem>Update Profile - The profile for an account has changed</listitem>
+                <listitem>Send Password Reset - A password reset email has been sent</listitem>
+                <listitem>Update Password - The password for an account has changed</listitem>
+                <listitem>Update TOTP - The TOTP settings for an account has changed</listitem>
+                <listitem>Remove TOTP - TOTP has been removed from an account</listitem>
+                <listitem>Send Verify Email - A email verification email has been sent</listitem>
+                <listitem>Verify Email - The email address for an account has been verified</listitem>
+            </itemizedlist>
+        </para>
+        <para>
+            For all events there is a corresponding error event.
+        </para>
+    </section>
+    <section>
+        <title>Event Listener</title>
+        <para>
+            Keycloak comes with an Email Event Listener and a JBoss Logging Event Listener. The Email Event Listener
+            sends an email to the users account when an event occurs. The JBoss Logging Event Listener writes to a log
+            file when an events occurs.
+        </para>
+        <para>
+            The Email Event Listener only supports the following events at the moment:
+            <itemizedlist>
+                <listitem>Login Error</listitem>
+                <listitem>Update Password</listitem>
+                <listitem>Update TOTP</listitem>
+                <listitem>Remove TOTP</listitem>
+            </itemizedlist>
+            You can exclude one or more events by editing <literal>standalone/configuration/keycloak-server.json</literal>
+            and adding for example:
+<programlisting><![CDATA[
+"eventListener": {
+    "email": {
+        "exclude-events": [ "UPDATE_TOTP", "REMOVE_TOTP" ]
+    }
+}
+]]></programlisting>
+        </para>
+    </section>
+
+    <section>
+        <title>Event Store</title>
+        <para>
+            Event Store listen for events and is expected to persist the events to make it possible to query for them
+            later. This is used by the admin console and account management to view events. Keycloak includes providers
+            to persist events to JPA and Mongo.
+        </para>
+        <para>
+            You can specify events to include or exclude by editing <literal>standalone/configuration/keycloak-server.json</literal>,
+        and adding for example:
+<programlisting><![CDATA[
+"eventsStore": {
+    "jpa": {
+        "exclude-events": [ "LOGIN", "REFRESH_TOKEN", "CODE_TO_TOKEN" ]
+    }
+}
+]]></programlisting>
+        </para>
+    </section>
+
+    <section>
+        <title>Configure Events Settings for Realm</title>
+        <para>
+            To enable persisting of events for a realm you first need to make sure you have a event store provider registered for Keycloak.
+            By default the JPA event store provider is registered. Once you've done that open the admin console, select the
+            realm you're configuring, select <literal>Events</literal>. Then click on <literal>Config</literal>.
+            You can enable storing events for your realm by toggling <literal>Save Events</literal> to ON. You can also set
+            an expiration on events. This will periodically delete events from the database that are older than the specified
+            time.
+        </para>
+        <para>
+            To configure listeners for a realm on the same page as above add one or more event listeners to the
+            <literal>Listeners</literal> select box. This will allow you to enable any registered event listeners with the
+            realm.
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/installed-applications.xml b/docbook/reference/en/en-US/modules/installed-applications.xml
index e55e552..1650a03 100755
--- a/docbook/reference/en/en-US/modules/installed-applications.xml
+++ b/docbook/reference/en/en-US/modules/installed-applications.xml
@@ -1,25 +1,25 @@
-<section id="installed-applications">
-    <title>Installed Applications</title>
-    <para>
-        Keycloak provides two special redirect uris for installed applications.
-    </para>
-    <section id="installed-applications-url">
-        <title>http://localhost</title>
-        <para>
-            This returns the code to a web server on the client as a query parameter. Any port number is allowed.
-            This makes it possible to start a web server for the installed application on any free port number without
-            requiring changes in the <literal>Admin Console</literal>.
-        </para>
-    </section>
-    <section id="installed-applications-urn">
-        <title>urn:ietf:wg:oauth:2.0:oob</title>
-        <para>
-            If its not possible to start a web server in the client (or a browser is not available) it is possible to
-            use the special <literal>urn:ietf:wg:oauth:2.0:oob</literal> redirect uri. When this redirect uri is used
-            Keycloak displays a page with the code in the title and in a box on the page. The application can either
-            detect that the browser title has changed, or the user can copy/paste the code manually to the application.
-            With this redirect uri it is also possible for a user to use a different device to obtain a code to paste
-            back to the application.
-        </para>
-    </section>
+<section id="installed-applications">
+    <title>Installed Applications</title>
+    <para>
+        Keycloak provides two special redirect uris for installed applications.
+    </para>
+    <section id="installed-applications-url">
+        <title>http://localhost</title>
+        <para>
+            This returns the code to a web server on the client as a query parameter. Any port number is allowed.
+            This makes it possible to start a web server for the installed application on any free port number without
+            requiring changes in the <literal>Admin Console</literal>.
+        </para>
+    </section>
+    <section id="installed-applications-urn">
+        <title>urn:ietf:wg:oauth:2.0:oob</title>
+        <para>
+            If its not possible to start a web server in the client (or a browser is not available) it is possible to
+            use the special <literal>urn:ietf:wg:oauth:2.0:oob</literal> redirect uri. When this redirect uri is used
+            Keycloak displays a page with the code in the title and in a box on the page. The application can either
+            detect that the browser title has changed, or the user can copy/paste the code manually to the application.
+            With this redirect uri it is also possible for a user to use a different device to obtain a code to paste
+            back to the application.
+        </para>
+    </section>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/javascript-adapter.xml b/docbook/reference/en/en-US/modules/javascript-adapter.xml
index 30f8dd0..996f29a 100755
--- a/docbook/reference/en/en-US/modules/javascript-adapter.xml
+++ b/docbook/reference/en/en-US/modules/javascript-adapter.xml
@@ -1,346 +1,346 @@
-<section id="javascript-adapter">
-    <title>Javascript Adapter</title>
-    <para>
-        The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications.  This
-        library is referencable directly from the keycloak server.  You can also download the adapter from Keycloak's download
-        site if you want a static copy of this library.  It
-        works in the same way as other application adapters except that your browser is driving the OAuth redirect protocol
-        rather than the server.
-    </para>
-    <para>
-        The disadvantage of using this approach is that you have a non-confidential, public client. This makes it more
-        important that you register valid redirect URLs and make sure your domain name is secured.
-    </para>
-    <para>
-        To use this adapter, you must first configure an application (or client) through the <literal>Keycloak Admin Console</literal>.
-        You should select <literal>public</literal> for the <literal>Client Type</literal> field. As public clients can't
-        be verified with a client secret you are required to configure one or more valid redirect uris as well.
-        Once you've configured the application click on the <literal>Installation</literal> tab and download the <literal>keycloak.json</literal>
-        file. This file should be hosted in your web-server at the same root as your HTML pages. Alternatively you can either
-        specify the URL for this file, or manually configure the adapter.
-    </para>
-    <para>
-        Next you have to initialize the adapter in your application. An example on how to do this is shown below.
-<programlisting><![CDATA[
-<head>
-    <script src="http://<keycloak server>/auth/js/keycloak.js"></script>
-    <script>
-        var keycloak = Keycloak();
-        keycloak.init().success(function(authenticated) {
-            alert(authenticated ? 'authenticated' : 'not authenticated');
-        }).error(function() {
-            alert('failed to initialize');
-        });
-    </script>
-</head>
-]]></programlisting>
-        To specify the location of the keycloak.json file:
-<programlisting><![CDATA[
-var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'));
-]]></programlisting>
-        Or finally to manually configure the adapter:
-        <programlisting><![CDATA[
-var keycloak = Keycloak({
-    url: 'http://keycloak-server/auth',
-    realm: 'myrealm',
-    clientId: 'myapp'
-});
-]]></programlisting>
-        You can also pass <literal>login-required</literal> or <literal>check-sso</literal> to the init function. Login
-        required will redirect to the login form on the server, while check-sso will redirect to the auth server to check
-        if the user is already logged in to the realm. For example:
-<programlisting><![CDATA[
-keycloak.init({ onLoad: 'login-required' })
-]]></programlisting>
-    </para>
-
-    <para>
-        After you login, your application will be able to make REST calls using bearer token authentication.  Here's
-        an example pulled from the <literal>customer-portal-js</literal> example that comes with the distribution.
-<programlisting><![CDATA[
-<script>
-    var loadData = function () {
-        document.getElementById('username').innerText = keycloak.username;
-
-        var url = 'http://localhost:8080/database/customers';
-
-        var req = new XMLHttpRequest();
-        req.open('GET', url, true);
-        req.setRequestHeader('Accept', 'application/json');
-        req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
-
-        req.onreadystatechange = function () {
-            if (req.readyState == 4) {
-                if (req.status == 200) {
-                    var users = JSON.parse(req.responseText);
-                    var html = '';
-                    for (var i = 0; i < users.length; i++) {
-                        html += '<p>' + users[i] + '</p>';
-                    }
-                    document.getElementById('customers').innerHTML = html;
-                    console.log('finished loading data');
-                }
-            }
-        }
-
-        req.send();
-    };
-
-    var loadFailure = function () {
-        document.getElementById('customers').innerHTML = '<b>Failed to load data.  Check console log</b>';
-
-    };
-
-    var reloadData = function () {
-        keycloak.updateToken().success(loadData).error(loadFailure);
-    }
-</script>
-
-<button onclick="loadData()">Submit</button>
-]]></programlisting>
-     </para>
-    <para>
-        The <literal>loadData()</literal> method builds an HTTP request setting the <literal>Authorization</literal>
-        header to a bearer token.  The <literal>keycloak.token</literal> points to the access token the browser obtained
-        when it logged you in.  The <literal>loadFailure()</literal> method is invoked on a failure.  The <literal>reloadData()</literal>
-        function calls <literal>keycloak.onValidAccessToken()</literal> passing in the <literal>loadData()</literal> and
-        <literal>loadFailure()</literal> callbacks.  The <literal>keycloak.onValidAcessToken()</literal> method checks to
-        see if the access token hasn't expired.  If it hasn't, and your oauth login returned a refresh token, this method
-        will refresh the access token.  Finally, if successful, it will invoke the success callback, which in this case
-        is the <literal>loadData()</literal> method.
-    </para>
-
-    <para>
-        To refresh the token if it's expired call the <literal>updateToken</literal> method. This method returns a promise
-        object which can be used to invoke a function on success or failure. This method can be used to wrap functions
-        that should only be called with a valid token. For example the following method will refresh the token if it
-        expires within 30 seconds, and then invoke the specified function. If the token is valid for more than 30 seconds it
-        will just call the specified function.
-<programlisting><![CDATA[
-keycloak.updateToken(30).success(function() {
-    // send request with valid token
-}).error(function() {
-    alert('failed to refresh token');
-);
-]]></programlisting>
-    </para>
-
-    <section>
-        <title>Session status iframe</title>
-
-        <para>
-            By default the JavaScript adapter creates a non-visible iframe that is used to detect if a single-sign out has occured.
-            This does not require any network traffic, instead the status is retrieved from a special status cookie. This feature can be disabled
-            by setting <literal>checkLoginIframe: false</literal> in the options passed to the <literal>init</literal>
-            method.
-        </para>
-    </section>
-
-    <section>
-        <title>Older browsers</title>
-
-        <para>
-            The JavaScript adapter depends on Base64 (window.btoa and window.atob) and HTML5 History API. If you need to
-            support browsers that don't provide those (for example IE9) you'll need to add polyfillers. Example polyfill
-            libraries:
-
-            <itemizedlist>
-                <listitem>Base64 - <ulink url="https://github.com/davidchambers/Base64.js">https://github.com/davidchambers/Base64.js</ulink></listitem>
-                <listitem>HTML5 History - <ulink url="https://github.com/devote/HTML5-History-API">https://github.com/devote/HTML5-History-API</ulink></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section>
-        <title>JavaScript Adapter reference</title>
-
-        <section>
-            <title>Constructor</title>
-<programlisting><![CDATA[
-new Keycloak();
-new Keycloak('http://localhost/keycloak.json');
-new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp' });
-]]></programlisting>
-        </section>
-
-        <section>
-            <title>Properties</title>
-
-            <itemizedlist>
-                <listitem>authenticated - true if the user is authenticated</listitem>
-                <listitem>token - the base64 encoded token that can be sent in the <literal>Authorization</literal> header in requests to services</listitem>
-                <listitem>tokenParsed - the parsed token</listitem>
-                <listitem>subject - the user id</listitem>
-                <listitem>idToken - the id token if claims is enabled for the application, null otherwise</listitem>
-                <listitem>idTokenParsed - the parsed id token</listitem>
-                <listitem>realmAccess - the realm roles associated with the token</listitem>
-                <listitem>resourceAccess - the resource roles assocaited with the token</listitem>
-                <listitem>refreshToken - the base64 encoded token that can be used to retrieve a new token</listitem>
-                <listitem>refreshTokenParsed - the parsed refresh token</listitem>
-            </itemizedlist>
-        </section>
-
-        <section>
-            <title>Methods</title>
-
-            <simplesect>
-                <title>init(options)</title>
-
-                <para>Called to initialize the adapter.</para>
-                <para>Options is an Object, where:
-                    <itemizedlist>
-                        <listitem>onLoad - specifies an action to do on load, can be either 'login-required' or 'check-sso'</listitem>
-                        <listitem>token - set an initial value for the token</listitem>
-                        <listitem>refreshToken - set an initial value for the refresh token</listitem>
-                        <listitem>checkLoginIframe - set to enable/disable monitoring login state (default is true)</listitem>
-                        <listitem>checkLoginIframeInterval - set the interval to check login state (default is 5 seconds)</listitem>
-                    </itemizedlist>
-                </para>
-                <para>Returns promise to set functions to be invoked on success or error.</para>
-            </simplesect>
-
-            <simplesect>
-                <title>login(options)</title>
-
-                <para>Redirects to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
-                <para>Options is an Object, where:
-                    <itemizedlist>
-                        <listitem>redirectUri - specifies the uri to redirect to after login</listitem>
-                        <listitem>prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)</listitem>
-                        <listitem>loginHint - used to pre-fill the username/email field on the login form</listitem>
-                    </itemizedlist>
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>createLoginUrl(options)</title>
-
-                <para>Returns the url to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
-                <para>Options is an Object, where:
-                    <itemizedlist>
-                        <listitem>redirectUri - specifies the uri to redirect to after login</listitem>
-                        <listitem>prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)</listitem>
-                    </itemizedlist>
-                </para>
-            </simplesect>
-
-            <simplesect>
-                <title>logout(options)</title>
-
-                <para>Redirects to logout</para>
-                <para>Options is an Object, where:
-                    <itemizedlist>
-                        <listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
-                    </itemizedlist>
-                </para>
-            </simplesect>
-
-            <simplesect>
-                <title>createLogoutUrl(options)</title>
-
-                <para>Returns logout out</para>
-                <para>Options is an Object, where:
-                    <itemizedlist>
-                        <listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
-                    </itemizedlist>
-                </para>
-            </simplesect>
-
-            <simplesect>
-                <title>accountManagement()</title>
-
-                <para>Redirects to account management</para>
-            </simplesect>
-
-            <simplesect>
-                <title>createAccountUrl()</title>
-
-                <para>Returns the url to account management</para>
-            </simplesect>
-
-            <simplesect>
-                <title>hasRealmRole(role)</title>
-
-                <para>Returns true if the token has the given realm role</para>
-            </simplesect>
-
-            <simplesect>
-                <title>hasResourceRole(role, resource)</title>
-
-                <para>Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used)</para>
-            </simplesect>
-
-            <simplesect>
-                <title>loadUserProfile()</title>
-
-                <para>Loads the users profile</para>
-
-                <para>Returns promise to set functions to be invoked on success or error.</para>
-            </simplesect>
-
-            <simplesect>
-                <title>isTokenExpired(minValidity)</title>
-
-                <para>Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used)</para>
-            </simplesect>
-
-            <simplesect>
-                <title>updateToken(minValidity)</title>
-
-                <para>If the token expires within minValidity seconds (minValidity is optional, if not specified 0 is used) the token is refreshed.
-                    If the session status iframe is enabled, the session status is also checked.
-                </para>
-
-                <para>Returns promise to set functions that can be invoked if the token is still valid, or if the token is no longer valid. For example:</para>
-
-                <programlisting><![CDATA[
-keycloak.updateToken(5).success(function(refreshed) {
-        if (refreshed) {
-            alert('token was successfully refreshed');
-        } else {
-            alert('token is still valid');
-        }
-    }).error(function() {
-        alert('failed to refresh the token, or the session has expired');
-    });
-]]></programlisting>
-
-            </simplesect>
-
-            <simplesect>
-                <title>clearToken()</title>
-
-                <para>
-                    Clear authentication state, including tokens. This can be useful if application has detected the session
-                    has expired, for example if updating token fails. Invoking this results in onAuthLogout callback listener
-                    being invoked.
-                </para>
-
-                <programlisting><![CDATA[
-keycloak.updateToken(5).error(function() {
-    keycloak.clearToken();
-});
-]]></programlisting>
-
-            </simplesect>
-        </section>
-
-        <section>
-            <title>Callback Events</title>
-
-            <para>The adapter supports setting callback listeners for certain events. For example:
-<programlisting><![CDATA[
-keycloak.onAuthSuccess = function() { alert('authenticated'); }
-]]></programlisting>
-            </para>
-
-            <itemizedlist>
-                <listitem>onReady(authenticated) - called when the adapter is initialized</listitem>
-                <listitem>onAuthSuccess - called when a user is successfully authenticated</listitem>
-                <listitem>onAuthError - called if there was an error during authentication</listitem>
-                <listitem>onAuthRefreshSuccess - called when the token is refreshed</listitem>
-                <listitem>onAuthRefreshError - called if there was an error while trying to refresh the token</listitem>
-                <listitem>onAuthLogout - called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode)</listitem>
-            </itemizedlist>
-        </section>
-    </section>
+<section id="javascript-adapter">
+    <title>Javascript Adapter</title>
+    <para>
+        The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications.  This
+        library is referencable directly from the keycloak server.  You can also download the adapter from Keycloak's download
+        site if you want a static copy of this library.  It
+        works in the same way as other application adapters except that your browser is driving the OAuth redirect protocol
+        rather than the server.
+    </para>
+    <para>
+        The disadvantage of using this approach is that you have a non-confidential, public client. This makes it more
+        important that you register valid redirect URLs and make sure your domain name is secured.
+    </para>
+    <para>
+        To use this adapter, you must first configure an application (or client) through the <literal>Keycloak Admin Console</literal>.
+        You should select <literal>public</literal> for the <literal>Client Type</literal> field. As public clients can't
+        be verified with a client secret you are required to configure one or more valid redirect uris as well.
+        Once you've configured the application click on the <literal>Installation</literal> tab and download the <literal>keycloak.json</literal>
+        file. This file should be hosted in your web-server at the same root as your HTML pages. Alternatively you can either
+        specify the URL for this file, or manually configure the adapter.
+    </para>
+    <para>
+        Next you have to initialize the adapter in your application. An example on how to do this is shown below.
+<programlisting><![CDATA[
+<head>
+    <script src="http://<keycloak server>/auth/js/keycloak.js"></script>
+    <script>
+        var keycloak = Keycloak();
+        keycloak.init().success(function(authenticated) {
+            alert(authenticated ? 'authenticated' : 'not authenticated');
+        }).error(function() {
+            alert('failed to initialize');
+        });
+    </script>
+</head>
+]]></programlisting>
+        To specify the location of the keycloak.json file:
+<programlisting><![CDATA[
+var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'));
+]]></programlisting>
+        Or finally to manually configure the adapter:
+        <programlisting><![CDATA[
+var keycloak = Keycloak({
+    url: 'http://keycloak-server/auth',
+    realm: 'myrealm',
+    clientId: 'myapp'
+});
+]]></programlisting>
+        You can also pass <literal>login-required</literal> or <literal>check-sso</literal> to the init function. Login
+        required will redirect to the login form on the server, while check-sso will redirect to the auth server to check
+        if the user is already logged in to the realm. For example:
+<programlisting><![CDATA[
+keycloak.init({ onLoad: 'login-required' })
+]]></programlisting>
+    </para>
+
+    <para>
+        After you login, your application will be able to make REST calls using bearer token authentication.  Here's
+        an example pulled from the <literal>customer-portal-js</literal> example that comes with the distribution.
+<programlisting><![CDATA[
+<script>
+    var loadData = function () {
+        document.getElementById('username').innerText = keycloak.username;
+
+        var url = 'http://localhost:8080/database/customers';
+
+        var req = new XMLHttpRequest();
+        req.open('GET', url, true);
+        req.setRequestHeader('Accept', 'application/json');
+        req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
+
+        req.onreadystatechange = function () {
+            if (req.readyState == 4) {
+                if (req.status == 200) {
+                    var users = JSON.parse(req.responseText);
+                    var html = '';
+                    for (var i = 0; i < users.length; i++) {
+                        html += '<p>' + users[i] + '</p>';
+                    }
+                    document.getElementById('customers').innerHTML = html;
+                    console.log('finished loading data');
+                }
+            }
+        }
+
+        req.send();
+    };
+
+    var loadFailure = function () {
+        document.getElementById('customers').innerHTML = '<b>Failed to load data.  Check console log</b>';
+
+    };
+
+    var reloadData = function () {
+        keycloak.updateToken().success(loadData).error(loadFailure);
+    }
+</script>
+
+<button onclick="loadData()">Submit</button>
+]]></programlisting>
+     </para>
+    <para>
+        The <literal>loadData()</literal> method builds an HTTP request setting the <literal>Authorization</literal>
+        header to a bearer token.  The <literal>keycloak.token</literal> points to the access token the browser obtained
+        when it logged you in.  The <literal>loadFailure()</literal> method is invoked on a failure.  The <literal>reloadData()</literal>
+        function calls <literal>keycloak.onValidAccessToken()</literal> passing in the <literal>loadData()</literal> and
+        <literal>loadFailure()</literal> callbacks.  The <literal>keycloak.onValidAcessToken()</literal> method checks to
+        see if the access token hasn't expired.  If it hasn't, and your oauth login returned a refresh token, this method
+        will refresh the access token.  Finally, if successful, it will invoke the success callback, which in this case
+        is the <literal>loadData()</literal> method.
+    </para>
+
+    <para>
+        To refresh the token if it's expired call the <literal>updateToken</literal> method. This method returns a promise
+        object which can be used to invoke a function on success or failure. This method can be used to wrap functions
+        that should only be called with a valid token. For example the following method will refresh the token if it
+        expires within 30 seconds, and then invoke the specified function. If the token is valid for more than 30 seconds it
+        will just call the specified function.
+<programlisting><![CDATA[
+keycloak.updateToken(30).success(function() {
+    // send request with valid token
+}).error(function() {
+    alert('failed to refresh token');
+);
+]]></programlisting>
+    </para>
+
+    <section>
+        <title>Session status iframe</title>
+
+        <para>
+            By default the JavaScript adapter creates a non-visible iframe that is used to detect if a single-sign out has occured.
+            This does not require any network traffic, instead the status is retrieved from a special status cookie. This feature can be disabled
+            by setting <literal>checkLoginIframe: false</literal> in the options passed to the <literal>init</literal>
+            method.
+        </para>
+    </section>
+
+    <section>
+        <title>Older browsers</title>
+
+        <para>
+            The JavaScript adapter depends on Base64 (window.btoa and window.atob) and HTML5 History API. If you need to
+            support browsers that don't provide those (for example IE9) you'll need to add polyfillers. Example polyfill
+            libraries:
+
+            <itemizedlist>
+                <listitem>Base64 - <ulink url="https://github.com/davidchambers/Base64.js">https://github.com/davidchambers/Base64.js</ulink></listitem>
+                <listitem>HTML5 History - <ulink url="https://github.com/devote/HTML5-History-API">https://github.com/devote/HTML5-History-API</ulink></listitem>
+            </itemizedlist>
+        </para>
+    </section>
+
+    <section>
+        <title>JavaScript Adapter reference</title>
+
+        <section>
+            <title>Constructor</title>
+<programlisting><![CDATA[
+new Keycloak();
+new Keycloak('http://localhost/keycloak.json');
+new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp' });
+]]></programlisting>
+        </section>
+
+        <section>
+            <title>Properties</title>
+
+            <itemizedlist>
+                <listitem>authenticated - true if the user is authenticated</listitem>
+                <listitem>token - the base64 encoded token that can be sent in the <literal>Authorization</literal> header in requests to services</listitem>
+                <listitem>tokenParsed - the parsed token</listitem>
+                <listitem>subject - the user id</listitem>
+                <listitem>idToken - the id token if claims is enabled for the application, null otherwise</listitem>
+                <listitem>idTokenParsed - the parsed id token</listitem>
+                <listitem>realmAccess - the realm roles associated with the token</listitem>
+                <listitem>resourceAccess - the resource roles assocaited with the token</listitem>
+                <listitem>refreshToken - the base64 encoded token that can be used to retrieve a new token</listitem>
+                <listitem>refreshTokenParsed - the parsed refresh token</listitem>
+            </itemizedlist>
+        </section>
+
+        <section>
+            <title>Methods</title>
+
+            <simplesect>
+                <title>init(options)</title>
+
+                <para>Called to initialize the adapter.</para>
+                <para>Options is an Object, where:
+                    <itemizedlist>
+                        <listitem>onLoad - specifies an action to do on load, can be either 'login-required' or 'check-sso'</listitem>
+                        <listitem>token - set an initial value for the token</listitem>
+                        <listitem>refreshToken - set an initial value for the refresh token</listitem>
+                        <listitem>checkLoginIframe - set to enable/disable monitoring login state (default is true)</listitem>
+                        <listitem>checkLoginIframeInterval - set the interval to check login state (default is 5 seconds)</listitem>
+                    </itemizedlist>
+                </para>
+                <para>Returns promise to set functions to be invoked on success or error.</para>
+            </simplesect>
+
+            <simplesect>
+                <title>login(options)</title>
+
+                <para>Redirects to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
+                <para>Options is an Object, where:
+                    <itemizedlist>
+                        <listitem>redirectUri - specifies the uri to redirect to after login</listitem>
+                        <listitem>prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)</listitem>
+                        <listitem>loginHint - used to pre-fill the username/email field on the login form</listitem>
+                    </itemizedlist>
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>createLoginUrl(options)</title>
+
+                <para>Returns the url to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
+                <para>Options is an Object, where:
+                    <itemizedlist>
+                        <listitem>redirectUri - specifies the uri to redirect to after login</listitem>
+                        <listitem>prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)</listitem>
+                    </itemizedlist>
+                </para>
+            </simplesect>
+
+            <simplesect>
+                <title>logout(options)</title>
+
+                <para>Redirects to logout</para>
+                <para>Options is an Object, where:
+                    <itemizedlist>
+                        <listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
+                    </itemizedlist>
+                </para>
+            </simplesect>
+
+            <simplesect>
+                <title>createLogoutUrl(options)</title>
+
+                <para>Returns logout out</para>
+                <para>Options is an Object, where:
+                    <itemizedlist>
+                        <listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
+                    </itemizedlist>
+                </para>
+            </simplesect>
+
+            <simplesect>
+                <title>accountManagement()</title>
+
+                <para>Redirects to account management</para>
+            </simplesect>
+
+            <simplesect>
+                <title>createAccountUrl()</title>
+
+                <para>Returns the url to account management</para>
+            </simplesect>
+
+            <simplesect>
+                <title>hasRealmRole(role)</title>
+
+                <para>Returns true if the token has the given realm role</para>
+            </simplesect>
+
+            <simplesect>
+                <title>hasResourceRole(role, resource)</title>
+
+                <para>Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used)</para>
+            </simplesect>
+
+            <simplesect>
+                <title>loadUserProfile()</title>
+
+                <para>Loads the users profile</para>
+
+                <para>Returns promise to set functions to be invoked on success or error.</para>
+            </simplesect>
+
+            <simplesect>
+                <title>isTokenExpired(minValidity)</title>
+
+                <para>Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used)</para>
+            </simplesect>
+
+            <simplesect>
+                <title>updateToken(minValidity)</title>
+
+                <para>If the token expires within minValidity seconds (minValidity is optional, if not specified 0 is used) the token is refreshed.
+                    If the session status iframe is enabled, the session status is also checked.
+                </para>
+
+                <para>Returns promise to set functions that can be invoked if the token is still valid, or if the token is no longer valid. For example:</para>
+
+                <programlisting><![CDATA[
+keycloak.updateToken(5).success(function(refreshed) {
+        if (refreshed) {
+            alert('token was successfully refreshed');
+        } else {
+            alert('token is still valid');
+        }
+    }).error(function() {
+        alert('failed to refresh the token, or the session has expired');
+    });
+]]></programlisting>
+
+            </simplesect>
+
+            <simplesect>
+                <title>clearToken()</title>
+
+                <para>
+                    Clear authentication state, including tokens. This can be useful if application has detected the session
+                    has expired, for example if updating token fails. Invoking this results in onAuthLogout callback listener
+                    being invoked.
+                </para>
+
+                <programlisting><![CDATA[
+keycloak.updateToken(5).error(function() {
+    keycloak.clearToken();
+});
+]]></programlisting>
+
+            </simplesect>
+        </section>
+
+        <section>
+            <title>Callback Events</title>
+
+            <para>The adapter supports setting callback listeners for certain events. For example:
+<programlisting><![CDATA[
+keycloak.onAuthSuccess = function() { alert('authenticated'); }
+]]></programlisting>
+            </para>
+
+            <itemizedlist>
+                <listitem>onReady(authenticated) - called when the adapter is initialized</listitem>
+                <listitem>onAuthSuccess - called when a user is successfully authenticated</listitem>
+                <listitem>onAuthError - called if there was an error during authentication</listitem>
+                <listitem>onAuthRefreshSuccess - called when the token is refreshed</listitem>
+                <listitem>onAuthRefreshError - called if there was an error while trying to refresh the token</listitem>
+                <listitem>onAuthLogout - called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode)</listitem>
+            </itemizedlist>
+        </section>
+    </section>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/jboss-adapter.xml b/docbook/reference/en/en-US/modules/jboss-adapter.xml
index 08949b4..52877de 100755
--- a/docbook/reference/en/en-US/modules/jboss-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jboss-adapter.xml
@@ -1,274 +1,274 @@
-<section id="jboss-adapter">
-    <title>JBoss/Wildfly Adapter</title>
-    <para>
-        To be able to secure WAR apps deployed on JBoss AS 7.1.1, JBoss EAP 6.x, or Wildfly, you must install and
-        configure the Keycloak Subsystem.  You then have two options to secure your WARs.  You can provide a keycloak
-        config file in your WAR and change the auth-method to KEYCLOAK within web.xml.  Alternatively, you don't have
-        to crack open your WARs at all and can apply Keycloak via the Keycloak Subsystem configuration in standalone.xml.
-        Both methods are described in this section.
-    </para>
-    <section id="jboss-adapter-installation">
-        <title>Adapter Installation</title>
-    <para>
-        Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
-        the Keycloak download site.  They are also available as a maven artifact.
-    </para>
-    <para>
-        Install on Wildfly 9:
-<programlisting>
-$ cd $WILDFLY_HOME
-$ unzip keycloak-wf9-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        Install on Wildfly 8:
-<programlisting>
-$ cd $WILDFLY_HOME
-$ unzip keycloak-wf8-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        Install on JBoss EAP 6.x:
-<programlisting>
-$ cd $JBOSS_HOME
-$ unzip keycloak-eap6-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        Install on JBoss AS 7.1.1:
-<programlisting>
-$ cd $JBOSS_HOME
-$ unzip keycloak-as7-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro.
-    </para>
-    <para>
-        After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration:
-        <literal>domain.xml</literal> or <literal>standalone.xml</literal>.
-    </para>
-    <para>
-<programlisting><![CDATA[
-<server xmlns="urn:jboss:domain:1.4">
-
-    <extensions>
-        <extension module="org.keycloak.keycloak-adapter-subsystem"/>
-          ...
-    </extensions>
-
-    <profile>
-        <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
-         ...
-    </profile>
-]]>
-</programlisting>
-    </para>
-        <para>
-            Finally, you must specify a shared keycloak security domain.
-            This security domain should be used with EJBs and other components when you need the security context created
-            in the secured web tier to be propagated to the EJBs (other EE component) you are invoking.  Otherwise
-            this configuration is optional.
-        </para>
-<programlisting><![CDATA[
-<server xmlns="urn:jboss:domain:1.4">
- <subsystem xmlns="urn:jboss:domain:security:1.2">
-    <security-domains>
-...
-      <security-domain name="keycloak">
-         <authentication>
-           <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
-                         flag="required"/>
-          </authentication>
-      </security-domain>
-    </security-domains>
-]]>
-</programlisting>
-        <para>
-            For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want
-            to annotate it with the @SecurityDomain annotation as follows:
-        </para>
-<programlisting><![CDATA[
-import org.jboss.ejb3.annotation.SecurityDomain;
-import org.jboss.resteasy.annotations.cache.NoCache;
-
-import javax.annotation.security.RolesAllowed;
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import java.util.ArrayList;
-import java.util.List;
-
-@Path("customers")
-@Stateless
-@SecurityDomain("keycloak")
-public class CustomerService {
-
-    @EJB
-    CustomerDB db;
-
-    @GET
-    @Produces("application/json")
-    @NoCache
-    @RolesAllowed("db_user")
-    public List<String> getCustomers() {
-        return db.getCustomers();
-    }
-}
-]]>
-</programlisting>
-        <para>
-            We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain
-            annotation when you want to propagate a keycloak security context to the EJB tier.
-        </para>
-
-    </section>
-    <section>
-        <title>Required Per WAR Configuration</title>
-        <para>
-            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
-        </para>
-        <para>
-            The first thing you must do is create
-            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
-            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
-            section.
-        </para>
-        <para>
-            Next you must set the <literal>auth-method</literal> to <literal>KEYCLOAK</literal> in <literal>web.xml</literal>.  You also
-            have to use standard servlet security to specify role-base constraints on your URLs.  Here's an example
-            pulled from one of the examples that comes distributed with Keycloak.
-        </para>
-        <para>
-<programlisting>
-<![CDATA[
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-      version="3.0">
-
-	<module-name>customer-portal</module-name>
-
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Admins</web-resource-name>
-            <url-pattern>/admin/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>admin</role-name>
-        </auth-constraint>
-    </security-constraint>
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Customers</web-resource-name>
-            <url-pattern>/customers/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>user</role-name>
-        </auth-constraint>
-    </security-constraint>
-
-    <security-constraint>
-        <web-resource-collection>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <user-data-constraint>
-            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
-        </user-data-constraint>
-    </security-constraint>
-
-    <login-config>
-        <auth-method>KEYCLOAK</auth-method>
-        <realm-name>this is ignored currently/realm-name>
-    </login-config>
-
-    <security-role>
-        <role-name>admin</role-name>
-    </security-role>
-    <security-role>
-        <role-name>user</role-name>
-    </security-role>
-</web-app>
-]]>
-</programlisting>
-        </para>
-    </section>
-    <section>
-        <title>Securing WARs via Keycloak Subsystem</title>
-        <para>
-            You do not have to crack open a WAR to secure it with Keycloak.  Alternatively, you can externally secure
-            it via the Keycloak Adapter Subsystem.  While you don't have to specify KEYCLOAK as an <literal>auth-method</literal>,
-            you still have to define the <literal>security-constraints</literal> in <literal>web.xml</literal>.  You do
-            not, however, have to create a <literal>WEB-INF/keycloak.json</literal> file.  This metadata is instead defined
-            within XML in your server's <literal>domain.xml</literal> or <literal>standalone.xml</literal> subsystem
-            configuration section.
-        </para>
-<para>
-<programlisting><![CDATA[
-<extensions>
-  <extension module="org.keycloak.keycloak-adapter-subsystem"/>
-</extensions>
-
-<profile>
-  <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
-     <secure-deployment name="WAR MODULE NAME.war">
-        <realm>demo</realm>
-        <realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA</realm-public-key>
-        <auth-server-url>http://localhost:8081/auth</auth-server-url>
-        <ssl-required>external</ssl-required>
-        <resource>customer-portal</resource>
-        <credential name="secret">password</credential>
-     </secure-deployment>
-  </subsystem>
-</profile>
-]]>
-</programlisting>
-</para>
-        <para>
-            The <literal>security-deployment</literal> <literal>name</literal> attribute identifies the WAR you want
-            to secure.  Its value is the <literal>module-name</literal> defined in <literal>web.xml</literal> with
-            <literal>.war</literal> appended.  The rest of the configuration corresponds pretty much one to one
-            with the <literal>keycloak.json</literal> configuration options defined in <link linkend='adapter-config'>general adapter configuration</link>.
-            The exception is the <literal>credential</literal> element.
-        </para>
-        <para>
-            To make it easier for you, you can go to the Keycloak Adminstration Console and go to the Application/Installation
-            tab of the application this WAR is aligned with.  It provides an example XML file you can cut and paste.
-        </para>
-        <para>
-            There is an additional convenience format for this XML if you have multiple WARs you are deployment that
-            are secured by the same domain.  This format allows you to define common configuration items in one place
-            under the <literal>realm</literal> element.
-        </para>
-        <para>
-            <programlisting><![CDATA[
-<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
-    <realm name="demo">
-        <realm-public-key>MIGfMA0GCSqGSIb3DQEBA</realm-public-key>
-        <auth-server-url>http://localhost:8080/auth</auth-server-url>
-        <ssl-required>external</ssl-required>
-    </realm>
-    <secure-deployment name="customer-portal.war">
-        <realm>demo</realm>
-        <resource>customer-portal</resource>
-        <credential name="secret">password</credential>
-    </secure-deployment>
-    <secure-deployment name="product-portal.war">
-        <realm>demo</realm>
-        <resource>product-portal</resource>
-        <credential name="secret">password</credential>
-    </secure-deployment>
-    <secure-deployment name="database.war">
-        <realm>demo</realm>
-        <resource>database-service</resource>
-        <bearer-only>true</bearer-only>
-    </secure-deployment>
-</subsystem>
-]]>
-            </programlisting>
-        </para>
-    </section>
-
+<section id="jboss-adapter">
+    <title>JBoss/Wildfly Adapter</title>
+    <para>
+        To be able to secure WAR apps deployed on JBoss AS 7.1.1, JBoss EAP 6.x, or Wildfly, you must install and
+        configure the Keycloak Subsystem.  You then have two options to secure your WARs.  You can provide a keycloak
+        config file in your WAR and change the auth-method to KEYCLOAK within web.xml.  Alternatively, you don't have
+        to crack open your WARs at all and can apply Keycloak via the Keycloak Subsystem configuration in standalone.xml.
+        Both methods are described in this section.
+    </para>
+    <section id="jboss-adapter-installation">
+        <title>Adapter Installation</title>
+    <para>
+        Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
+        the Keycloak download site.  They are also available as a maven artifact.
+    </para>
+    <para>
+        Install on Wildfly 9:
+<programlisting>
+$ cd $WILDFLY_HOME
+$ unzip keycloak-wf9-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        Install on Wildfly 8:
+<programlisting>
+$ cd $WILDFLY_HOME
+$ unzip keycloak-wf8-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        Install on JBoss EAP 6.x:
+<programlisting>
+$ cd $JBOSS_HOME
+$ unzip keycloak-eap6-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        Install on JBoss AS 7.1.1:
+<programlisting>
+$ cd $JBOSS_HOME
+$ unzip keycloak-as7-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro.
+    </para>
+    <para>
+        After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration:
+        <literal>domain.xml</literal> or <literal>standalone.xml</literal>.
+    </para>
+    <para>
+<programlisting><![CDATA[
+<server xmlns="urn:jboss:domain:1.4">
+
+    <extensions>
+        <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+          ...
+    </extensions>
+
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
+         ...
+    </profile>
+]]>
+</programlisting>
+    </para>
+        <para>
+            Finally, you must specify a shared keycloak security domain.
+            This security domain should be used with EJBs and other components when you need the security context created
+            in the secured web tier to be propagated to the EJBs (other EE component) you are invoking.  Otherwise
+            this configuration is optional.
+        </para>
+<programlisting><![CDATA[
+<server xmlns="urn:jboss:domain:1.4">
+ <subsystem xmlns="urn:jboss:domain:security:1.2">
+    <security-domains>
+...
+      <security-domain name="keycloak">
+         <authentication>
+           <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
+                         flag="required"/>
+          </authentication>
+      </security-domain>
+    </security-domains>
+]]>
+</programlisting>
+        <para>
+            For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want
+            to annotate it with the @SecurityDomain annotation as follows:
+        </para>
+<programlisting><![CDATA[
+import org.jboss.ejb3.annotation.SecurityDomain;
+import org.jboss.resteasy.annotations.cache.NoCache;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.util.ArrayList;
+import java.util.List;
+
+@Path("customers")
+@Stateless
+@SecurityDomain("keycloak")
+public class CustomerService {
+
+    @EJB
+    CustomerDB db;
+
+    @GET
+    @Produces("application/json")
+    @NoCache
+    @RolesAllowed("db_user")
+    public List<String> getCustomers() {
+        return db.getCustomers();
+    }
+}
+]]>
+</programlisting>
+        <para>
+            We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain
+            annotation when you want to propagate a keycloak security context to the EJB tier.
+        </para>
+
+    </section>
+    <section>
+        <title>Required Per WAR Configuration</title>
+        <para>
+            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
+        </para>
+        <para>
+            The first thing you must do is create
+            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
+            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
+            section.
+        </para>
+        <para>
+            Next you must set the <literal>auth-method</literal> to <literal>KEYCLOAK</literal> in <literal>web.xml</literal>.  You also
+            have to use standard servlet security to specify role-base constraints on your URLs.  Here's an example
+            pulled from one of the examples that comes distributed with Keycloak.
+        </para>
+        <para>
+<programlisting>
+<![CDATA[
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+      version="3.0">
+
+	<module-name>customer-portal</module-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Admins</web-resource-name>
+            <url-pattern>/admin/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>admin</role-name>
+        </auth-constraint>
+    </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Customers</web-resource-name>
+            <url-pattern>/customers/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>user</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-constraint>
+        <web-resource-collection>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>KEYCLOAK</auth-method>
+        <realm-name>this is ignored currently/realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>admin</role-name>
+    </security-role>
+    <security-role>
+        <role-name>user</role-name>
+    </security-role>
+</web-app>
+]]>
+</programlisting>
+        </para>
+    </section>
+    <section>
+        <title>Securing WARs via Keycloak Subsystem</title>
+        <para>
+            You do not have to crack open a WAR to secure it with Keycloak.  Alternatively, you can externally secure
+            it via the Keycloak Adapter Subsystem.  While you don't have to specify KEYCLOAK as an <literal>auth-method</literal>,
+            you still have to define the <literal>security-constraints</literal> in <literal>web.xml</literal>.  You do
+            not, however, have to create a <literal>WEB-INF/keycloak.json</literal> file.  This metadata is instead defined
+            within XML in your server's <literal>domain.xml</literal> or <literal>standalone.xml</literal> subsystem
+            configuration section.
+        </para>
+<para>
+<programlisting><![CDATA[
+<extensions>
+  <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+</extensions>
+
+<profile>
+  <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
+     <secure-deployment name="WAR MODULE NAME.war">
+        <realm>demo</realm>
+        <realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA</realm-public-key>
+        <auth-server-url>http://localhost:8081/auth</auth-server-url>
+        <ssl-required>external</ssl-required>
+        <resource>customer-portal</resource>
+        <credential name="secret">password</credential>
+     </secure-deployment>
+  </subsystem>
+</profile>
+]]>
+</programlisting>
+</para>
+        <para>
+            The <literal>security-deployment</literal> <literal>name</literal> attribute identifies the WAR you want
+            to secure.  Its value is the <literal>module-name</literal> defined in <literal>web.xml</literal> with
+            <literal>.war</literal> appended.  The rest of the configuration corresponds pretty much one to one
+            with the <literal>keycloak.json</literal> configuration options defined in <link linkend='adapter-config'>general adapter configuration</link>.
+            The exception is the <literal>credential</literal> element.
+        </para>
+        <para>
+            To make it easier for you, you can go to the Keycloak Adminstration Console and go to the Application/Installation
+            tab of the application this WAR is aligned with.  It provides an example XML file you can cut and paste.
+        </para>
+        <para>
+            There is an additional convenience format for this XML if you have multiple WARs you are deployment that
+            are secured by the same domain.  This format allows you to define common configuration items in one place
+            under the <literal>realm</literal> element.
+        </para>
+        <para>
+            <programlisting><![CDATA[
+<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
+    <realm name="demo">
+        <realm-public-key>MIGfMA0GCSqGSIb3DQEBA</realm-public-key>
+        <auth-server-url>http://localhost:8080/auth</auth-server-url>
+        <ssl-required>external</ssl-required>
+    </realm>
+    <secure-deployment name="customer-portal.war">
+        <realm>demo</realm>
+        <resource>customer-portal</resource>
+        <credential name="secret">password</credential>
+    </secure-deployment>
+    <secure-deployment name="product-portal.war">
+        <realm>demo</realm>
+        <resource>product-portal</resource>
+        <credential name="secret">password</credential>
+    </secure-deployment>
+    <secure-deployment name="database.war">
+        <realm>demo</realm>
+        <resource>database-service</resource>
+        <bearer-only>true</bearer-only>
+    </secure-deployment>
+</subsystem>
+]]>
+            </programlisting>
+        </para>
+    </section>
+
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/jetty8-adapter.xml b/docbook/reference/en/en-US/modules/jetty8-adapter.xml
index 43e45c2..3c3cc74 100755
--- a/docbook/reference/en/en-US/modules/jetty8-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jetty8-adapter.xml
@@ -1,50 +1,50 @@
-<section id="jetty8-adapter">
-    <title>Jetty 8.1.x Adapter</title>
-    <para>
-        Keycloak has a separate adapter for Jetty 8.1.x that you will have to install into your Jetty
-        installation.  You then have to provide some extra configuration in each WAR you deploy to
-        Jetty.  Let's go over these steps.
-    </para>
-    <section id="jetty8-adapter-installation">
-        <title>Adapter Installation</title>
-        <para>
-            Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
-            the Keycloak download site.  They are also available as a maven artifact.
-        </para>
-    <para>
-        You must unzip the Jetty 8.1.x  distro into Jetty 8.1.x's root directory.  Including
-        adapter's jars within your WEB-INF/lib directory will not work!
-    </para>
-    <para>
-<programlisting>
-$ cd $JETTY_HOME
-$ unzip keycloak-jetty81-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        Next, you will have to enable the keycloak option.  Edit start.ini and add keycloak to the options
-    </para>
-        <para>
-<programlisting>
-<![CDATA[
-#===========================================================
-# Start classpath OPTIONS.
-# These control what classes are on the classpath
-# for a full listing do
-#   java -jar start.jar --list-options
-#-----------------------------------------------------------
-OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations,keycloak
-]]>
-</programlisting>
-
-        </para>
-    </section>
-
-    <section>
-        <title>Required Per WAR Configuration</title>
-        <para>
-            Enabling Keycloak for your WARs is the same as the Jetty 9.x adapter.  Our 8.1.x adapter supports both keycloak.json
-            and the jboss-web.xml advanced configuration.  See <link linkend="jetty9_per_war">Required Per WAR Configuration</link>
-        </para>
-     </section>
+<section id="jetty8-adapter">
+    <title>Jetty 8.1.x Adapter</title>
+    <para>
+        Keycloak has a separate adapter for Jetty 8.1.x that you will have to install into your Jetty
+        installation.  You then have to provide some extra configuration in each WAR you deploy to
+        Jetty.  Let's go over these steps.
+    </para>
+    <section id="jetty8-adapter-installation">
+        <title>Adapter Installation</title>
+        <para>
+            Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
+            the Keycloak download site.  They are also available as a maven artifact.
+        </para>
+    <para>
+        You must unzip the Jetty 8.1.x  distro into Jetty 8.1.x's root directory.  Including
+        adapter's jars within your WEB-INF/lib directory will not work!
+    </para>
+    <para>
+<programlisting>
+$ cd $JETTY_HOME
+$ unzip keycloak-jetty81-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        Next, you will have to enable the keycloak option.  Edit start.ini and add keycloak to the options
+    </para>
+        <para>
+<programlisting>
+<![CDATA[
+#===========================================================
+# Start classpath OPTIONS.
+# These control what classes are on the classpath
+# for a full listing do
+#   java -jar start.jar --list-options
+#-----------------------------------------------------------
+OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations,keycloak
+]]>
+</programlisting>
+
+        </para>
+    </section>
+
+    <section>
+        <title>Required Per WAR Configuration</title>
+        <para>
+            Enabling Keycloak for your WARs is the same as the Jetty 9.x adapter.  Our 8.1.x adapter supports both keycloak.json
+            and the jboss-web.xml advanced configuration.  See <link linkend="jetty9_per_war">Required Per WAR Configuration</link>
+        </para>
+     </section>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/jetty9-adapter.xml b/docbook/reference/en/en-US/modules/jetty9-adapter.xml
index 57dd802..30e3878 100755
--- a/docbook/reference/en/en-US/modules/jetty9-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jetty9-adapter.xml
@@ -1,162 +1,162 @@
-<section id="jetty9-adapter">
-    <title>Jetty 9.x Adapters</title>
-    <para>
-        Keycloak has a separate adapter for Jetty 9.1.x and Jetty 9.2.x that you will have to install into your Jetty
-        installation.  You then have to provide some extra configuration in each WAR you deploy to
-        Jetty.  Let's go over these steps.
-    </para>
-    <section id="jetty9-adapter-installation">
-        <title>Adapter Installation</title>
-        <para>
-            Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
-            the Keycloak download site.  They are also available as a maven artifact.
-        </para>
-        <para>
-            You must unzip the Jetty 9.x  distro into Jetty 9.x's root directory.  Including
-            adapter's jars within your WEB-INF/lib directory will not work!
-        </para>
-    <para>
-<programlisting>
-$ cd $JETTY_HOME
-$ unzip keycloak-jetty92-adapter-dist.zip
-</programlisting>
-    </para>
-    <para>
-        Next, you will have to enable the keycloak module for your jetty.base.
-    </para>
-        <para>
-<programlisting>
-$ cd your-base
-$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
-</programlisting>
-
-        </para>
-    </section>
-
-    <section id="jetty9_per_war">
-        <title>Required Per WAR Configuration</title>
-        <para>
-            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
-        </para>
-        <para>
-            The first thing you must do is create a <literal>WEB-INF/jetty-web.xml</literal> file in your WAR package.  This is
-            a Jetty specific config file and you must define a Keycloak specific authenticator within it.
-        </para>
-        <programlisting>
-<![CDATA[
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-            </New>
-        </Set>
-    </Get>
-</Configure>]]>
-        </programlisting>
-        <para>
-            Next you must create
-            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
-            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
-            section.
-        </para>
-        <warning>
-            <para>
-                The Jetty 9.1.x adapter will not be able to find the <literal>keycloak.json</literal> file.  You will have to define
-                all adapter settings within the <literal>jetty-web.xml</literal> file as described below.
-            </para>
-        </warning>
-        <para>
-            Instead of using keycloak.json, you can define everything within the <literal>jetty-web.xml</literal>.  You'll
-            just have to figure out how the json settings match to the <literal>org.keycloak.representations.adapters.config.AdapterConfig</literal>
-            class.
-        </para>
-        <para>
-<programlisting>
-<![CDATA[
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-  <Get name="securityHandler">
-    <Set name="authenticator">
-        <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-            <Set name="adapterConfig">
-                <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                    <Set name="realm">tomcat</Set>
-                    <Set name="resource">customer-portal</Set>
-                    <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                    <Set name="sslRequired">external</Set>
-                    <Set name="credentials">
-                        <Map>
-                            <Entry>
-                                <Item>secret</Item>
-                                <Item>password</Item>
-                            </Entry>
-                        </Map>
-                    </Set>
-                    <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4</Set>
-                </New>
-            </Set>
-        </New>
-    </Set>
-  </Get>
-</Configure>
-]]>
-</programlisting>
-        </para>
-        <para>
-            You do not have to crack open your WAR to secure it with keycloak.  Instead create the jetty-web.xml file
-            in your webapps directory with the name of yourwar.xml.  Jetty should pick it up.  In this mode, you'll have
-            to declare keycloak.json configuration directly within the xml file.
-        </para>
-        <para>
-            Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
-            role-base constraints on your URLs.  Here's an example:
-        </para>
-        <para>
-<programlisting>
-<![CDATA[
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-      version="3.0">
-
-	<module-name>customer-portal</module-name>
-
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Customers</web-resource-name>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>user</role-name>
-        </auth-constraint>
-    </security-constraint>
-
-    <security-constraint>
-        <web-resource-collection>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <user-data-constraint>
-            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
-        </user-data-constraint>
-    </security-constraint>
-
-    <login-config>
-        <auth-method>BASIC</auth-method>
-        <realm-name>this is ignored currently</realm-name>
-    </login-config>
-
-    <security-role>
-        <role-name>admin</role-name>
-    </security-role>
-    <security-role>
-        <role-name>user</role-name>
-    </security-role>
-</web-app>
-]]>
-</programlisting>
-        </para>
-    </section>
+<section id="jetty9-adapter">
+    <title>Jetty 9.x Adapters</title>
+    <para>
+        Keycloak has a separate adapter for Jetty 9.1.x and Jetty 9.2.x that you will have to install into your Jetty
+        installation.  You then have to provide some extra configuration in each WAR you deploy to
+        Jetty.  Let's go over these steps.
+    </para>
+    <section id="jetty9-adapter-installation">
+        <title>Adapter Installation</title>
+        <para>
+            Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
+            the Keycloak download site.  They are also available as a maven artifact.
+        </para>
+        <para>
+            You must unzip the Jetty 9.x  distro into Jetty 9.x's root directory.  Including
+            adapter's jars within your WEB-INF/lib directory will not work!
+        </para>
+    <para>
+<programlisting>
+$ cd $JETTY_HOME
+$ unzip keycloak-jetty92-adapter-dist.zip
+</programlisting>
+    </para>
+    <para>
+        Next, you will have to enable the keycloak module for your jetty.base.
+    </para>
+        <para>
+<programlisting>
+$ cd your-base
+$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
+</programlisting>
+
+        </para>
+    </section>
+
+    <section id="jetty9_per_war">
+        <title>Required Per WAR Configuration</title>
+        <para>
+            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
+        </para>
+        <para>
+            The first thing you must do is create a <literal>WEB-INF/jetty-web.xml</literal> file in your WAR package.  This is
+            a Jetty specific config file and you must define a Keycloak specific authenticator within it.
+        </para>
+        <programlisting>
+<![CDATA[
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+            </New>
+        </Set>
+    </Get>
+</Configure>]]>
+        </programlisting>
+        <para>
+            Next you must create
+            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
+            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
+            section.
+        </para>
+        <warning>
+            <para>
+                The Jetty 9.1.x adapter will not be able to find the <literal>keycloak.json</literal> file.  You will have to define
+                all adapter settings within the <literal>jetty-web.xml</literal> file as described below.
+            </para>
+        </warning>
+        <para>
+            Instead of using keycloak.json, you can define everything within the <literal>jetty-web.xml</literal>.  You'll
+            just have to figure out how the json settings match to the <literal>org.keycloak.representations.adapters.config.AdapterConfig</literal>
+            class.
+        </para>
+        <para>
+<programlisting>
+<![CDATA[
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+  <Get name="securityHandler">
+    <Set name="authenticator">
+        <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+            <Set name="adapterConfig">
+                <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                    <Set name="realm">tomcat</Set>
+                    <Set name="resource">customer-portal</Set>
+                    <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                    <Set name="sslRequired">external</Set>
+                    <Set name="credentials">
+                        <Map>
+                            <Entry>
+                                <Item>secret</Item>
+                                <Item>password</Item>
+                            </Entry>
+                        </Map>
+                    </Set>
+                    <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4</Set>
+                </New>
+            </Set>
+        </New>
+    </Set>
+  </Get>
+</Configure>
+]]>
+</programlisting>
+        </para>
+        <para>
+            You do not have to crack open your WAR to secure it with keycloak.  Instead create the jetty-web.xml file
+            in your webapps directory with the name of yourwar.xml.  Jetty should pick it up.  In this mode, you'll have
+            to declare keycloak.json configuration directly within the xml file.
+        </para>
+        <para>
+            Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
+            role-base constraints on your URLs.  Here's an example:
+        </para>
+        <para>
+<programlisting>
+<![CDATA[
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+      version="3.0">
+
+	<module-name>customer-portal</module-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Customers</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>user</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-constraint>
+        <web-resource-collection>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>this is ignored currently</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>admin</role-name>
+    </security-role>
+    <security-role>
+        <role-name>user</role-name>
+    </security-role>
+</web-app>
+]]>
+</programlisting>
+        </para>
+    </section>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/logout.xml b/docbook/reference/en/en-US/modules/logout.xml
index e2812b8..76a05e2 100755
--- a/docbook/reference/en/en-US/modules/logout.xml
+++ b/docbook/reference/en/en-US/modules/logout.xml
@@ -1,9 +1,9 @@
-<section>
-    <title>Logout</title>
-    <para>
-        There are multiple ways you can logout from a web application.  For Java EE servlet containers, you can call
-        HttpServletRequest.logout().
-        For any other browser application, you can point the browser at the url <literal>http://auth-server/auth/realms/{realm-name}/tokens/logout?redirect_uri=encodedRedirectUri</literal>.
-        This will log you out if you have an SSO session with your browser.
-    </para>
+<section>
+    <title>Logout</title>
+    <para>
+        There are multiple ways you can logout from a web application.  For Java EE servlet containers, you can call
+        HttpServletRequest.logout().
+        For any other browser application, you can point the browser at the url <literal>http://auth-server/auth/realms/{realm-name}/tokens/logout?redirect_uri=encodedRedirectUri</literal>.
+        This will log you out if you have an SSO session with your browser.
+    </para>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml b/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml
index 5996b6d..256f100 100755
--- a/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml
+++ b/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml
@@ -1,394 +1,394 @@
-<chapter id="Migration_from_older_versions">
-    <title>Migration from older versions</title>
-
-    <para>
-        To upgrade to a new version of Keycloak first download and install the new version of Keycloak. You then have to
-        migrate the database, keycloak-server.json, providers, themes and applications from the old version.
-    </para>
-
-    <section>
-        <title>Migrate database</title>
-        <para>
-            Keycloak provides automatic migration of the database. It's highly recommended that you backup your
-            database prior to upgrading Keycloak.
-        </para>
-        <para>
-            To enable automatic upgrading of the database if you're using a relational database make sure
-            <literal>databaseSchema</literal> is set to <literal>update</literal> for <literal>connectionsJpa</literal>:
-<programlisting>
-"connectionsJpa": {
-    "default": {
-        ...
-        "databaseSchema": "update"
-    }
-}
-</programlisting>
-        </para>
-        <para>
-            For MongoDB do the same, but for <literal>connectionsMongo</literal>:
-<programlisting>
-"connectionsMongo": {
-    "default": {
-        ...
-        "databaseSchema": "update"
-    }
-}
-</programlisting>
-        </para>
-        <para>
-            When you start the server with this setting your database will automatically be migrated if the database
-            schema has changed in the new version.
-        </para>
-    </section>
-
-    <section>
-        <title>Migrate keycloak-server.json</title>
-        <para>
-            You should copy <literal>standalone/configuration/keycloak-server.json</literal> from the old version to
-            make sure any configuration changes you've done are added to the new installation. The version specific
-            section below will list any changes done to this file that you have to do when upgrading from one version
-            to another.
-        </para>
-    </section>
-
-    <section>
-        <title>Migrate providers</title>
-        <para>
-            If you have implemented any SPI providers you need to copy them to the new server. The version
-            specific section below will mention if any of the SPI's have changed. If they have you may have to update
-            your code accordingly.
-        </para>
-    </section>
-
-    <section>
-        <title>Migrate themes</title>
-        <para>
-            If you have created a custom theme you need to copy them to the new server. The version specific section below
-            will mention if changes have been made to themes. If there is you may have to update your themes accordingly.
-        </para>
-    </section>
-
-    <section>
-        <title>Migrate application</title>
-        <para>
-            If you deploy applications directly to the Keycloak server you should copy them to the new server. For any
-            applications including those not deployed directly to the Keycloak server you should upgrade the adapter.
-            The version specific section below will mention if any changes are required to applications.
-        </para>
-    </section>
-
-    <section>
-        <title>Version specific migration</title>
-        <section>
-            <title>Migrating to 1.3.0.Final</title>
-            <simplesect>
-                <title>Direct Grant API always enabled</title>
-                <para>
-                    In the past Direct Grant API (or Resource Owner Password Credentials) was disabled by default and
-                    there was an option on a realm to enable it. The Direct Grant API is now always enabled and the
-                    option to enable/disable for a realm is removed.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Database changed</title>
-                <para>
-                    There are again few database changes. Remember to backup your database prior to upgrading.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>UserFederationProvider changed</title>
-                <para>
-                    There are few minor changes in UserFederationProvider interface. You may need to sync your implementation when upgrade
-                    to newer version and upgrade few methods, which has changed signature. Changes are really minor, but were needed to improve performance of federation.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>WildFly 9.0.0.Final</title>
-                <para>
-                    Following on from the distribution changes that was done in the last release the standalone download
-                    of Keycloak is now based on WildFly 9.0.0.Final. This als affects the overlay which can only be deployed
-                    to WildFly 9.0.0.Final or JBoss EAP 6.4.0.GA. WildFly 8.2.0.Final is no longer supported for the server.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>WildFly, JBoss EAP and JBoss AS7 adapters</title>
-                <para>
-                    There are now 3 separate adapter downloads for WildFly, JBoss EAP and JBoss AS7:
-                    <itemizedlist>
-                        <listitem><literal>eap6</literal> - for JBoss EAP 6.x</listitem>
-                        <listitem><literal>wf9</literal> - for WildFly 9.x</listitem>
-                        <listitem><literal>wf8</literal> - for WildFly 8.x</listitem>
-                        <listitem><literal>as7</literal> - for JBoss AS 7.x</listitem>
-                    </itemizedlist>
-                    Make sure you grab the correct one.
-                </para>
-                <para>
-                    You also need to update standalone.xml as the extension module and subsystem definition has changed.
-                    See <link linkend="jboss-adapter-installation">Adapter Installation</link> for details.
-                </para>
-            </simplesect>
-        </section>
-        <section>
-            <title>Migrating from 1.2.0.Beta1 to 1.2.0.RC1</title>
-            <simplesect>
-                <title>Distribution changes</title>
-                <para>
-                    Keycloak is now available in 3 downloads: standalone, overlay and demo bundle. The standalone is intended
-                    for production and non-JEE developers. Overlay is aimed at adding Keycloak to an existing WildFly 8.2 or EAP 6.4
-                    installation and is mainly for development. Finally we have a demo (or dev) bundle that is aimed at
-                    developers getting started with Keycloak. This bundle contains a WildFly server, with Keycloak server and
-                    adapter included. It also contains all documentation and examples.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Database changed</title>
-                <para>
-                    This release contains again a number of changes to the database. The biggest one is Application and OAuth client merge.
-                    Remember to backup your database prior to upgrading.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Application and OAuth client merge</title>
-                <para>
-                    Application and OAuth clients are now merged into <literal>Clients</literal>. The UI of admin console is updated and database as well.
-                    Your data from database should be automatically updated. The previously set Applications will be converted into Clients with <literal>Consent required</literal>
-                    switch off and OAuth Clients will be converted into Clients with this switch on.
-                </para>
-            </simplesect>
-        </section>
-        <section>
-            <title>Migrating from 1.1.0.Final to 1.2.0.Beta1</title>
-            <simplesect>
-                <title>Database changed</title>
-                <para>
-                    This release contains a number of changes to the database. Remember to backup your database prior to
-                    upgrading.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title><literal>iss</literal> in access and id tokens</title>
-                <para>
-                    The value of <literal>iss</literal> claim in access and id tokens have changed from <literal>realm name</literal>
-                    to <literal>realm url</literal>. This is required by OpenID Connect specification. If you're using our adapters
-                    there's no change required, other than if you've been using bearer-only without specifying <literal>auth-server-url</literal>
-                    you have to add it now. If you're using another library (or RSATokenVerifier) you need to make the corresponding
-                    changes when verifying <literal>iss</literal>.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>OpenID Connect endpoints</title>
-                <para>
-                    To comply with OpenID Connect specification the authentication and token endpoints have been changed
-                    to having a single authentication endpoint and a single token endpoint. As per-spec <literal>response_type</literal>
-                    and <literal>grant_type</literal> parameters are used to select the required flow. The old endpoints (<literal>/realms/{realm}/protocols/openid-connect/login</literal>,
-                    <literal>/realms/{realm}/protocols/openid-connect/grants/access</literal>, <literal>/realms/{realm}/protocols/openid-connect/refresh</literal>,
-                    <literal>/realms/{realm}/protocols/openid-connect/access/codes)</literal> are now deprecated and will be removed
-                    in a future version.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Theme changes</title>
-                <para>
-                    The layout of themes have changed. The directory hierarchy used to be <literal>type/name</literal>
-                    this is now changed to <literal>name/type</literal>. For example a login theme named <literal>sunrise</literal>
-                    used to be deployed to <literal>standalone/configuration/themes/login/sunrise</literal>, which is now
-                    moved to <literal>standalone/configuration/themes/sunrise/login</literal>. This change was done to
-                    make it easier to have group the different types for the same theme into one folder.
-                </para>
-                <para>
-                    If you deployed themes as a JAR in the past you had to create a custom theme loader which required
-                    Java code. This has been simplified to only requiring a plain text file (<literal>META-INF/keycloak-themes.json</literal>)
-                    to describe the themes included in a JAR. See the <link linkend='themes'>themes</link> section in the docs for more information.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Claims changes</title>
-                <para>
-                    Previously there was <literal>Claims</literal> tab in admin console for application and OAuth clients. This
-                    was used to configure which attributes should go into access token for particular application/client. This was removed
-                    and replaced with <link linkend='mappers'>Protocol mappers</link>, which are more flexible.
-                </para>
-                <para>
-                    You don't need to care about migration of database from previous version.
-                    We did migration scripts for both RDBMS and Mongo, which should ensure that claims configured for particular application/client
-                    will be converted into corresponding protocol mappers (Still it's safer to backup DB before migrating to newer version though).
-                    Same applies for exported JSON representation from previous version.
-                </para>
-            </simplesect>
-            <simplesect>
-                <title>Social migration to identity brokering</title>
-                <para>
-                    We refactored social providers SPI and replaced it with <link linkend="identity-broker">identity brokering SPI</link>,
-                    which is more flexible. The <literal>Social</literal> tab in admin console is renamed to <literal>Identity Provider</literal> tab.
-                </para>
-                <para>
-                    Again you don't need to care about migration of database from previous version similarly like for Claims/protocol mappers.
-                    Both configuration of social providers and "social links" to your users will be converted to corresponding Identity providers.
-                </para>
-                <para>
-                    Only required action from you would be to change allowed <literal>Redirect URI</literal> in the admin console of
-                    particular 3rd party social providers. You can first go to the Keycloak admin console and copy Redirect URI from the page where
-                    you configure the identity provider. Then you can simply paste this as allowed Redirect URI to the admin console
-                    of 3rd party provider (IE. Facebook admin console).
-                </para>
-            </simplesect>
-        </section>
-        <section>
-            <title>Migrating from 1.1.0.Beta2 to 1.1.0.Final</title>
-            <itemizedlist>
-                <listitem>
-                    Providers are no longer loaded from <literal>WEB-INF/lib</literal>, they are now loaded
-                    from <literal>standalone/configuration/providers</literal>. See the
-                    <link linkend='providers'>providers</link> section for more details.
-                </listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.1.0.Beta1 to 1.1.0.Beta2</title>
-            <itemizedlist>
-                <listitem>Adapters are now a separate download.  They are not included in appliance and war distribution.  We have too many now and the distro
-                is getting bloated.</listitem>
-                <listitem>The tomcat adapter valve has moved to a different package.  From <literal>org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve</literal> to <literal>org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve</literal>
-                From the 'tomcat7' package to just 'tomcat'.
-                </listitem>
-                <listitem>JavaScript adapter now has idToken and idTokenParsed properties. If you use idToken to retrieve first name, email, etc. you need to change this to idTokenParsed.</listitem>
-                <listitem>The as7-eap-subsystem and keycloak-wildfly-subsystem have been merged into one keycloak-subsystem.  If you have an existing standalone.xml
-                          or domain.xml, you will need edit near the top of the file and change the extension module name to org.keycloak.keycloak-subsystem.
-                          For AS7 only, the extension module name is org.keycloak.keycloak-as7-subsystem.</listitem>
-                <listitem>Server installation is no longer supported on AS7.  You can still use AS7 as an application client.</listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0.x.Final to 1.1.0.Beta1</title>
-            <itemizedlist>
-                <listitem>RealmModel JPA and Mongo storage schema has changed</listitem>
-                <listitem>UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored</listitem>
-                <listitem>
-                    Upgrade your adapters, old adapters are not compatible with Keycloak 1.1.  We interpreted JSON Web Token and OIDC ID Token specification incorrectly.  'aud'
-                    claim must be the client id, we were storing the realm name in there and validating it.
-                </listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 RC-1 to RC-2</title>
-            <itemizedlist>
-                <listitem>A lot of info level logging has been changed to debug. Also, a realm no longer has the jboss-logging audit listener by default.
-                    If you want log output when users login, logout, change passwords, etc. enable the jboss-logging audit listener through the admin console.</listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 Beta 4 to RC-1</title>
-            <itemizedlist>
-                <listitem>
-                    logout REST API has been refactored.  The GET request on the logout URI does not take a session_state
-                    parameter anymore.  You must be logged in in order to log out the session.
-                    You can also POST to the logout REST URI.  This action requires a valid refresh token to perform the logout.
-                    The signature is the same as refresh token minus the grant type form parameter.  See documentation for details.
-                </listitem>
-             </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 Beta 1 to Beta 4</title>
-            <itemizedlist>
-                <listitem>
-                    LDAP/AD configuration is changed.  It is no longer under the "Settings" page.  It is now under
-                    Users->Federation.  Add Provider will show you an "ldap" option.
-                </listitem>
-                <listitem>
-                    Authentication SPI has been removed and rewritten.  The new SPI is UserFederationProvider and is
-                    more flexible.
-                </listitem>
-                <listitem>
-                    <literal>ssl-not-required</literal> property in adapter config has been removed. Replaced with
-                    <literal>ssl-required</literal>, valid values are <literal>all</literal> (require SSL for all requests), <literal>external</literal>
-                    (require SSL only for external request) and <literal>none</literal> (SSL not required).
-                </listitem>
-                <listitem>
-                    DB Schema has changed again.
-                </listitem>
-                <listitem>
-                    Created applications now have a full scope by default.  This means that you don't have to configure
-                    the scope of an application if you don't want to.
-                </listitem>
-                <listitem>
-                    Format of JSON file for importing realm data was changed. Now role mappings is available under the JSON record of particular
-                    user.
-                </listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 Alpha 4 to Beta 1</title>
-            <itemizedlist>
-                <listitem>
-                    DB Schema has changed.  We have added export of the database to Beta 1, but not the ability to import
-                    the database from older versions. This will be supported in future releases.
-                </listitem>
-                <listitem>
-                    For all clients except bearer-only applications, you must specify at least one redirect uri.  Keycloak
-                    will not allow you to log in unless you have specified a valid redirect uri for that application.
-                </listitem>
-                <listitem>
-                    Resource Owner Password Credentials flow is now disabled by default. It can be enabled by setting the toggle
-                    for <literal>Direct Grant API</literal> <literal>ON</literal> under realm config in the admin console.
-                </listitem>
-                <listitem>
-                    Configuration is now done through <literal>standalone/configuration/keycloak-server.json</literal>. This
-                    should mainly affect those that use MongoDB.
-                </listitem>
-                <listitem>
-                    JavaScript adapter has been refactored. See the <link linkend='javascript-adapter'>JavaScript adapter</link> section for more details.
-                </listitem>
-                <listitem>
-                    The "Central Login Lifespan" setting no longer exists.  Please see the <link linkend='session-timeouts'>Session Timeout</link> section
-                    for me details.
-                </listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 Alpha 2 to Alpha 3</title>
-            <itemizedlist>
-                <listitem>
-                    SkeletonKeyToken, SkeletonKeyScope, SkeletonKeyPrincipal, and SkeletonKeySession have been renamed to:
-                    AccessToken, AccessScope, KeycloakPrincipal, and KeycloakAuthenticatedSession respectively.
-                </listitem>
-                <listitem>
-                    ServleOAuthClient.getBearerToken() method signature has changed.  It now returns an AccessTokenResponse
-                    so that you can obtain a refresh token too.
-                </listitem>
-                <listitem>
-                    Adapters now check the access token expiration with every request.  If the token is expired, they will
-                    attempt to invoke a refresh on the auth server using a saved refresh token.
-                </listitem>
-                <listitem>
-                    Subject in AccessToken has been changed to the User ID.
-                </listitem>
-            </itemizedlist>
-        </section>
-        <section>
-            <title>Migrating from 1.0 Alpha 1 to Alpha 2</title>
-            <itemizedlist>
-                <listitem>
-                    DB Schema has changed.  We don't have any data migration utilities yet as of Alpha 2.
-                </listitem>
-                <listitem>
-                    JBoss and Wildfly adapters are now installed via a JBoss/Wildfly subsystem.  Please review the adapter
-                    installation documentation.  Edits to standalone.xml are now required.
-                </listitem>
-                <listitem>
-                    There is a new credential type "secret".  Unlike other credential types, it is stored in plain text in
-                    the database and can be viewed in the admin console.
-
-                </listitem>
-                <listitem>
-                    There is no longer required Application or OAuth Client credentials.  These client types are now
-                    hard coded to use the "secret" credential type.
-                </listitem>
-                <listitem>
-                    Because of the "secret" credential change to Application and OAuth Client, you'll have to update
-                    your keycloak.json configuration files and regenarate a secret within the Application or OAuth Client
-                    credentials tab in the administration console.
-                </listitem>
-            </itemizedlist>
-        </section>
-    </section>
+<chapter id="Migration_from_older_versions">
+    <title>Migration from older versions</title>
+
+    <para>
+        To upgrade to a new version of Keycloak first download and install the new version of Keycloak. You then have to
+        migrate the database, keycloak-server.json, providers, themes and applications from the old version.
+    </para>
+
+    <section>
+        <title>Migrate database</title>
+        <para>
+            Keycloak provides automatic migration of the database. It's highly recommended that you backup your
+            database prior to upgrading Keycloak.
+        </para>
+        <para>
+            To enable automatic upgrading of the database if you're using a relational database make sure
+            <literal>databaseSchema</literal> is set to <literal>update</literal> for <literal>connectionsJpa</literal>:
+<programlisting>
+"connectionsJpa": {
+    "default": {
+        ...
+        "databaseSchema": "update"
+    }
+}
+</programlisting>
+        </para>
+        <para>
+            For MongoDB do the same, but for <literal>connectionsMongo</literal>:
+<programlisting>
+"connectionsMongo": {
+    "default": {
+        ...
+        "databaseSchema": "update"
+    }
+}
+</programlisting>
+        </para>
+        <para>
+            When you start the server with this setting your database will automatically be migrated if the database
+            schema has changed in the new version.
+        </para>
+    </section>
+
+    <section>
+        <title>Migrate keycloak-server.json</title>
+        <para>
+            You should copy <literal>standalone/configuration/keycloak-server.json</literal> from the old version to
+            make sure any configuration changes you've done are added to the new installation. The version specific
+            section below will list any changes done to this file that you have to do when upgrading from one version
+            to another.
+        </para>
+    </section>
+
+    <section>
+        <title>Migrate providers</title>
+        <para>
+            If you have implemented any SPI providers you need to copy them to the new server. The version
+            specific section below will mention if any of the SPI's have changed. If they have you may have to update
+            your code accordingly.
+        </para>
+    </section>
+
+    <section>
+        <title>Migrate themes</title>
+        <para>
+            If you have created a custom theme you need to copy them to the new server. The version specific section below
+            will mention if changes have been made to themes. If there is you may have to update your themes accordingly.
+        </para>
+    </section>
+
+    <section>
+        <title>Migrate application</title>
+        <para>
+            If you deploy applications directly to the Keycloak server you should copy them to the new server. For any
+            applications including those not deployed directly to the Keycloak server you should upgrade the adapter.
+            The version specific section below will mention if any changes are required to applications.
+        </para>
+    </section>
+
+    <section>
+        <title>Version specific migration</title>
+        <section>
+            <title>Migrating to 1.3.0.Final</title>
+            <simplesect>
+                <title>Direct Grant API always enabled</title>
+                <para>
+                    In the past Direct Grant API (or Resource Owner Password Credentials) was disabled by default and
+                    there was an option on a realm to enable it. The Direct Grant API is now always enabled and the
+                    option to enable/disable for a realm is removed.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Database changed</title>
+                <para>
+                    There are again few database changes. Remember to backup your database prior to upgrading.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>UserFederationProvider changed</title>
+                <para>
+                    There are few minor changes in UserFederationProvider interface. You may need to sync your implementation when upgrade
+                    to newer version and upgrade few methods, which has changed signature. Changes are really minor, but were needed to improve performance of federation.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>WildFly 9.0.0.Final</title>
+                <para>
+                    Following on from the distribution changes that was done in the last release the standalone download
+                    of Keycloak is now based on WildFly 9.0.0.Final. This als affects the overlay which can only be deployed
+                    to WildFly 9.0.0.Final or JBoss EAP 6.4.0.GA. WildFly 8.2.0.Final is no longer supported for the server.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>WildFly, JBoss EAP and JBoss AS7 adapters</title>
+                <para>
+                    There are now 3 separate adapter downloads for WildFly, JBoss EAP and JBoss AS7:
+                    <itemizedlist>
+                        <listitem><literal>eap6</literal> - for JBoss EAP 6.x</listitem>
+                        <listitem><literal>wf9</literal> - for WildFly 9.x</listitem>
+                        <listitem><literal>wf8</literal> - for WildFly 8.x</listitem>
+                        <listitem><literal>as7</literal> - for JBoss AS 7.x</listitem>
+                    </itemizedlist>
+                    Make sure you grab the correct one.
+                </para>
+                <para>
+                    You also need to update standalone.xml as the extension module and subsystem definition has changed.
+                    See <link linkend="jboss-adapter-installation">Adapter Installation</link> for details.
+                </para>
+            </simplesect>
+        </section>
+        <section>
+            <title>Migrating from 1.2.0.Beta1 to 1.2.0.RC1</title>
+            <simplesect>
+                <title>Distribution changes</title>
+                <para>
+                    Keycloak is now available in 3 downloads: standalone, overlay and demo bundle. The standalone is intended
+                    for production and non-JEE developers. Overlay is aimed at adding Keycloak to an existing WildFly 8.2 or EAP 6.4
+                    installation and is mainly for development. Finally we have a demo (or dev) bundle that is aimed at
+                    developers getting started with Keycloak. This bundle contains a WildFly server, with Keycloak server and
+                    adapter included. It also contains all documentation and examples.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Database changed</title>
+                <para>
+                    This release contains again a number of changes to the database. The biggest one is Application and OAuth client merge.
+                    Remember to backup your database prior to upgrading.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Application and OAuth client merge</title>
+                <para>
+                    Application and OAuth clients are now merged into <literal>Clients</literal>. The UI of admin console is updated and database as well.
+                    Your data from database should be automatically updated. The previously set Applications will be converted into Clients with <literal>Consent required</literal>
+                    switch off and OAuth Clients will be converted into Clients with this switch on.
+                </para>
+            </simplesect>
+        </section>
+        <section>
+            <title>Migrating from 1.1.0.Final to 1.2.0.Beta1</title>
+            <simplesect>
+                <title>Database changed</title>
+                <para>
+                    This release contains a number of changes to the database. Remember to backup your database prior to
+                    upgrading.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title><literal>iss</literal> in access and id tokens</title>
+                <para>
+                    The value of <literal>iss</literal> claim in access and id tokens have changed from <literal>realm name</literal>
+                    to <literal>realm url</literal>. This is required by OpenID Connect specification. If you're using our adapters
+                    there's no change required, other than if you've been using bearer-only without specifying <literal>auth-server-url</literal>
+                    you have to add it now. If you're using another library (or RSATokenVerifier) you need to make the corresponding
+                    changes when verifying <literal>iss</literal>.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>OpenID Connect endpoints</title>
+                <para>
+                    To comply with OpenID Connect specification the authentication and token endpoints have been changed
+                    to having a single authentication endpoint and a single token endpoint. As per-spec <literal>response_type</literal>
+                    and <literal>grant_type</literal> parameters are used to select the required flow. The old endpoints (<literal>/realms/{realm}/protocols/openid-connect/login</literal>,
+                    <literal>/realms/{realm}/protocols/openid-connect/grants/access</literal>, <literal>/realms/{realm}/protocols/openid-connect/refresh</literal>,
+                    <literal>/realms/{realm}/protocols/openid-connect/access/codes)</literal> are now deprecated and will be removed
+                    in a future version.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Theme changes</title>
+                <para>
+                    The layout of themes have changed. The directory hierarchy used to be <literal>type/name</literal>
+                    this is now changed to <literal>name/type</literal>. For example a login theme named <literal>sunrise</literal>
+                    used to be deployed to <literal>standalone/configuration/themes/login/sunrise</literal>, which is now
+                    moved to <literal>standalone/configuration/themes/sunrise/login</literal>. This change was done to
+                    make it easier to have group the different types for the same theme into one folder.
+                </para>
+                <para>
+                    If you deployed themes as a JAR in the past you had to create a custom theme loader which required
+                    Java code. This has been simplified to only requiring a plain text file (<literal>META-INF/keycloak-themes.json</literal>)
+                    to describe the themes included in a JAR. See the <link linkend='themes'>themes</link> section in the docs for more information.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Claims changes</title>
+                <para>
+                    Previously there was <literal>Claims</literal> tab in admin console for application and OAuth clients. This
+                    was used to configure which attributes should go into access token for particular application/client. This was removed
+                    and replaced with <link linkend='mappers'>Protocol mappers</link>, which are more flexible.
+                </para>
+                <para>
+                    You don't need to care about migration of database from previous version.
+                    We did migration scripts for both RDBMS and Mongo, which should ensure that claims configured for particular application/client
+                    will be converted into corresponding protocol mappers (Still it's safer to backup DB before migrating to newer version though).
+                    Same applies for exported JSON representation from previous version.
+                </para>
+            </simplesect>
+            <simplesect>
+                <title>Social migration to identity brokering</title>
+                <para>
+                    We refactored social providers SPI and replaced it with <link linkend="identity-broker">identity brokering SPI</link>,
+                    which is more flexible. The <literal>Social</literal> tab in admin console is renamed to <literal>Identity Provider</literal> tab.
+                </para>
+                <para>
+                    Again you don't need to care about migration of database from previous version similarly like for Claims/protocol mappers.
+                    Both configuration of social providers and "social links" to your users will be converted to corresponding Identity providers.
+                </para>
+                <para>
+                    Only required action from you would be to change allowed <literal>Redirect URI</literal> in the admin console of
+                    particular 3rd party social providers. You can first go to the Keycloak admin console and copy Redirect URI from the page where
+                    you configure the identity provider. Then you can simply paste this as allowed Redirect URI to the admin console
+                    of 3rd party provider (IE. Facebook admin console).
+                </para>
+            </simplesect>
+        </section>
+        <section>
+            <title>Migrating from 1.1.0.Beta2 to 1.1.0.Final</title>
+            <itemizedlist>
+                <listitem>
+                    Providers are no longer loaded from <literal>WEB-INF/lib</literal>, they are now loaded
+                    from <literal>standalone/configuration/providers</literal>. See the
+                    <link linkend='providers'>providers</link> section for more details.
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.1.0.Beta1 to 1.1.0.Beta2</title>
+            <itemizedlist>
+                <listitem>Adapters are now a separate download.  They are not included in appliance and war distribution.  We have too many now and the distro
+                is getting bloated.</listitem>
+                <listitem>The tomcat adapter valve has moved to a different package.  From <literal>org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve</literal> to <literal>org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve</literal>
+                From the 'tomcat7' package to just 'tomcat'.
+                </listitem>
+                <listitem>JavaScript adapter now has idToken and idTokenParsed properties. If you use idToken to retrieve first name, email, etc. you need to change this to idTokenParsed.</listitem>
+                <listitem>The as7-eap-subsystem and keycloak-wildfly-subsystem have been merged into one keycloak-subsystem.  If you have an existing standalone.xml
+                          or domain.xml, you will need edit near the top of the file and change the extension module name to org.keycloak.keycloak-subsystem.
+                          For AS7 only, the extension module name is org.keycloak.keycloak-as7-subsystem.</listitem>
+                <listitem>Server installation is no longer supported on AS7.  You can still use AS7 as an application client.</listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0.x.Final to 1.1.0.Beta1</title>
+            <itemizedlist>
+                <listitem>RealmModel JPA and Mongo storage schema has changed</listitem>
+                <listitem>UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored</listitem>
+                <listitem>
+                    Upgrade your adapters, old adapters are not compatible with Keycloak 1.1.  We interpreted JSON Web Token and OIDC ID Token specification incorrectly.  'aud'
+                    claim must be the client id, we were storing the realm name in there and validating it.
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 RC-1 to RC-2</title>
+            <itemizedlist>
+                <listitem>A lot of info level logging has been changed to debug. Also, a realm no longer has the jboss-logging audit listener by default.
+                    If you want log output when users login, logout, change passwords, etc. enable the jboss-logging audit listener through the admin console.</listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 Beta 4 to RC-1</title>
+            <itemizedlist>
+                <listitem>
+                    logout REST API has been refactored.  The GET request on the logout URI does not take a session_state
+                    parameter anymore.  You must be logged in in order to log out the session.
+                    You can also POST to the logout REST URI.  This action requires a valid refresh token to perform the logout.
+                    The signature is the same as refresh token minus the grant type form parameter.  See documentation for details.
+                </listitem>
+             </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 Beta 1 to Beta 4</title>
+            <itemizedlist>
+                <listitem>
+                    LDAP/AD configuration is changed.  It is no longer under the "Settings" page.  It is now under
+                    Users->Federation.  Add Provider will show you an "ldap" option.
+                </listitem>
+                <listitem>
+                    Authentication SPI has been removed and rewritten.  The new SPI is UserFederationProvider and is
+                    more flexible.
+                </listitem>
+                <listitem>
+                    <literal>ssl-not-required</literal> property in adapter config has been removed. Replaced with
+                    <literal>ssl-required</literal>, valid values are <literal>all</literal> (require SSL for all requests), <literal>external</literal>
+                    (require SSL only for external request) and <literal>none</literal> (SSL not required).
+                </listitem>
+                <listitem>
+                    DB Schema has changed again.
+                </listitem>
+                <listitem>
+                    Created applications now have a full scope by default.  This means that you don't have to configure
+                    the scope of an application if you don't want to.
+                </listitem>
+                <listitem>
+                    Format of JSON file for importing realm data was changed. Now role mappings is available under the JSON record of particular
+                    user.
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 Alpha 4 to Beta 1</title>
+            <itemizedlist>
+                <listitem>
+                    DB Schema has changed.  We have added export of the database to Beta 1, but not the ability to import
+                    the database from older versions. This will be supported in future releases.
+                </listitem>
+                <listitem>
+                    For all clients except bearer-only applications, you must specify at least one redirect uri.  Keycloak
+                    will not allow you to log in unless you have specified a valid redirect uri for that application.
+                </listitem>
+                <listitem>
+                    Resource Owner Password Credentials flow is now disabled by default. It can be enabled by setting the toggle
+                    for <literal>Direct Grant API</literal> <literal>ON</literal> under realm config in the admin console.
+                </listitem>
+                <listitem>
+                    Configuration is now done through <literal>standalone/configuration/keycloak-server.json</literal>. This
+                    should mainly affect those that use MongoDB.
+                </listitem>
+                <listitem>
+                    JavaScript adapter has been refactored. See the <link linkend='javascript-adapter'>JavaScript adapter</link> section for more details.
+                </listitem>
+                <listitem>
+                    The "Central Login Lifespan" setting no longer exists.  Please see the <link linkend='session-timeouts'>Session Timeout</link> section
+                    for me details.
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 Alpha 2 to Alpha 3</title>
+            <itemizedlist>
+                <listitem>
+                    SkeletonKeyToken, SkeletonKeyScope, SkeletonKeyPrincipal, and SkeletonKeySession have been renamed to:
+                    AccessToken, AccessScope, KeycloakPrincipal, and KeycloakAuthenticatedSession respectively.
+                </listitem>
+                <listitem>
+                    ServleOAuthClient.getBearerToken() method signature has changed.  It now returns an AccessTokenResponse
+                    so that you can obtain a refresh token too.
+                </listitem>
+                <listitem>
+                    Adapters now check the access token expiration with every request.  If the token is expired, they will
+                    attempt to invoke a refresh on the auth server using a saved refresh token.
+                </listitem>
+                <listitem>
+                    Subject in AccessToken has been changed to the User ID.
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section>
+            <title>Migrating from 1.0 Alpha 1 to Alpha 2</title>
+            <itemizedlist>
+                <listitem>
+                    DB Schema has changed.  We don't have any data migration utilities yet as of Alpha 2.
+                </listitem>
+                <listitem>
+                    JBoss and Wildfly adapters are now installed via a JBoss/Wildfly subsystem.  Please review the adapter
+                    installation documentation.  Edits to standalone.xml are now required.
+                </listitem>
+                <listitem>
+                    There is a new credential type "secret".  Unlike other credential types, it is stored in plain text in
+                    the database and can be viewed in the admin console.
+
+                </listitem>
+                <listitem>
+                    There is no longer required Application or OAuth Client credentials.  These client types are now
+                    hard coded to use the "secret" credential type.
+                </listitem>
+                <listitem>
+                    Because of the "secret" credential change to Application and OAuth Client, you'll have to update
+                    your keycloak.json configuration files and regenarate a secret within the Application or OAuth Client
+                    credentials tab in the administration console.
+                </listitem>
+            </itemizedlist>
+        </section>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/per-realm-admin-permissions.xml b/docbook/reference/en/en-US/modules/per-realm-admin-permissions.xml
index 19f3863..ffd90f8 100755
--- a/docbook/reference/en/en-US/modules/per-realm-admin-permissions.xml
+++ b/docbook/reference/en/en-US/modules/per-realm-admin-permissions.xml
@@ -1,65 +1,65 @@
-<chapter id="per-realm-admin-permissions">
-    <title>Per Realm Admin Access Control</title>
-    <para>
-        Administering your realm through the <literal>master</literal> realm as discussed in <xref linkend="admin-permissions" /> may not always be
-        ideal or feasible.  For example, maybe you have more than one admin application that manages various admin aspects of your organization
-        and you want to unify all these different "admin consoles" under one realm so you can do SSO between them.  Keycloak allows you to
-        grant realm admin privileges to users within that realm.  These realm admins can participate in SSO for that realm and
-        visit a keycloak admin console instance that is dedicated solely for that realm by going to the url:
-        <literal>/{keycloak-root}/admin/{realm}/console</literal>
-    </para>
-    <section>
-        <title>Realm Roles</title>
-        <para>
-            Each realm has a built-in application called <literal>realm-management</literal>.  This application defines
-            roles that define permissions that can be granted to manage the realm.
-            <itemizedlist>
-                <listitem>
-                    <literal>realm-admin</literal> - This is a composite role that grants all admin privileges for managing
-                    security for that realm.
-                </listitem>
-            </itemizedlist>
-            These are more fine-grain roles you can assign to the user.
-
-            <itemizedlist>
-                <listitem>
-                    <literal>view-realm</literal> - View the realm configuration
-                </listitem>
-                <listitem>
-                    <literal>view-users</literal> - View users (including details for specific user) in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-applications</literal> - View applications in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-clients</literal> - View clients in the realm
-                </listitem>
-                <listitem>
-                    <literal>view-events</literal> - View events in the realm
-                </listitem>
-
-                <listitem>
-                    <literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
-                </listitem>
-                <listitem>
-                    <literal>manage-users</literal> - Create, modify and delete users in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-applications</literal> - Create, modify and delete applications in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-clients</literal> - Create, modify and delete clients in the realm
-                </listitem>
-                <listitem>
-                    <literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
-                </listitem>
-            </itemizedlist>
-            Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
-        </para>
-        <para>
-            To add these roles to a user select the realm you want. Then click on <literal>Users</literal>.
-            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
-            <literal>Application Roles</literal> select <literal>realm-management</literal>, then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
-        </para>
-    </section>
-</chapter>
+<chapter id="per-realm-admin-permissions">
+    <title>Per Realm Admin Access Control</title>
+    <para>
+        Administering your realm through the <literal>master</literal> realm as discussed in <xref linkend="admin-permissions" /> may not always be
+        ideal or feasible.  For example, maybe you have more than one admin application that manages various admin aspects of your organization
+        and you want to unify all these different "admin consoles" under one realm so you can do SSO between them.  Keycloak allows you to
+        grant realm admin privileges to users within that realm.  These realm admins can participate in SSO for that realm and
+        visit a keycloak admin console instance that is dedicated solely for that realm by going to the url:
+        <literal>/{keycloak-root}/admin/{realm}/console</literal>
+    </para>
+    <section>
+        <title>Realm Roles</title>
+        <para>
+            Each realm has a built-in application called <literal>realm-management</literal>.  This application defines
+            roles that define permissions that can be granted to manage the realm.
+            <itemizedlist>
+                <listitem>
+                    <literal>realm-admin</literal> - This is a composite role that grants all admin privileges for managing
+                    security for that realm.
+                </listitem>
+            </itemizedlist>
+            These are more fine-grain roles you can assign to the user.
+
+            <itemizedlist>
+                <listitem>
+                    <literal>view-realm</literal> - View the realm configuration
+                </listitem>
+                <listitem>
+                    <literal>view-users</literal> - View users (including details for specific user) in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-applications</literal> - View applications in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-clients</literal> - View clients in the realm
+                </listitem>
+                <listitem>
+                    <literal>view-events</literal> - View events in the realm
+                </listitem>
+
+                <listitem>
+                    <literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
+                </listitem>
+                <listitem>
+                    <literal>manage-users</literal> - Create, modify and delete users in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-applications</literal> - Create, modify and delete applications in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-clients</literal> - Create, modify and delete clients in the realm
+                </listitem>
+                <listitem>
+                    <literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
+                </listitem>
+            </itemizedlist>
+            Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
+        </para>
+        <para>
+            To add these roles to a user select the realm you want. Then click on <literal>Users</literal>.
+            Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
+            <literal>Application Roles</literal> select <literal>realm-management</literal>, then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
+        </para>
+    </section>
+</chapter>
diff --git a/docbook/reference/en/en-US/modules/protocol-mappers.xml b/docbook/reference/en/en-US/modules/protocol-mappers.xml
index 0c85d62..7ca3a0f 100755
--- a/docbook/reference/en/en-US/modules/protocol-mappers.xml
+++ b/docbook/reference/en/en-US/modules/protocol-mappers.xml
@@ -1,17 +1,17 @@
-<chapter id="mappers">
-    <title>OIDC Token and SAML Assertion Mappings</title>
-    <para>
-        Applications that receive ID Tokens, Access Tokens, or SAML assertions may need or want different user metadata
-        and roles.  Keycloak allows you to define what exactly is transferred.  You can hardcode roles, claims and custom
-        attributes.  You can pull user metadata into a token or assertion.  You can rename roles.  Basicall you have
-        a lot of control of what exactly goes back to the client.
-    </para>
-    <para>
-        Within the admin console, if you go to an application you've registered, you'll see a "Mappers" sub-menu item.
-        This is the place where you can control how a OIDC ID Token, Access Token, and SAML login response assertions look
-        like.  When you click on this you'll see some default mappers that have been set up for you.  Clicking the
-        "Add Builtin" button gives you the option to add other preconfigured mappers.  Clicking on "Create" allows
-        you to define your own protocol mappers.  The tooltips are very helpful to learn exactly what you can do
-        to tailor your tokens and assertions.  They should be enough to guide you through the process.
-    </para>
+<chapter id="mappers">
+    <title>OIDC Token and SAML Assertion Mappings</title>
+    <para>
+        Applications that receive ID Tokens, Access Tokens, or SAML assertions may need or want different user metadata
+        and roles.  Keycloak allows you to define what exactly is transferred.  You can hardcode roles, claims and custom
+        attributes.  You can pull user metadata into a token or assertion.  You can rename roles.  Basicall you have
+        a lot of control of what exactly goes back to the client.
+    </para>
+    <para>
+        Within the admin console, if you go to an application you've registered, you'll see a "Mappers" sub-menu item.
+        This is the place where you can control how a OIDC ID Token, Access Token, and SAML login response assertions look
+        like.  When you click on this you'll see some default mappers that have been set up for you.  Clicking the
+        "Add Builtin" button gives you the option to add other preconfigured mappers.  Clicking on "Create" allows
+        you to define your own protocol mappers.  The tooltips are very helpful to learn exactly what you can do
+        to tailor your tokens and assertions.  They should be enough to guide you through the process.
+    </para>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/proxy.xml b/docbook/reference/en/en-US/modules/proxy.xml
index b38fbbb..43f7ee3 100755
--- a/docbook/reference/en/en-US/modules/proxy.xml
+++ b/docbook/reference/en/en-US/modules/proxy.xml
@@ -1,402 +1,402 @@
-<chapter id="proxy">
-    <title>Keycloak Security Proxy</title>
-    <para>
-        Keycloak has an HTTP(S) proxy that you can put in front of web applications and services where it is not possible
-        to install the keycloak adapter.  You can set up URL filters so that certain URLs are secured either by browser login
-        and/or bearer token authentication.  You can also define role constraints for URL patterns within your applications.
-    </para>
-    <section>
-        <title>Proxy Install and Run</title>
-        <para>Download the keycloak proxy distribution from the Keycloak download pages and unzip it.
-<programlisting>
-$ unzip keycloak-proxy-dist.zip
-</programlisting>
-        </para>
-        <para>
-            To run it you must have a proxy config file (which we'll discuss in a moment).
-<programlisting>
-$ java -jar bin/launcher.jar [your-config.json]
-</programlisting>
-        </para>
-        <para>
-            If you do not specify a path to the proxy config file, the launcher will look in the current working directory
-            for the file named <literal>proxy.json</literal>
-        </para>
-    </section>
-    <section>
-        <title>Proxy Configuration</title>
-        <para>
-            Here's an example configuration file.
-<programlisting><![CDATA[
-{
-    "target-url": "http://localhost:8082",
-    "send-access-token": true,
-    "bind-address": "localhost",
-    "http-port": "8080",
-    "https-port": "8443",
-    "keystore": "classpath:ssl.jks",
-    "keystore-password": "password",
-    "key-password": "password",
-    "applications": [
-        {
-            "base-path": "/customer-portal",
-            "error-page": "/error.html",
-            "adapter-config": {
-                "realm": "demo",
-                "resource": "customer-portal",
-                "realm-public-key": "MIGfMA0GCSqGSIb",
-                "auth-server-url": "http://localhost:8081/auth",
-                "ssl-required" : "external",
-                "principal-attribute": "name",
-                "credentials": {
-                    "secret": "password"
-                }
-            }
-            ,
-            "constraints": [
-                {
-                    "pattern": "/users/*",
-                    "roles-allowed": [
-                        "user"
-                    ]
-                },
-                {
-                    "pattern": "/admins/*",
-                    "roles-allowed": [
-                        "admin"
-                    ]
-                },
-                {
-                    "pattern": "/users/permit",
-                    "permit": true
-                },
-                {
-                    "pattern": "/users/deny",
-                    "deny": true
-                }
-            ]
-        }
-    ]
-}]]>
-</programlisting>
-        </para>
-        <section>
-            <title>Basic Config</title>
-        <para>
-            The basic configuration options for the server are as follows:
-            <variablelist>
-                <varlistentry>
-                    <term>target-url</term>
-                    <listitem>
-                        <para>
-                            The URL this server is proxying <emphasis>REQUIRED.</emphasis>.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>send-access-token</term>
-                    <listitem>
-                        <para>
-                            Boolean flag.  If true, this will send the access token via the KEYCLOAK_ACCESS_TOKEN header to the
-                            proxied server. <emphasis>OPTIONAL.</emphasis>.  Default is false.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>bind-address</term>
-                    <listitem>
-                        <para>
-                            DNS name or IP address to bind the proxy server's sockets to.
-                            <emphasis>OPTIONAL.</emphasis>.  The default value is <emphasis>localhost</emphasis>
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>http-port</term>
-                    <listitem>
-                        <para>
-                            Port to listen for HTTP requests.  If you do not specify this value, then the proxy will
-                            not listen for regular HTTP requests.
-                            <emphasis>OPTIONAL.</emphasis>.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>https-port</term>
-                    <listitem>
-                        <para>
-                            Port to listen for HTTPS requests.  If you do not specify this value, then the proxy will
-                            not listen for HTTPS requests.
-                            <emphasis>OPTIONAL.</emphasis>.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>keystore</term>
-                    <listitem>
-                        <para>
-                            Path to a Java keystore file that contains private key and certificate for the server to be
-                            able to handle HTTPS requests.  Can be a file path, or, if you prefix it with <literal>classpath:</literal>
-                            it will look for this file in the classpath.
-                            <emphasis>OPTIONAL.</emphasis>.  If you have enabled HTTPS, but have not defined a keystore, the proxy
-                            will auto-generate a self-signed certificate and use that.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>buffer-size</term>
-                    <listitem>
-                        <para>
-                            HTTP server socket buffer size.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>buffers-per-region</term>
-                    <listitem>
-                        <para>
-                            HTTP server socket buffers per region.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>io-threads</term>
-                    <listitem>
-                        <para>
-                            Number of threads to handle IO.  Usually default is good enough.  <emphasis>OPTIONAL.</emphasis>.
-                            The default is the number of available processors * 2.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>worker-threads</term>
-                    <listitem>
-                        <para>
-                            Number of threads to handle requests.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
-                            The default is the number of available processors * 16.
-                        </para>
-                    </listitem>
-                </varlistentry>
-            </variablelist>
-        </para>
-        </section>
-        <section>
-            <title>Application Config</title>
-            <para>
-                Next under the <literal>applications</literal> array attribute, you can define one or more applications per host you are proxying.
-                <variablelist>
-                    <varlistentry>
-                        <term>base-path</term>
-                        <listitem>
-                            <para>
-                                The base context root for the application.  Must start with '/' <emphasis>REQUIRED.</emphasis>.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>error-page</term>
-                        <listitem>
-                            <para>
-                                If the proxy has an error, it will display the target application's error page relative URL <emphasis>OPTIONAL.</emphasis>.
-                                This is a relative path to the base-path.  In the example above it would be <literal>/customer-portal/error.html</literal>.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>adapter-config</term>
-                        <listitem>
-                            <para>
-                                <emphasis>REQUIRED.</emphasis>.  Same configuration as any other keycloak adapter.  See <link linkend='adapter-config'>Adapter Config</link>
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                </variablelist>
-            </para>
-            <section>
-                <title>Constraint Config</title>
-                <para>
-                    Next under each application you can define one or more constraints in the <literal>constraints</literal> array attribute.
-                    A constraint defines a URL pattern relative to the base-path.  You can deny, permit, or require authentication for
-                    a specific URL pattern.  You can specify roles allowed for that path as well.  More specific constraints will take
-                    precedence over more general ones.
-                    <variablelist>
-                        <varlistentry>
-                            <term>pattern</term>
-                            <listitem>
-                                <para>
-                                    URL pattern to match relative to the base-path of the application.  Must start with '/' <emphasis>REQUIRED.</emphasis>.
-                                    You may only have one wildcard and it must come at the end of the pattern.  Valid <literal>/foo/bar/*</literal> and  <literal>/foo/*.txt</literal>
-                                    Not valid: <literal>/*/foo/*</literal>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>roles-allowed</term>
-                            <listitem>
-                                <para>
-                                    Array of strings of roles allowed to access this url pattern. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>methods</term>
-                            <listitem>
-                                <para>
-                                    Array of strings of HTTP methods that will exclusively match this pattern and HTTP request. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>excluded-methods</term>
-                            <listitem>
-                                <para>
-                                    Array of strings of HTTP methods that will be ignored when match this pattern. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>deny</term>
-                            <listitem>
-                                <para>
-                                    Deny all access to this URL pattern. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>permit</term>
-                            <listitem>
-                                <para>
-                                    Permit all access without requiring authentication or a role mapping. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>permit-and-inject</term>
-                            <listitem>
-                                <para>
-                                    Permit all access, but inject the headers, if user is already authenticated.<emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                        <varlistentry>
-                            <term>authenticate</term>
-                            <listitem>
-                                <para>
-                                    Require authentication for this pattern, but no role mapping. <emphasis>OPTIONAL.</emphasis>.
-                                </para>
-                            </listitem>
-                        </varlistentry>
-                    </variablelist>
-                </para>
-            </section>
-        </section>
-        <section>
-            <title>Header Names Config</title>
-            <para>
-            Next under the list of applications you can override the defaults for the names of the header fields injected by the proxy (see Keycloak Identity Headers).
-            This mapping is optional.
-            <variablelist>
-                <varlistentry>
-                    <term>keycloak-subject</term>
-                    <listitem>
-                        <para>
-                            e.g. MYAPP_USER_ID
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>keycloak-username</term>
-                    <listitem>
-                        <para>
-                            e.g. MYAPP_USER_NAME
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>keycloak-email</term>
-                    <listitem>
-                        <para>
-                            e.g. MYAPP_USER_EMAIL
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>keycloak-name</term>
-                    <listitem>
-                        <para>
-                            e.g. MYAPP_USER_ID
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>keycloak-access-token</term>
-                    <listitem>
-                        <para>
-                            e.g. MYAPP_ACCESS_TOKEN
-                        </para>
-                    </listitem>
-                </varlistentry>
-            </variablelist>
-            </para>
-        </section>
-    </section>
-    <section>
-        <title>Keycloak Identity Headers</title>
-        <para>
-            When forwarding requests to the proxied server, Keycloak Proxy will set some additional headers with values from the
-            OIDC identity token it received for authentication.
-            <variablelist>
-                <varlistentry>
-                    <term>KEYCLOAK_SUBJECT</term>
-                    <listitem>
-                        <para>
-                            User id. Corresponds to JWT <literal>sub</literal> and will be the user id Keycloak uses to store
-                            this user.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>KEYCLOAK_USERNAME</term>
-                    <listitem>
-                        <para>
-                            Username. Corresponds to JWT <literal>preferred_username</literal>
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>KEYCLOAK_EMAIL</term>
-                    <listitem>
-                        <para>
-                            Email address of user if set.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>KEYCLOAK_NAME</term>
-                    <listitem>
-                        <para>
-                            Full name of user if set.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>KEYCLOAK_ACCESS_TOKEN</term>
-                    <listitem>
-                        <para>
-                            Send the access token in this header if the proxy was configured to send it.  This token can
-                            be used to make bearer token requests.
-                        </para>
-                    </listitem>
-                </varlistentry>
-            </variablelist>
-            Header field names can be configured using a map of <literal>header-names</literal> in configuration file:
-            <programlisting><![CDATA[
-{
-    "header-names" {
-        "keycloak-subject": "MY_SUBJECT"
-    }
-}
-            ]]></programlisting>
-        </para>
-    </section>
+<chapter id="proxy">
+    <title>Keycloak Security Proxy</title>
+    <para>
+        Keycloak has an HTTP(S) proxy that you can put in front of web applications and services where it is not possible
+        to install the keycloak adapter.  You can set up URL filters so that certain URLs are secured either by browser login
+        and/or bearer token authentication.  You can also define role constraints for URL patterns within your applications.
+    </para>
+    <section>
+        <title>Proxy Install and Run</title>
+        <para>Download the keycloak proxy distribution from the Keycloak download pages and unzip it.
+<programlisting>
+$ unzip keycloak-proxy-dist.zip
+</programlisting>
+        </para>
+        <para>
+            To run it you must have a proxy config file (which we'll discuss in a moment).
+<programlisting>
+$ java -jar bin/launcher.jar [your-config.json]
+</programlisting>
+        </para>
+        <para>
+            If you do not specify a path to the proxy config file, the launcher will look in the current working directory
+            for the file named <literal>proxy.json</literal>
+        </para>
+    </section>
+    <section>
+        <title>Proxy Configuration</title>
+        <para>
+            Here's an example configuration file.
+<programlisting><![CDATA[
+{
+    "target-url": "http://localhost:8082",
+    "send-access-token": true,
+    "bind-address": "localhost",
+    "http-port": "8080",
+    "https-port": "8443",
+    "keystore": "classpath:ssl.jks",
+    "keystore-password": "password",
+    "key-password": "password",
+    "applications": [
+        {
+            "base-path": "/customer-portal",
+            "error-page": "/error.html",
+            "adapter-config": {
+                "realm": "demo",
+                "resource": "customer-portal",
+                "realm-public-key": "MIGfMA0GCSqGSIb",
+                "auth-server-url": "http://localhost:8081/auth",
+                "ssl-required" : "external",
+                "principal-attribute": "name",
+                "credentials": {
+                    "secret": "password"
+                }
+            }
+            ,
+            "constraints": [
+                {
+                    "pattern": "/users/*",
+                    "roles-allowed": [
+                        "user"
+                    ]
+                },
+                {
+                    "pattern": "/admins/*",
+                    "roles-allowed": [
+                        "admin"
+                    ]
+                },
+                {
+                    "pattern": "/users/permit",
+                    "permit": true
+                },
+                {
+                    "pattern": "/users/deny",
+                    "deny": true
+                }
+            ]
+        }
+    ]
+}]]>
+</programlisting>
+        </para>
+        <section>
+            <title>Basic Config</title>
+        <para>
+            The basic configuration options for the server are as follows:
+            <variablelist>
+                <varlistentry>
+                    <term>target-url</term>
+                    <listitem>
+                        <para>
+                            The URL this server is proxying <emphasis>REQUIRED.</emphasis>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>send-access-token</term>
+                    <listitem>
+                        <para>
+                            Boolean flag.  If true, this will send the access token via the KEYCLOAK_ACCESS_TOKEN header to the
+                            proxied server. <emphasis>OPTIONAL.</emphasis>.  Default is false.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>bind-address</term>
+                    <listitem>
+                        <para>
+                            DNS name or IP address to bind the proxy server's sockets to.
+                            <emphasis>OPTIONAL.</emphasis>.  The default value is <emphasis>localhost</emphasis>
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>http-port</term>
+                    <listitem>
+                        <para>
+                            Port to listen for HTTP requests.  If you do not specify this value, then the proxy will
+                            not listen for regular HTTP requests.
+                            <emphasis>OPTIONAL.</emphasis>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>https-port</term>
+                    <listitem>
+                        <para>
+                            Port to listen for HTTPS requests.  If you do not specify this value, then the proxy will
+                            not listen for HTTPS requests.
+                            <emphasis>OPTIONAL.</emphasis>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>keystore</term>
+                    <listitem>
+                        <para>
+                            Path to a Java keystore file that contains private key and certificate for the server to be
+                            able to handle HTTPS requests.  Can be a file path, or, if you prefix it with <literal>classpath:</literal>
+                            it will look for this file in the classpath.
+                            <emphasis>OPTIONAL.</emphasis>.  If you have enabled HTTPS, but have not defined a keystore, the proxy
+                            will auto-generate a self-signed certificate and use that.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>buffer-size</term>
+                    <listitem>
+                        <para>
+                            HTTP server socket buffer size.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>buffers-per-region</term>
+                    <listitem>
+                        <para>
+                            HTTP server socket buffers per region.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>io-threads</term>
+                    <listitem>
+                        <para>
+                            Number of threads to handle IO.  Usually default is good enough.  <emphasis>OPTIONAL.</emphasis>.
+                            The default is the number of available processors * 2.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>worker-threads</term>
+                    <listitem>
+                        <para>
+                            Number of threads to handle requests.  Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
+                            The default is the number of available processors * 16.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+        </section>
+        <section>
+            <title>Application Config</title>
+            <para>
+                Next under the <literal>applications</literal> array attribute, you can define one or more applications per host you are proxying.
+                <variablelist>
+                    <varlistentry>
+                        <term>base-path</term>
+                        <listitem>
+                            <para>
+                                The base context root for the application.  Must start with '/' <emphasis>REQUIRED.</emphasis>.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>error-page</term>
+                        <listitem>
+                            <para>
+                                If the proxy has an error, it will display the target application's error page relative URL <emphasis>OPTIONAL.</emphasis>.
+                                This is a relative path to the base-path.  In the example above it would be <literal>/customer-portal/error.html</literal>.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>adapter-config</term>
+                        <listitem>
+                            <para>
+                                <emphasis>REQUIRED.</emphasis>.  Same configuration as any other keycloak adapter.  See <link linkend='adapter-config'>Adapter Config</link>
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                </variablelist>
+            </para>
+            <section>
+                <title>Constraint Config</title>
+                <para>
+                    Next under each application you can define one or more constraints in the <literal>constraints</literal> array attribute.
+                    A constraint defines a URL pattern relative to the base-path.  You can deny, permit, or require authentication for
+                    a specific URL pattern.  You can specify roles allowed for that path as well.  More specific constraints will take
+                    precedence over more general ones.
+                    <variablelist>
+                        <varlistentry>
+                            <term>pattern</term>
+                            <listitem>
+                                <para>
+                                    URL pattern to match relative to the base-path of the application.  Must start with '/' <emphasis>REQUIRED.</emphasis>.
+                                    You may only have one wildcard and it must come at the end of the pattern.  Valid <literal>/foo/bar/*</literal> and  <literal>/foo/*.txt</literal>
+                                    Not valid: <literal>/*/foo/*</literal>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>roles-allowed</term>
+                            <listitem>
+                                <para>
+                                    Array of strings of roles allowed to access this url pattern. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>methods</term>
+                            <listitem>
+                                <para>
+                                    Array of strings of HTTP methods that will exclusively match this pattern and HTTP request. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>excluded-methods</term>
+                            <listitem>
+                                <para>
+                                    Array of strings of HTTP methods that will be ignored when match this pattern. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>deny</term>
+                            <listitem>
+                                <para>
+                                    Deny all access to this URL pattern. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>permit</term>
+                            <listitem>
+                                <para>
+                                    Permit all access without requiring authentication or a role mapping. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>permit-and-inject</term>
+                            <listitem>
+                                <para>
+                                    Permit all access, but inject the headers, if user is already authenticated.<emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                        <varlistentry>
+                            <term>authenticate</term>
+                            <listitem>
+                                <para>
+                                    Require authentication for this pattern, but no role mapping. <emphasis>OPTIONAL.</emphasis>.
+                                </para>
+                            </listitem>
+                        </varlistentry>
+                    </variablelist>
+                </para>
+            </section>
+        </section>
+        <section>
+            <title>Header Names Config</title>
+            <para>
+            Next under the list of applications you can override the defaults for the names of the header fields injected by the proxy (see Keycloak Identity Headers).
+            This mapping is optional.
+            <variablelist>
+                <varlistentry>
+                    <term>keycloak-subject</term>
+                    <listitem>
+                        <para>
+                            e.g. MYAPP_USER_ID
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>keycloak-username</term>
+                    <listitem>
+                        <para>
+                            e.g. MYAPP_USER_NAME
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>keycloak-email</term>
+                    <listitem>
+                        <para>
+                            e.g. MYAPP_USER_EMAIL
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>keycloak-name</term>
+                    <listitem>
+                        <para>
+                            e.g. MYAPP_USER_ID
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>keycloak-access-token</term>
+                    <listitem>
+                        <para>
+                            e.g. MYAPP_ACCESS_TOKEN
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+            </para>
+        </section>
+    </section>
+    <section>
+        <title>Keycloak Identity Headers</title>
+        <para>
+            When forwarding requests to the proxied server, Keycloak Proxy will set some additional headers with values from the
+            OIDC identity token it received for authentication.
+            <variablelist>
+                <varlistentry>
+                    <term>KEYCLOAK_SUBJECT</term>
+                    <listitem>
+                        <para>
+                            User id. Corresponds to JWT <literal>sub</literal> and will be the user id Keycloak uses to store
+                            this user.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_USERNAME</term>
+                    <listitem>
+                        <para>
+                            Username. Corresponds to JWT <literal>preferred_username</literal>
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_EMAIL</term>
+                    <listitem>
+                        <para>
+                            Email address of user if set.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_NAME</term>
+                    <listitem>
+                        <para>
+                            Full name of user if set.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>KEYCLOAK_ACCESS_TOKEN</term>
+                    <listitem>
+                        <para>
+                            Send the access token in this header if the proxy was configured to send it.  This token can
+                            be used to make bearer token requests.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+            Header field names can be configured using a map of <literal>header-names</literal> in configuration file:
+            <programlisting><![CDATA[
+{
+    "header-names" {
+        "keycloak-subject": "MY_SUBJECT"
+    }
+}
+            ]]></programlisting>
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/roles.xml b/docbook/reference/en/en-US/modules/roles.xml
index 97e80d5..9cd6176 100755
--- a/docbook/reference/en/en-US/modules/roles.xml
+++ b/docbook/reference/en/en-US/modules/roles.xml
@@ -1,31 +1,31 @@
-<chapter id="roles">
-    <title>Roles</title>
-    <para>
-        In Keycloak, roles (or permissions) can be defined globally at the realm level, or individually per application.
-        Each role has a name which must be unique at the level it is defined in, i.e. you can have only one "admin" role at
-        the realm level.  You may have that a role named "admin" within an Application too, but "admin" must be unique
-        for that application.
-    </para>
-    <para>
-        The description of a role is displayed in the OAuth Grant page when Keycloak is processing a browser OAuth
-        Grant request.  Look for more features being added here in the future like internationalization and other fine
-        grain options.
-    </para>
-
-    <section>
-        <title>Composite Roles</title>
-        <para>
-            Any realm or application level role can be turned into a Composite Role.  A Composite Role is a role that has
-            one or more additional roles associated with it.  I guess another term for it could be Role Group.
-            When a composite role is mapped to the user, the user gains the permission of that role, plus any other role the
-            composite is associated with.  This association is dynamic.  So, if you add  or remove an associated role from
-            the composite, then all users that are mapped to the composite role will automatically have those permissions
-            added or removed.  Composites can also be used to define Client scopes.
-        </para>
-        <para>
-            Composite roles can be associated with any type of role Realm or Application.  In the admin console simple
-            flip the composite switch in the Role detail, and you will get a screen that will allow you to associate roles
-            with the composite.
-        </para>
-    </section>
+<chapter id="roles">
+    <title>Roles</title>
+    <para>
+        In Keycloak, roles (or permissions) can be defined globally at the realm level, or individually per application.
+        Each role has a name which must be unique at the level it is defined in, i.e. you can have only one "admin" role at
+        the realm level.  You may have that a role named "admin" within an Application too, but "admin" must be unique
+        for that application.
+    </para>
+    <para>
+        The description of a role is displayed in the OAuth Grant page when Keycloak is processing a browser OAuth
+        Grant request.  Look for more features being added here in the future like internationalization and other fine
+        grain options.
+    </para>
+
+    <section>
+        <title>Composite Roles</title>
+        <para>
+            Any realm or application level role can be turned into a Composite Role.  A Composite Role is a role that has
+            one or more additional roles associated with it.  I guess another term for it could be Role Group.
+            When a composite role is mapped to the user, the user gains the permission of that role, plus any other role the
+            composite is associated with.  This association is dynamic.  So, if you add  or remove an associated role from
+            the composite, then all users that are mapped to the composite role will automatically have those permissions
+            added or removed.  Composites can also be used to define Client scopes.
+        </para>
+        <para>
+            Composite roles can be associated with any type of role Realm or Application.  In the admin console simple
+            flip the composite switch in the Role detail, and you will get a screen that will allow you to associate roles
+            with the composite.
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/saml.xml b/docbook/reference/en/en-US/modules/saml.xml
index 4f4ffb7..de289b8 100755
--- a/docbook/reference/en/en-US/modules/saml.xml
+++ b/docbook/reference/en/en-US/modules/saml.xml
@@ -1,201 +1,201 @@
-<chapter id="saml">
-    <title>SAML SSO</title>
-    <para>
-        Keycloak supports SAML 2.0 for registered applications.  Both POST and Redirect bindings are supported.  You can choose
-        to require client signature validation and can have the server sign and/or encrypt responses as well.  We do not
-        yet support logout via redirects.  All logouts happen via a background POST binding request to the application
-        that will be logged out.  We do not support SAML 1.1 either.  If you want support for either of those, please
-        log a JIRA request and we'll schedule it.
-    </para>
-    <para>
-        When you create an application in the admin console, you can choose which protocol the application will log in with.
-        In the application create screen, choose <literal>saml</literal> from the protocol list.  After that there
-        are a bunch of configuration options.  Here is a description of each item:
-    </para>
-    <para>
-        <variablelist>
-            <varlistentry>
-                <term>Include AuthnStatement</term>
-                <listitem>
-                    <para>
-                        SAML login responses may specify the authentication method used (password, etc.) as well as
-                        a timestamp of the login.  Setting this to on will include that statement in the response document.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Multi-valued Roles</term>
-                <listitem>
-                    <para>
-                        If this switch is off, any user role mappings will have a corresponding attribute created for it.
-                        If this switch is turn on, only one role attribute will be created, but it will have
-                        multiple values within in.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Sign Documents</term>
-                <listitem>
-                    <para>
-                        When turned on, Keycloak will sign the document using the realm's private key.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Sign Assertions</term>
-                <listitem>
-                    <para>
-                        With the <literal>Sign Documents</literal> switch signs the whole document.  With this setting
-                        you just assign the assertions of the document.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Signature Algorithm</term>
-                <listitem>
-                    <para>
-                        Choose between a variety of algorithms for signing SAML documents.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Encrypt Assertions</term>
-                <listitem>
-                    <para>
-                        Encrypt assertions in SAML documents with the realm's private key.  The AES algorithm is used
-                        with a key size of 128 bits.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Client Signature Required</term>
-                <listitem>
-                    <para>
-                        Expect that documents coming from a client are signed.  Keycloak will validate this signature
-                        using the client keys set up in the <literal>Application Keys</literal> submenu item.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Force POST Binding</term>
-                <listitem>
-                    <para>
-                        By default, Keycloak will respond using the initial SAML binding of the original request.  By turning
-                        on this switch, you will force Keycloak to always respond using the SAML POST Binding even if the
-                        original request was the Redirect binding.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Front Channel Logout</term>
-                <listitem>
-                    <para>
-                        If true, this application requires a browser redirect to be able to perform a logout.  For example,
-                        the application may require a cookie to be reset which could only be done by a done via a redirect.
-                        If this switch is false, then Keycloak will invoke a background SAML request to logout the application.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Force Name ID Format</term>
-                <listitem>
-                    <para>
-                        If the request has a name ID policy, ignore it and used the value configured in the admin console
-                        under Name ID Format
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Name ID Format</term>
-                <listitem>
-                    <para>
-                        Name ID Format for the subject.  If no name ID policy is specified in the request or if the
-                        Force Name ID Format attribute is true, this value is used.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Master SAML Processing URL</term>
-                <listitem>
-                    <para>
-                        This URL will be used for all SAML requests and responsed directed to the SP.  It will be used
-                        as the Assertion Consumer Service URL and the Single Logout Service URL.  If a login request
-                        contains the Assertion Consumer Service URL, that will take precedence, but this URL must be valided
-                        by a registered Valid Redirect URI pattern
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Assertion Consumer Service POST Binding URL</term>
-                <listitem>
-                    <para>
-                        POST Binding URL for the Assertion Consumer Service.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Assertion Consumer Service Redirect Binding URL</term>
-                <listitem>
-                    <para>
-                        Redirect Binding URL for the Assertion Consumer Service.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Logout Service POST Binding URL</term>
-                <listitem>
-                    <para>
-                        POST Binding URL for the Logout Service.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>Logout Service Redirect Binding URL</term>
-                <listitem>
-                    <para>
-                        Redirect Binding URL for the Logout Service.
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </para>
-    <para>
-        For login to work, Keycloak needs to be able to resolve the URL for the Assertion Consumer Service of the SP.  If
-        you are relying on the SP to provide this URL in the login request, then you must register valid redirect uri patterns
-        so that this URL can be validated.  You can set the Master SAML Processing URL as well, or alternatively, you can
-        specify the Assertion Consumer Service URL per binding.
-    </para>
-    <para>
-        For logout to work, you must specify a Master SAML Processing URL, or the Loging Service URL for the binding
-        you want Keycloak to use.
-    </para>
-    <para>
-        One thing to note is that roles are not treated as a hierarchy.  So, any role mappings will just be added
-        to the role attributes in the SAML document using their basic name.  So, if you have multiple application roles
-        you might have name collisions.  You can use the Scope Mapping menu item to control which role mappings are set
-        in the response.
-    </para>
-    <section>
-        <title>SAML Entity Descriptor</title>
-        <para>
-            If you go into the admin console in the application list menu page you will see an <literal>Import</literal>
-            button.  If you click on that you can import SAML Service Provider definitions using the <ulink url="http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf">Entity Descriptor</ulink>
-            format described in SAML 2.0.  You should review all the information there to make sure everything is set up correctly.
-        </para>
-        <para>
-            Each realm has a URL where you can view the XML entity descriptor for the IDP.  <literal>root/auth/realms/{realm}/protocol/saml/descriptor</literal>
-        </para>
-    </section>
-    <section>
-        <title>IDP Initiated Login</title>
-        <para>
-            IDP Initiated Login is a feature that where you can set up a URL on the Keycloak server that will log you into a specific application/client.  To set this up
-            go to the client page in the admin console of the client you want to set this up for.  Specify the <literal>IDP Initiated SSO URL Name</literal>.  This is a simple string
-            with no whitespace in it.  After this you can reference your client at the following URL:  <literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}</literal>
-        </para>
-        <para>
-            If your client requires a special relay state, you can also configure this in the admin console.  Alternatively, you can specify the relay state in a
-            <literal>RelayState</literal> query parameter, i.e. :  <literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}?RelayState=thestate</literal>
-        </para>
-    </section>
-</chapter>
+<chapter id="saml">
+    <title>SAML SSO</title>
+    <para>
+        Keycloak supports SAML 2.0 for registered applications.  Both POST and Redirect bindings are supported.  You can choose
+        to require client signature validation and can have the server sign and/or encrypt responses as well.  We do not
+        yet support logout via redirects.  All logouts happen via a background POST binding request to the application
+        that will be logged out.  We do not support SAML 1.1 either.  If you want support for either of those, please
+        log a JIRA request and we'll schedule it.
+    </para>
+    <para>
+        When you create an application in the admin console, you can choose which protocol the application will log in with.
+        In the application create screen, choose <literal>saml</literal> from the protocol list.  After that there
+        are a bunch of configuration options.  Here is a description of each item:
+    </para>
+    <para>
+        <variablelist>
+            <varlistentry>
+                <term>Include AuthnStatement</term>
+                <listitem>
+                    <para>
+                        SAML login responses may specify the authentication method used (password, etc.) as well as
+                        a timestamp of the login.  Setting this to on will include that statement in the response document.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Multi-valued Roles</term>
+                <listitem>
+                    <para>
+                        If this switch is off, any user role mappings will have a corresponding attribute created for it.
+                        If this switch is turn on, only one role attribute will be created, but it will have
+                        multiple values within in.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Sign Documents</term>
+                <listitem>
+                    <para>
+                        When turned on, Keycloak will sign the document using the realm's private key.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Sign Assertions</term>
+                <listitem>
+                    <para>
+                        With the <literal>Sign Documents</literal> switch signs the whole document.  With this setting
+                        you just assign the assertions of the document.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Signature Algorithm</term>
+                <listitem>
+                    <para>
+                        Choose between a variety of algorithms for signing SAML documents.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Encrypt Assertions</term>
+                <listitem>
+                    <para>
+                        Encrypt assertions in SAML documents with the realm's private key.  The AES algorithm is used
+                        with a key size of 128 bits.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Client Signature Required</term>
+                <listitem>
+                    <para>
+                        Expect that documents coming from a client are signed.  Keycloak will validate this signature
+                        using the client keys set up in the <literal>Application Keys</literal> submenu item.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Force POST Binding</term>
+                <listitem>
+                    <para>
+                        By default, Keycloak will respond using the initial SAML binding of the original request.  By turning
+                        on this switch, you will force Keycloak to always respond using the SAML POST Binding even if the
+                        original request was the Redirect binding.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Front Channel Logout</term>
+                <listitem>
+                    <para>
+                        If true, this application requires a browser redirect to be able to perform a logout.  For example,
+                        the application may require a cookie to be reset which could only be done by a done via a redirect.
+                        If this switch is false, then Keycloak will invoke a background SAML request to logout the application.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Force Name ID Format</term>
+                <listitem>
+                    <para>
+                        If the request has a name ID policy, ignore it and used the value configured in the admin console
+                        under Name ID Format
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Name ID Format</term>
+                <listitem>
+                    <para>
+                        Name ID Format for the subject.  If no name ID policy is specified in the request or if the
+                        Force Name ID Format attribute is true, this value is used.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Master SAML Processing URL</term>
+                <listitem>
+                    <para>
+                        This URL will be used for all SAML requests and responsed directed to the SP.  It will be used
+                        as the Assertion Consumer Service URL and the Single Logout Service URL.  If a login request
+                        contains the Assertion Consumer Service URL, that will take precedence, but this URL must be valided
+                        by a registered Valid Redirect URI pattern
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Assertion Consumer Service POST Binding URL</term>
+                <listitem>
+                    <para>
+                        POST Binding URL for the Assertion Consumer Service.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Assertion Consumer Service Redirect Binding URL</term>
+                <listitem>
+                    <para>
+                        Redirect Binding URL for the Assertion Consumer Service.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Logout Service POST Binding URL</term>
+                <listitem>
+                    <para>
+                        POST Binding URL for the Logout Service.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Logout Service Redirect Binding URL</term>
+                <listitem>
+                    <para>
+                        Redirect Binding URL for the Logout Service.
+                    </para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </para>
+    <para>
+        For login to work, Keycloak needs to be able to resolve the URL for the Assertion Consumer Service of the SP.  If
+        you are relying on the SP to provide this URL in the login request, then you must register valid redirect uri patterns
+        so that this URL can be validated.  You can set the Master SAML Processing URL as well, or alternatively, you can
+        specify the Assertion Consumer Service URL per binding.
+    </para>
+    <para>
+        For logout to work, you must specify a Master SAML Processing URL, or the Loging Service URL for the binding
+        you want Keycloak to use.
+    </para>
+    <para>
+        One thing to note is that roles are not treated as a hierarchy.  So, any role mappings will just be added
+        to the role attributes in the SAML document using their basic name.  So, if you have multiple application roles
+        you might have name collisions.  You can use the Scope Mapping menu item to control which role mappings are set
+        in the response.
+    </para>
+    <section>
+        <title>SAML Entity Descriptor</title>
+        <para>
+            If you go into the admin console in the application list menu page you will see an <literal>Import</literal>
+            button.  If you click on that you can import SAML Service Provider definitions using the <ulink url="http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf">Entity Descriptor</ulink>
+            format described in SAML 2.0.  You should review all the information there to make sure everything is set up correctly.
+        </para>
+        <para>
+            Each realm has a URL where you can view the XML entity descriptor for the IDP.  <literal>root/auth/realms/{realm}/protocol/saml/descriptor</literal>
+        </para>
+    </section>
+    <section>
+        <title>IDP Initiated Login</title>
+        <para>
+            IDP Initiated Login is a feature that where you can set up a URL on the Keycloak server that will log you into a specific application/client.  To set this up
+            go to the client page in the admin console of the client you want to set this up for.  Specify the <literal>IDP Initiated SSO URL Name</literal>.  This is a simple string
+            with no whitespace in it.  After this you can reference your client at the following URL:  <literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}</literal>
+        </para>
+        <para>
+            If your client requires a special relay state, you can also configure this in the admin console.  Alternatively, you can specify the relay state in a
+            <literal>RelayState</literal> query parameter, i.e. :  <literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}?RelayState=thestate</literal>
+        </para>
+    </section>
+</chapter>
diff --git a/docbook/reference/en/en-US/modules/security-vulnerabilities.xml b/docbook/reference/en/en-US/modules/security-vulnerabilities.xml
index 7107fb7..d7fadb0 100755
--- a/docbook/reference/en/en-US/modules/security-vulnerabilities.xml
+++ b/docbook/reference/en/en-US/modules/security-vulnerabilities.xml
@@ -1,177 +1,177 @@
-<chapter id="security_vulnerabilities">
-    <title>Security Vulnerabilities</title>
-    <para>
-        This chapter discusses possible security vulnerabilities Keycloak could have, how Keycloak mitigates those
-        vulnerabilities, and what steps you need to do to configure Keycloak to mitigate some vulnerabilities.  A good list
-        of potential vulnerabilities and what security implementations should do to mitigate them can be found in the
-        <ulink url="http://tools.ietf.org/html/rfc6819">OAuth 2.0 Threat Model</ulink> document put out by the IETF.  Many of those vulnerabilities are discussed here.
-    </para>
-    <section>
-        <title>SSL/HTTPS Requirement</title>
-        <para>
-            If you do not use SSL/HTTPS for all communication between the Keycloak auth server and the clients it secures
-            you will be very vulnerable to man in the middle attacks.  OAuth 2.0/OpenID Connect uses access tokens for
-            security.  Without SSL/HTTPS, attackers can sniff your network and obtain an access token.  Once they have an
-            access token they can do any operation that the token has been given permission for.
-        </para>
-        <para>
-            Keycloak has <link linkend="ssl_modes">three modes for SSL/HTTPS</link>.  SSL can be hard to set up, so out of the box, Keycloak allows
-            non-HTTPS communication over private IP addresses like localhost, 192.168.x.x, and other private IP addresses.
-            In production, you should make sure SSL is enabled and required across the board.
-        </para>
-        <para>
-            On the adapter/client side, Keycloak allows you to turn off the SSL trust manager.  The trust manager ensures
-            identity the client is talking to.  It checks the DNS domain name against the server's certificate.  In production
-            you should make sure that each of your client adapters is configured to use a truststore.  Otherwise you are vulnerable
-            to DNS man in the middle attacks.
-        </para>
-    </section>
-    <section>
-        <title>CSRF Attacks</title>
-        <para>
-            Cross-site request forgery (CSRF) is a web-based attack whereby HTTP
-            requests are transmitted from a user that the web site trusts or has
-            authenticated (e.g., via HTTP redirects or HTML forms).  Any site that uses
-            cookie based authentication is vulnerable for these types of attacks.  These attacks are mitigated
-            by matching a state cookie against a posted form or query parameter.
-        </para>
-        <para>
-            OAuth 2.0 login specification requires that a state cookie be used and matched against a transmitted state
-            parameter.  Keycloak fully implements this part of the specification so all logins are protected.
-        </para>
-        <para>
-            The Keycloak adminstration console is a pure Javascript/HTML5 application that makes REST calls to the
-            backend Keycloak admin API.  These calls all require bearer token authentication and are made via Javascript
-            Ajax calls.  CSRF does not apply here.  The admin REST API can also be configured to validate CORS origins
-            as well.
-        </para>
-        <para>
-            The only part of Keycloak that really falls into CSRF is the user account management pages.  To mitigate this
-            Keycloak sets a state cookie and also embeds the value of this state cookie within hidden form fields or
-            query parameters in action links.  This query or form parameter is checked against the state cookie to verify
-            that the call was made by the user.
-        </para>
-    </section>
-    <section>
-        <title>Clickjacking</title>
-        <para>
-            With clickjacking, a malicious site loads the target site in a
-            transparent iFrame overlaid on top of a set of dummy
-            buttons that are carefully constructed to be placed directly under
-            important buttons on the target site.  When a user clicks a visible
-            button, they are actually clicking a button (such as an "Authorize"
-            button) on the hidden page.  An attacker can steal a user's authentication credentials and
-            access their resources.
-        </para>
-        <para>
-            By default, every response by Keycloak sets some specific browser headers that can prevent this from happening
-            specifically <ulink url="http://tools.ietf.org/html/rfc7034">X-FRAME_OPTIONS</ulink> and <ulink url="http://www.w3.org/TR/CSP/">Content-Security-Policy</ulink>.  You
-            should take a look at both of these headers.  In the admin console you can specify the values these headers will
-            have.  By default, Keycloak only sets up a same-origin policy for iframes.
-        </para>
-    </section>
-    <section>
-        <title>Compromised Access Codes</title>
-        <para>
-            It would be very hard for an attacker to compromise Keycloak access codes.  Keycloak generates a cryptographically
-            strong random value for its access codes so it would be very hard to guess an access token.
-            An access code can only be turned into an access token once so it can't be replayed.  In the admin console
-            you can specify how long an access token is valid for.  This value should be really short.  Like a seconds.
-            Just long enough for the client to make the request to turn the code into an token.
-        </para>
-    </section>
-    <section>
-        <title>Compromised access and refresh tokens</title>
-        <para>
-            There's a few things you can do to mitigate access tokens and refresh tokens from being stolen.
-            Most importantly is to enforce SSL/HTTPS communication between Keycloak and its clients and applications.
-            Short lifespans (minutes) for access tokens allows Keycloak to check the validity of a refresh token.  Making
-            sure refresh tokens always stay private to the client and are never transmitted ever is very important as well.
-        </para>
-        <para>
-            If an access token or refresh token is compromised, the first thing you should do is go to the admin console
-            and push a not-before revocation policy to all applications.  This will enforce that any tokens issued
-            prior to that date are now invalid.  You can also disable specific applications, clients, and users if you
-            feel that any one of those entities is completely compromised.
-        </para>
-    </section>
-    <section>
-        <title>Open redirectors</title>
-        <para>
-            An attacker could use the end-user authorization endpoint and the
-            redirect URI parameter to abuse the authorization server as an open
-            redirector.  An open redirector is an endpoint using a parameter to
-            automatically redirect a user agent to the location specified by the
-            parameter value without any validation.  An attacker could utilize a user's trust in an authorization
-            server to launch a phishing attack.
-        </para>
-        <para>
-            Keycloak requires that all registered applications and clients register at least one redirection uri pattern.
-            Any time a client asks Keycloak to perform a redirect (on login or logout for example), Keycloak will
-            check the redirect uri vs. the list of valid registered uri patterns.  It is important that clients and
-            applications register as specific a URI pattern as possible to mitigate open redirector attacks.
-        </para>
-    </section>
-    <section>
-        <title>Password guess: brute force attacks</title>
-        <para>
-            A brute force attack happens when an attacker is trying to guess a user's password.  Keycloak has some
-            limited brute force detection capabilities.  If turned on, a user account will be temporarily disabled
-            if a threshold of login failures is reached.  The downside of this is that this makes Keycloak vulnerable
-            to denial of service attacks.  Eventually we will expand this functionality to take client IP address into
-            account when deciding whether to block a user.
-        </para>
-        <para>
-            Another thing you can do to prevent password guessing is to point a tool like <ulink url="http://fail2ban.org">Fail2Ban</ulink> to the Keycloak
-            server's log file.  Keycloak logs every login failure and client IP address that had the failure.
-        </para>
-        <para>
-            In the admin console, per realm, you can set up a password policy to enforce that users pick hard to guess passwords.
-            A password has to match all policies. The password policies that can be configured are hash iterations, length, digits,
-            lowercase, uppercase, special characters, not username, regex patterns, password history and force expired password update. 
-            Force expired password update policy forces or requires password updates after specified span of time. Password history policy 
-            restricts a user from resetting his password to N old expired passwords. Multiple regex patterns, separated by comma, 
-            can be specified in regex pattern policy. If there's more than one regex added, password has to match all fully.
-            Increasing number of Hash Iterations (n) does not worsen anything (and certainly not the cipher) and it greatly increases the 
-            resistance to dictionary attacks. However the drawback to increasing n is that it has some cost (CPU usage, energy, delay) for 
-            the legitimate parties. Increasing n also slightly increases the odds that a random password gives the same result as the right 
-            password due to hash collisions, and is thus a false but accepted password; however that remains very unlikely, in the order of 
-            n*[1/(2^256)] for practical values of n, and can be entirely ignored in practice. Keycloak also uses PBKDF2 internally to 
-            cryptographically derive passwords to refine and improve the ratio of cost between attacker and legitimate parties.
-            Good practice is to pay attention to the time complexity of hash_password and hash; then increase n as much as tolerable in 
-            the situation(s) at hand and and revise parameters such as n every few years to account for time complexity trade off.
-        </para>
-        <para>
-            Finally, the best way to mitigate against brute force attacks is to require user to set up a one-time-password (OTP).
-        </para>
-    </section>
-    <section>
-        <title>Password database compromised</title>
-        <para>
-            Keycloak does not store passwords in raw text.  It stores a hash of them.  Because of performance reasons,
-            Keycloak only hashes passwords once.  While a human could probably never crack a hashed password, it is very
-            possible that a computer could.  The security community suggests around 20,000 (yes thousand!) hashing iterations
-            to be done to each password.  This number grows every year due to increasing computing power (It was 1000 12 years ago).
-            The problem with this is that password hashing is a huge performance hit as each login would require the entered
-            password to be hashed that many times and compared to the stored hash.  So, its up to the admin to configure the
-            password hash iterations.  This can be done in the admin console password policy configuration.  Again, the default
-            value is 1 as we thought it might be more important for Keycloak to scale out of the box.  There's a lot of
-            other measures admins can do to protect their password databases.
-        </para>
-    </section>
-    <section>
-        <title>SQL Injection attacks</title>
-        <para>
-            At this point in time, there is no knowledge of any SQL injection vulnerabilities in Keycloak
-        </para>
-    </section>
-    <section>
-        <title>Limiting Scope</title>
-        <para>
-            Using the <literal>Scope</literal> menu in the admin console for clients, you can control
-            exactly which role mappings will be included within the token sent back to the client application.  This
-            allows you to limit the scope of permissions given to the client which is great if the client isn't
-            very trusted and is known to not being very careful with its tokens.
-        </para>
-    </section>
+<chapter id="security_vulnerabilities">
+    <title>Security Vulnerabilities</title>
+    <para>
+        This chapter discusses possible security vulnerabilities Keycloak could have, how Keycloak mitigates those
+        vulnerabilities, and what steps you need to do to configure Keycloak to mitigate some vulnerabilities.  A good list
+        of potential vulnerabilities and what security implementations should do to mitigate them can be found in the
+        <ulink url="http://tools.ietf.org/html/rfc6819">OAuth 2.0 Threat Model</ulink> document put out by the IETF.  Many of those vulnerabilities are discussed here.
+    </para>
+    <section>
+        <title>SSL/HTTPS Requirement</title>
+        <para>
+            If you do not use SSL/HTTPS for all communication between the Keycloak auth server and the clients it secures
+            you will be very vulnerable to man in the middle attacks.  OAuth 2.0/OpenID Connect uses access tokens for
+            security.  Without SSL/HTTPS, attackers can sniff your network and obtain an access token.  Once they have an
+            access token they can do any operation that the token has been given permission for.
+        </para>
+        <para>
+            Keycloak has <link linkend="ssl_modes">three modes for SSL/HTTPS</link>.  SSL can be hard to set up, so out of the box, Keycloak allows
+            non-HTTPS communication over private IP addresses like localhost, 192.168.x.x, and other private IP addresses.
+            In production, you should make sure SSL is enabled and required across the board.
+        </para>
+        <para>
+            On the adapter/client side, Keycloak allows you to turn off the SSL trust manager.  The trust manager ensures
+            identity the client is talking to.  It checks the DNS domain name against the server's certificate.  In production
+            you should make sure that each of your client adapters is configured to use a truststore.  Otherwise you are vulnerable
+            to DNS man in the middle attacks.
+        </para>
+    </section>
+    <section>
+        <title>CSRF Attacks</title>
+        <para>
+            Cross-site request forgery (CSRF) is a web-based attack whereby HTTP
+            requests are transmitted from a user that the web site trusts or has
+            authenticated (e.g., via HTTP redirects or HTML forms).  Any site that uses
+            cookie based authentication is vulnerable for these types of attacks.  These attacks are mitigated
+            by matching a state cookie against a posted form or query parameter.
+        </para>
+        <para>
+            OAuth 2.0 login specification requires that a state cookie be used and matched against a transmitted state
+            parameter.  Keycloak fully implements this part of the specification so all logins are protected.
+        </para>
+        <para>
+            The Keycloak adminstration console is a pure Javascript/HTML5 application that makes REST calls to the
+            backend Keycloak admin API.  These calls all require bearer token authentication and are made via Javascript
+            Ajax calls.  CSRF does not apply here.  The admin REST API can also be configured to validate CORS origins
+            as well.
+        </para>
+        <para>
+            The only part of Keycloak that really falls into CSRF is the user account management pages.  To mitigate this
+            Keycloak sets a state cookie and also embeds the value of this state cookie within hidden form fields or
+            query parameters in action links.  This query or form parameter is checked against the state cookie to verify
+            that the call was made by the user.
+        </para>
+    </section>
+    <section>
+        <title>Clickjacking</title>
+        <para>
+            With clickjacking, a malicious site loads the target site in a
+            transparent iFrame overlaid on top of a set of dummy
+            buttons that are carefully constructed to be placed directly under
+            important buttons on the target site.  When a user clicks a visible
+            button, they are actually clicking a button (such as an "Authorize"
+            button) on the hidden page.  An attacker can steal a user's authentication credentials and
+            access their resources.
+        </para>
+        <para>
+            By default, every response by Keycloak sets some specific browser headers that can prevent this from happening
+            specifically <ulink url="http://tools.ietf.org/html/rfc7034">X-FRAME_OPTIONS</ulink> and <ulink url="http://www.w3.org/TR/CSP/">Content-Security-Policy</ulink>.  You
+            should take a look at both of these headers.  In the admin console you can specify the values these headers will
+            have.  By default, Keycloak only sets up a same-origin policy for iframes.
+        </para>
+    </section>
+    <section>
+        <title>Compromised Access Codes</title>
+        <para>
+            It would be very hard for an attacker to compromise Keycloak access codes.  Keycloak generates a cryptographically
+            strong random value for its access codes so it would be very hard to guess an access token.
+            An access code can only be turned into an access token once so it can't be replayed.  In the admin console
+            you can specify how long an access token is valid for.  This value should be really short.  Like a seconds.
+            Just long enough for the client to make the request to turn the code into an token.
+        </para>
+    </section>
+    <section>
+        <title>Compromised access and refresh tokens</title>
+        <para>
+            There's a few things you can do to mitigate access tokens and refresh tokens from being stolen.
+            Most importantly is to enforce SSL/HTTPS communication between Keycloak and its clients and applications.
+            Short lifespans (minutes) for access tokens allows Keycloak to check the validity of a refresh token.  Making
+            sure refresh tokens always stay private to the client and are never transmitted ever is very important as well.
+        </para>
+        <para>
+            If an access token or refresh token is compromised, the first thing you should do is go to the admin console
+            and push a not-before revocation policy to all applications.  This will enforce that any tokens issued
+            prior to that date are now invalid.  You can also disable specific applications, clients, and users if you
+            feel that any one of those entities is completely compromised.
+        </para>
+    </section>
+    <section>
+        <title>Open redirectors</title>
+        <para>
+            An attacker could use the end-user authorization endpoint and the
+            redirect URI parameter to abuse the authorization server as an open
+            redirector.  An open redirector is an endpoint using a parameter to
+            automatically redirect a user agent to the location specified by the
+            parameter value without any validation.  An attacker could utilize a user's trust in an authorization
+            server to launch a phishing attack.
+        </para>
+        <para>
+            Keycloak requires that all registered applications and clients register at least one redirection uri pattern.
+            Any time a client asks Keycloak to perform a redirect (on login or logout for example), Keycloak will
+            check the redirect uri vs. the list of valid registered uri patterns.  It is important that clients and
+            applications register as specific a URI pattern as possible to mitigate open redirector attacks.
+        </para>
+    </section>
+    <section>
+        <title>Password guess: brute force attacks</title>
+        <para>
+            A brute force attack happens when an attacker is trying to guess a user's password.  Keycloak has some
+            limited brute force detection capabilities.  If turned on, a user account will be temporarily disabled
+            if a threshold of login failures is reached.  The downside of this is that this makes Keycloak vulnerable
+            to denial of service attacks.  Eventually we will expand this functionality to take client IP address into
+            account when deciding whether to block a user.
+        </para>
+        <para>
+            Another thing you can do to prevent password guessing is to point a tool like <ulink url="http://fail2ban.org">Fail2Ban</ulink> to the Keycloak
+            server's log file.  Keycloak logs every login failure and client IP address that had the failure.
+        </para>
+        <para>
+            In the admin console, per realm, you can set up a password policy to enforce that users pick hard to guess passwords.
+            A password has to match all policies. The password policies that can be configured are hash iterations, length, digits,
+            lowercase, uppercase, special characters, not username, regex patterns, password history and force expired password update. 
+            Force expired password update policy forces or requires password updates after specified span of time. Password history policy 
+            restricts a user from resetting his password to N old expired passwords. Multiple regex patterns, separated by comma, 
+            can be specified in regex pattern policy. If there's more than one regex added, password has to match all fully.
+            Increasing number of Hash Iterations (n) does not worsen anything (and certainly not the cipher) and it greatly increases the 
+            resistance to dictionary attacks. However the drawback to increasing n is that it has some cost (CPU usage, energy, delay) for 
+            the legitimate parties. Increasing n also slightly increases the odds that a random password gives the same result as the right 
+            password due to hash collisions, and is thus a false but accepted password; however that remains very unlikely, in the order of 
+            n*[1/(2^256)] for practical values of n, and can be entirely ignored in practice. Keycloak also uses PBKDF2 internally to 
+            cryptographically derive passwords to refine and improve the ratio of cost between attacker and legitimate parties.
+            Good practice is to pay attention to the time complexity of hash_password and hash; then increase n as much as tolerable in 
+            the situation(s) at hand and and revise parameters such as n every few years to account for time complexity trade off.
+        </para>
+        <para>
+            Finally, the best way to mitigate against brute force attacks is to require user to set up a one-time-password (OTP).
+        </para>
+    </section>
+    <section>
+        <title>Password database compromised</title>
+        <para>
+            Keycloak does not store passwords in raw text.  It stores a hash of them.  Because of performance reasons,
+            Keycloak only hashes passwords once.  While a human could probably never crack a hashed password, it is very
+            possible that a computer could.  The security community suggests around 20,000 (yes thousand!) hashing iterations
+            to be done to each password.  This number grows every year due to increasing computing power (It was 1000 12 years ago).
+            The problem with this is that password hashing is a huge performance hit as each login would require the entered
+            password to be hashed that many times and compared to the stored hash.  So, its up to the admin to configure the
+            password hash iterations.  This can be done in the admin console password policy configuration.  Again, the default
+            value is 1 as we thought it might be more important for Keycloak to scale out of the box.  There's a lot of
+            other measures admins can do to protect their password databases.
+        </para>
+    </section>
+    <section>
+        <title>SQL Injection attacks</title>
+        <para>
+            At this point in time, there is no knowledge of any SQL injection vulnerabilities in Keycloak
+        </para>
+    </section>
+    <section>
+        <title>Limiting Scope</title>
+        <para>
+            Using the <literal>Scope</literal> menu in the admin console for clients, you can control
+            exactly which role mappings will be included within the token sent back to the client application.  This
+            allows you to limit the scope of permissions given to the client which is great if the client isn't
+            very trusted and is known to not being very careful with its tokens.
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/spring-boot-adapter.xml b/docbook/reference/en/en-US/modules/spring-boot-adapter.xml
index 0946e13..09dfc5e 100755
--- a/docbook/reference/en/en-US/modules/spring-boot-adapter.xml
+++ b/docbook/reference/en/en-US/modules/spring-boot-adapter.xml
@@ -1,72 +1,72 @@
-<section id="spring-boot-adapter">
-    <title>Spring Boot Adapter</title>
-    <para>
-        To be able to secure Spring Boot apps you must add the Keycloak Spring Boot adapter
-        JAR to your app. You then have to provide some extra configuration via normal Spring
-        Boot configuration (<literal>application.properties</literal>).  Let's go over these steps.
-    </para>
-    <section id="spring-boot-adapter-installation">
-        <title>Adapter Installation</title>
-        <para>
-            The Keycloak Spring Boot adapter takes advantage of Spring Boot's autoconfiguration so all
-            you need to do is add the Keycloak Spring Boot adapter JAR to your project. Depending on
-            what container you are using with Spring Boot, you also need to add the appropriate
-            Keycloak container adapter. If you are using Maven, add the following to your pom.xml (using
-            Tomcat as an example):
-        </para>
-        <para>
-            <programlisting>
-<![CDATA[
-<dependency>
-    <groupId>org.keycloak</groupId>
-    <artifactId>keycloak-spring-boot-adapter</artifactId>
-    <version>&project.version;</version>
-</dependency>
-<dependency>
-    <groupId>org.keycloak</groupId>
-    <artifactId>keycloak-tomcat8-adapter</artifactId>
-    <version>&project.version;</version>
-</dependency>
-]]>
-            </programlisting>
-        </para>
-    </section>
-
-    <section id="spring-boot-adapter-configuration">
-        <title>Required Spring Boot Adapter Configuration</title>
-        <para>
-            This section describes how to configure your Spring Boot app to use Keycloak.
-        </para>
-        <para>
-            Instead of a <literal>keycloak.json</literal> file, you configure the realm for the Spring
-            Boot Keycloak adapter via the normal Spring Boot configuration. For example:
-        </para>
-        <programlisting>
-<![CDATA[
-keycloak.realm = demorealm
-keycloak.realmKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCWYuxXmsmfV+Xc9Ik8QET8lD4wuHrJAXbbutS2O/eMjQQLNK7QDX/k/XhOkhxP0YBEypqeXeGaeQJjCxDhFjJXQuewUEMlmSja3IpoJ9/hFn4Cns4m7NGO+rtvnfnwgVfsEOS5EmZhRddp+40KBPPJfTH6Vgu6KjQwuFPj6DTwIDAQAB
-keycloak.auth-server-url = http://127.0.0.1:8080/auth
-keycloak.ssl-required = external
-keycloak.resource = demoapp
-keycloak.credentials.secret = 11111111-1111-1111-1111-111111111111
-keycloak.use-resource-role-mappings = true
-]]>
-        </programlisting>
-        <para>
-            You also need to specify the J2EE security config that would normally go in the <literal>web.xml</literal>.
-            Here's an example configuration:
-        </para>
-        <programlisting>
-<![CDATA[
-keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
-keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
-keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = user
-keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /insecure
-
-keycloak.securityConstraints[0].securityCollections[1].name = admin stuff
-keycloak.securityConstraints[0].securityCollections[1].authRoles[0] = admin
-keycloak.securityConstraints[0].securityCollections[1].patterns[0] = /admin
-]]>
-        </programlisting>
-    </section>
-</section>
+<section id="spring-boot-adapter">
+    <title>Spring Boot Adapter</title>
+    <para>
+        To be able to secure Spring Boot apps you must add the Keycloak Spring Boot adapter
+        JAR to your app. You then have to provide some extra configuration via normal Spring
+        Boot configuration (<literal>application.properties</literal>).  Let's go over these steps.
+    </para>
+    <section id="spring-boot-adapter-installation">
+        <title>Adapter Installation</title>
+        <para>
+            The Keycloak Spring Boot adapter takes advantage of Spring Boot's autoconfiguration so all
+            you need to do is add the Keycloak Spring Boot adapter JAR to your project. Depending on
+            what container you are using with Spring Boot, you also need to add the appropriate
+            Keycloak container adapter. If you are using Maven, add the following to your pom.xml (using
+            Tomcat as an example):
+        </para>
+        <para>
+            <programlisting>
+<![CDATA[
+<dependency>
+    <groupId>org.keycloak</groupId>
+    <artifactId>keycloak-spring-boot-adapter</artifactId>
+    <version>&project.version;</version>
+</dependency>
+<dependency>
+    <groupId>org.keycloak</groupId>
+    <artifactId>keycloak-tomcat8-adapter</artifactId>
+    <version>&project.version;</version>
+</dependency>
+]]>
+            </programlisting>
+        </para>
+    </section>
+
+    <section id="spring-boot-adapter-configuration">
+        <title>Required Spring Boot Adapter Configuration</title>
+        <para>
+            This section describes how to configure your Spring Boot app to use Keycloak.
+        </para>
+        <para>
+            Instead of a <literal>keycloak.json</literal> file, you configure the realm for the Spring
+            Boot Keycloak adapter via the normal Spring Boot configuration. For example:
+        </para>
+        <programlisting>
+<![CDATA[
+keycloak.realm = demorealm
+keycloak.realmKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCWYuxXmsmfV+Xc9Ik8QET8lD4wuHrJAXbbutS2O/eMjQQLNK7QDX/k/XhOkhxP0YBEypqeXeGaeQJjCxDhFjJXQuewUEMlmSja3IpoJ9/hFn4Cns4m7NGO+rtvnfnwgVfsEOS5EmZhRddp+40KBPPJfTH6Vgu6KjQwuFPj6DTwIDAQAB
+keycloak.auth-server-url = http://127.0.0.1:8080/auth
+keycloak.ssl-required = external
+keycloak.resource = demoapp
+keycloak.credentials.secret = 11111111-1111-1111-1111-111111111111
+keycloak.use-resource-role-mappings = true
+]]>
+        </programlisting>
+        <para>
+            You also need to specify the J2EE security config that would normally go in the <literal>web.xml</literal>.
+            Here's an example configuration:
+        </para>
+        <programlisting>
+<![CDATA[
+keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
+keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
+keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = user
+keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /insecure
+
+keycloak.securityConstraints[0].securityCollections[1].name = admin stuff
+keycloak.securityConstraints[0].securityCollections[1].authRoles[0] = admin
+keycloak.securityConstraints[0].securityCollections[1].patterns[0] = /admin
+]]>
+        </programlisting>
+    </section>
+</section>
diff --git a/docbook/reference/en/en-US/modules/timeouts.xml b/docbook/reference/en/en-US/modules/timeouts.xml
index ef41019..08e0450 100755
--- a/docbook/reference/en/en-US/modules/timeouts.xml
+++ b/docbook/reference/en/en-US/modules/timeouts.xml
@@ -1,55 +1,55 @@
-    <chapter id="timeouts">
-    <title>Cookie settings, Session Timeouts, and Token Lifespans</title>
-    <para>
-        Keycloak has a bunch of fine-grain settings to manage browser cookies, user login sessions, and token lifespans.
-        Sessions can be viewed and managed within the admin console for all users, and individually in the user's account
-        management pages.  This chapter goes over configuration options for cookies, sessions, and tokens.
-    </para>
-    <section>
-        <title>Remember Me</title>
-        <para>
-            If you go to the admin console page of Settings->General, you should see a <literal>Remember Me</literal> on/off switch.
-            Your realm sets a SSO cookie so that you only have to enter in your login credentials once.
-            This <literal>Remember Me</literal> admin config option, when turned on, will show a "Remember Me" checkbox on the user's login page.
-            If the user clicks this, the realm's SSO cookie will be persistent.   This means that if the user closes their browser
-            they will still be logged in the next time they start up their browser.
-        </para>
-    </section>
-    <section id="session-timeouts">
-        <title>Session Timeouts</title>
-        <para>
-            If you go to the Sesions and Tokens->Timeout Settings page of the Keycloak adminstration console there is a bunch of fine tuning
-            you can do as far as login session timeouts go.
-        </para>
-        <para>
-            The <literal>SSO Session Idle Timeout</literal> is the idle time of a user session.  If there is no activity
-            in the user's session for this amount of time, the user session will be destroyed, and the user will become logged
-            out.  The idle time is refreshed with every action against the keycloak server for that session, i.e.: a user login,
-            SSO, a refresh token grant, etc.
-        </para>
-        <para>
-            The <literal>SSO Session Max Lifespan</literal> setting is the maximum time a user session is allowed to be alive.  This
-            max lifespan countdown starts from when the user first logs in and is never refreshed.  This works great with <literal>Remember Me</literal>
-            in that it allow you to force a relogin after a set timeframe.
-        </para>
-    </section>
-    <section id="token-timeouts">
-        <title>Token Timeouts</title>
-        <para>
-            The <literal>Access Token Lifespan</literal> is how long an access token is valid for.  An access token contains everything
-            an application needs to authorize a client.  It contains roles allowed as well as other user information.  When
-            an access token expires, your application will attempt to refresh it using a refresh token that it obtained in the
-            initial login.  The value of this configuration option should be however long you feel comfortable with the
-            application not knowing if the user's permissions have changed.  This value is usually in minutes.
-        </para>
-        <para>
-            The <literal>Client login timeout</literal> is how long an access code is valid for.  An access code is obtained
-            on the 1st leg of the OAuth 2.0 redirection protocol.  This should be a short time limit.  Usually seconds.
-        </para>
-        <para>
-            The <literal>Login user action lifespan</literal> is how long a user is allowed to attempt a login.  When a user tries
-            to login, they may have to change their password, set up TOTP, or perform some other action before they are redirected
-            back to your application as an authentnicated user.  This value is relatively short and is usually measured in minutes.
-        </para>
-    </section>
+    <chapter id="timeouts">
+    <title>Cookie settings, Session Timeouts, and Token Lifespans</title>
+    <para>
+        Keycloak has a bunch of fine-grain settings to manage browser cookies, user login sessions, and token lifespans.
+        Sessions can be viewed and managed within the admin console for all users, and individually in the user's account
+        management pages.  This chapter goes over configuration options for cookies, sessions, and tokens.
+    </para>
+    <section>
+        <title>Remember Me</title>
+        <para>
+            If you go to the admin console page of Settings->General, you should see a <literal>Remember Me</literal> on/off switch.
+            Your realm sets a SSO cookie so that you only have to enter in your login credentials once.
+            This <literal>Remember Me</literal> admin config option, when turned on, will show a "Remember Me" checkbox on the user's login page.
+            If the user clicks this, the realm's SSO cookie will be persistent.   This means that if the user closes their browser
+            they will still be logged in the next time they start up their browser.
+        </para>
+    </section>
+    <section id="session-timeouts">
+        <title>Session Timeouts</title>
+        <para>
+            If you go to the Sesions and Tokens->Timeout Settings page of the Keycloak adminstration console there is a bunch of fine tuning
+            you can do as far as login session timeouts go.
+        </para>
+        <para>
+            The <literal>SSO Session Idle Timeout</literal> is the idle time of a user session.  If there is no activity
+            in the user's session for this amount of time, the user session will be destroyed, and the user will become logged
+            out.  The idle time is refreshed with every action against the keycloak server for that session, i.e.: a user login,
+            SSO, a refresh token grant, etc.
+        </para>
+        <para>
+            The <literal>SSO Session Max Lifespan</literal> setting is the maximum time a user session is allowed to be alive.  This
+            max lifespan countdown starts from when the user first logs in and is never refreshed.  This works great with <literal>Remember Me</literal>
+            in that it allow you to force a relogin after a set timeframe.
+        </para>
+    </section>
+    <section id="token-timeouts">
+        <title>Token Timeouts</title>
+        <para>
+            The <literal>Access Token Lifespan</literal> is how long an access token is valid for.  An access token contains everything
+            an application needs to authorize a client.  It contains roles allowed as well as other user information.  When
+            an access token expires, your application will attempt to refresh it using a refresh token that it obtained in the
+            initial login.  The value of this configuration option should be however long you feel comfortable with the
+            application not knowing if the user's permissions have changed.  This value is usually in minutes.
+        </para>
+        <para>
+            The <literal>Client login timeout</literal> is how long an access code is valid for.  An access code is obtained
+            on the 1st leg of the OAuth 2.0 redirection protocol.  This should be a short time limit.  Usually seconds.
+        </para>
+        <para>
+            The <literal>Login user action lifespan</literal> is how long a user is allowed to attempt a login.  When a user tries
+            to login, they may have to change their password, set up TOTP, or perform some other action before they are redirected
+            back to your application as an authentnicated user.  This value is relatively short and is usually measured in minutes.
+        </para>
+    </section>
 </chapter>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/tomcat-adapter.xml b/docbook/reference/en/en-US/modules/tomcat-adapter.xml
index e898f94..6e542af 100755
--- a/docbook/reference/en/en-US/modules/tomcat-adapter.xml
+++ b/docbook/reference/en/en-US/modules/tomcat-adapter.xml
@@ -1,101 +1,101 @@
-<section id="tomcat-adapter">
-    <title>Tomcat 6, 7 and 8 Adapters</title>
-    <para>
-        To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 adapter
-        into your Tomcat installation.  You then have to provide some extra configuration in each WAR you deploy to
-        Tomcat.  Let's go over these steps.
-    </para>
-    <section id="tomcat-adapter-installation">
-        <title>Adapter Installation</title>
-        <para>
-            Adapters are no longer included with the appliance or war distribution.  Each adapter is a separate download on
-            the Keycloak download site.  They are also available as a maven artifact.
-        </para>
-    <para>
-        You must unzip the adapter distro into Tomcat's <literal>lib/</literal> directory.  Including
-        adapter's jars within your WEB-INF/lib directory will not work!  The Keycloak adapter is implemented as a Valve
-        and valve code must reside in Tomcat's main lib/ directory.
-    </para>
-    <para>
-<programlisting>
-$ cd $TOMCAT_HOME/lib
-$ unzip keycloak-tomcat6-adapter-dist.zip
-    or
-$ unzip keycloak-tomcat7-adapter-dist.zip
-    or
-$ unzip keycloak-tomcat8-adapter-dist.zip
-</programlisting>
-    </para>
-    </section>
-
-    <section>
-        <title>Required Per WAR Configuration</title>
-        <para>
-            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
-        </para>
-        <para>
-            The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package.  This is
-            a Tomcat specific config file and you must define a Keycloak specific Valve.
-        </para>
-        <programlisting>
-<![CDATA[
-<Context path="/your-context-path">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
-</Context>]]>
-        </programlisting>
-        <para>
-            Next you must create
-            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
-            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
-            section.
-        </para>
-        <para>
-            Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
-            role-base constraints on your URLs.  Here's an example:
-        </para>
-        <para>
-<programlisting>
-<![CDATA[
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
-      version="3.0">
-
-	<module-name>customer-portal</module-name>
-
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Customers</web-resource-name>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>user</role-name>
-        </auth-constraint>
-    </security-constraint>
-
-    <security-constraint>
-        <web-resource-collection>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <user-data-constraint>
-            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
-        </user-data-constraint>
-    </security-constraint>
-
-    <login-config>
-        <auth-method>BASIC</auth-method>
-        <realm-name>this is ignored currently/realm-name>
-    </login-config>
-
-    <security-role>
-        <role-name>admin</role-name>
-    </security-role>
-    <security-role>
-        <role-name>user</role-name>
-    </security-role>
-</web-app>
-]]>
-</programlisting>
-        </para>
-    </section>
+<section id="tomcat-adapter">
+    <title>Tomcat 6, 7 and 8 Adapters</title>
+    <para>
+        To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 adapter
+        into your Tomcat installation.  You then have to provide some extra configuration in each WAR you deploy to
+        Tomcat.  Let's go over these steps.
+    </para>
+    <section id="tomcat-adapter-installation">
+        <title>Adapter Installation</title>
+        <para>
+            Adapters are no longer included with the appliance or war distribution.  Each adapter is a separate download on
+            the Keycloak download site.  They are also available as a maven artifact.
+        </para>
+    <para>
+        You must unzip the adapter distro into Tomcat's <literal>lib/</literal> directory.  Including
+        adapter's jars within your WEB-INF/lib directory will not work!  The Keycloak adapter is implemented as a Valve
+        and valve code must reside in Tomcat's main lib/ directory.
+    </para>
+    <para>
+<programlisting>
+$ cd $TOMCAT_HOME/lib
+$ unzip keycloak-tomcat6-adapter-dist.zip
+    or
+$ unzip keycloak-tomcat7-adapter-dist.zip
+    or
+$ unzip keycloak-tomcat8-adapter-dist.zip
+</programlisting>
+    </para>
+    </section>
+
+    <section>
+        <title>Required Per WAR Configuration</title>
+        <para>
+            This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
+        </para>
+        <para>
+            The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package.  This is
+            a Tomcat specific config file and you must define a Keycloak specific Valve.
+        </para>
+        <programlisting>
+<![CDATA[
+<Context path="/your-context-path">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+</Context>]]>
+        </programlisting>
+        <para>
+            Next you must create
+            a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
+            of your WAR.  The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
+            section.
+        </para>
+        <para>
+            Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
+            role-base constraints on your URLs.  Here's an example:
+        </para>
+        <para>
+<programlisting>
+<![CDATA[
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+      version="3.0">
+
+	<module-name>customer-portal</module-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Customers</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>user</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-constraint>
+        <web-resource-collection>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>this is ignored currently/realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>admin</role-name>
+    </security-role>
+    <security-role>
+        <role-name>user</role-name>
+    </security-role>
+</web-app>
+]]>
+</programlisting>
+        </para>
+    </section>
 </section>
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/user-federation.xml b/docbook/reference/en/en-US/modules/user-federation.xml
index 58a8727..272c2f6 100755
--- a/docbook/reference/en/en-US/modules/user-federation.xml
+++ b/docbook/reference/en/en-US/modules/user-federation.xml
@@ -1,244 +1,244 @@
-<chapter id="user_federation">
-    <title>User Federation SPI and LDAP/AD Integration</title>
-    <para>
-        Keycloak can federate external user databases.  Out of the box we have support for LDAP and Active Directory.
-        Before you dive into this, you should understand how Keycloak does federation.
-    </para>
-    <para>
-        Keycloak performs federation a bit differently than other products/projects.  The vision of Keycloak is that it
-        is an out of the box solution that should provide a core set of feature irregardless of the backend user storage you
-        want to use.  Because of this requirement/vision, Keycloak has a set data model that all of its services use.
-        Most of the time when you want to federate an external user store, much of the metadata that would be needed to
-        provide this complete feature set does not exist in that external store.  For example your LDAP server may only
-        provide password validation, but not support TOTP or user role mappings.  The Keycloak User Federation SPI was
-        written to support these completely variable configurations.
-    </para>
-    <para>
-        The way user federation works is that Keycloak will import your federated users on demand to its local storage.  How
-        much metadata that is imported depends on the underlying federation plugin and how that plugin is configured.  Some
-        federation plugins may only import the username into Keycloak storage, others might import everything from name,
-        address, and phone number, to user role mappings.  Some plugins might want to import credentials directly into
-        Keycloak storage and let Keycloak handle credential validation.  Others might want to handle credential validation
-        themselves.  The goal of the Federation SPI is to support all of these scenarios.
-    </para>
-    <section>
-        <title>LDAP and Active Directory Plugin</title>
-        <para>
-            Keycloak comes with a built-in LDAP/AD plugin.  By default, it is set up only to import username, email, first and last name, but you are free
-            to configure <link linkend='ldap_mappers'>mappers</link> and add more attributes or delete default ones.
-            It supports password validation via LDAP/AD protocols and different user metadata synchronization modes.  To configure
-            a federated LDAP store go to the admin console.  Click on the <literal>Users</literal> menu option to get you
-            to the user management page.  Then click on the <literal>Federation</literal> submenu option.  When
-            you get to this page there is an "Add Provider" select box.  You should see "ldap" within this list.  Selecting
-            "ldap" will bring you to the ldap configuration page.
-        </para>
-        <section>
-            <title>Edit Mode</title>
-            <para>
-                Edit mode defines various synchronization options with your LDAP store depending on what privileges
-                you have.
-                <variablelist>
-                    <varlistentry>
-                        <term>READONLY</term>
-                        <listitem>
-                            <para>
-                                Username, email, first and last name and other mapped attributes will be unchangeable.  Keycloak will show an error
-                                anytime anybody tries to update these fields.  Also, password updates will not be supported.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>WRITABLE</term>
-                        <listitem>
-                            <para>
-                                Username, email, first and last name, other mapped attributes and passwords can all be updated and will
-                                be synchronized automatically with your LDAP store.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>UNSYNCED</term>
-                        <listitem>
-                            <para>
-                                Any changes to username, email, first and last name, and passwords will be stored
-                                in Keycloak local storage. It is up to you to figure out how to synchronize back to
-                                LDAP.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                </variablelist>
-            </para>
-        </section>
-        <section>
-            <title>Other config options</title>
-            <para>
-                <variablelist>
-                    <varlistentry>
-                        <term>Display Name</term>
-                        <listitem>
-                            <para>
-                                Name used when this provider is referenced in the admin console
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>Priority</term>
-                        <listitem>
-                            <para>
-                                The priority of this provider when looking up users or for adding registrations.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>Sync Registrations</term>
-                        <listitem>
-                            <para>
-                                If a new user is added through a registration page or admin console, should the user
-                                be eligible to be synchronized to this provider.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>Allow Kerberos authentication</term>
-                        <listitem>
-                            <para>
-                                Enable Kerberos/SPNEGO authentication in realm with users data provisioned from LDAP. More info in <link linkend="kerberos">Kerberos section</link>.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                    <varlistentry>
-                        <term>Other options</term>
-                        <listitem>
-                            <para>
-                                The rest of the configuration options should be self explanatory. You can use tooltips in admin console
-                                to see some more details about them.
-                            </para>
-                        </listitem>
-                    </varlistentry>
-                </variablelist>
-            </para>
-        </section>
-    </section>
-    <section>
-        <title>Sync of LDAP users to Keycloak</title>
-        <para>
-            LDAP Federation Provider will automatically take care of synchronization (import) of needed LDAP users into Keycloak database.
-            For example once you first authenticate LDAP user <literal>john</literal> from Keycloak UI, LDAP Federation provider will
-            first import this LDAP user into Keycloak database and then authenticate against LDAP password.
-        </para>
-        <para>
-            Federation Provider imports just requested users by default, so if you click to <literal>View all users</literal>
-            in Keycloak admin console, you will see just those LDAP users, which were already authenticated/requested by Keycloak.
-        </para>
-        <para>If you want to sync all LDAP users into Keycloak database, you may configure and enable Sync, which is in
-            admin console on same page like the configuration of Federation provider itself. There are 2 types of sync:
-            <variablelist>
-                <varlistentry>
-                    <term>Full sync</term>
-                    <listitem>
-                        <para>
-                            This will synchronize all LDAP users into Keycloak DB. Those LDAP users, which already exist in Keycloak and were
-                            changed in LDAP directly will be updated in Keycloak DB (For example if user <literal>Mary Kelly</literal> was changed in LDAP to <literal>Mary Doe</literal>).
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>Changed users sync</term>
-                    <listitem>
-                        <para>
-                            This will check LDAP and it will sync into Keycloak just those users, which were created or updated in LDAP from the time of last sync.
-                        </para>
-                    </listitem>
-                </varlistentry>
-            </variablelist>
-        </para>
-        <para>
-            In usual cases you may want to trigger full sync at the beginning, so you will import all LDAP users to Keycloak just once. Then you may setup
-            periodic sync of changed users, so Keycloak will periodically ask LDAP server for newly created or updated users and backport them to Keycloak DB.
-            Also you may want to trigger full sync again after some longer time or setup periodic full sync as well.
-        </para>
-        <para>In admin console, you can trigger sync directly or you can enable periodic changed or full sync.</para>
-    </section>
-    <section id="ldap_mappers">
-        <title>LDAP/Federation mappers</title>
-        <para>
-            LDAP mappers are <literal>listeners</literal>, which are triggered by LDAP Federation provider at various points and provide
-            another extension point to LDAP integration. They are triggered during import LDAP user into Keycloak, registration Keycloak user back to LDAP or when querying LDAP user from Keycloak.
-            When you create LDAP Federation provider, Keycloak will automatically provide set of builtin <literal>mappers</literal> for this provider.
-            You are free to change this set and create new mapper or update/delete existing ones.
-        </para>
-        <para>
-            By default, we have those implementation of LDAP federation mapper:
-            <variablelist>
-                <varlistentry>
-                    <term>User Attribute Mapper</term>
-                    <listitem>
-                        <para>
-                            This allows to specify which LDAP attribute is mapped to which attribute of Keycloak User. So for example you can configure
-                            that LDAP attribute <literal>mail</literal> is supposed to be mapped to the UserModel attribute <literal>email</literal> in Keycloak database.
-                            For this mapper implementation, there is always one-to-one mapping (one LDAP attribute mapped to one Keycloak UserModel attribute)
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>FullName Mapper</term>
-                    <listitem>
-                        <para>
-                            This allows to specify that fullname of user, which is saved in some LDAP attribute (usualy <literal>cn</literal> ) will be mapped to
-                            <literal>firstName</literal> and <literal>lastname</literal> attributes of UserModel. Having <literal>cn</literal> to contain full name of user
-                            is common case for some LDAP deployments.
-                        </para>
-                    </listitem>
-                </varlistentry>
-                <varlistentry>
-                    <term>Role Mapper</term>
-                    <listitem>
-                        <para>
-                            This allows to configure role mappings from LDAP into Keycloak role mappings. One Role mapper can be used to map LDAP roles
-                            (usually groups from particular branch of LDAP tree) into roles corresponding to either realm roles or client roles of specified client.
-                            It's not a problem to configure more Role mappers for same LDAP provider. So for example you can specify that role mappings from groups under
-                            <literal>ou=main,dc=example,dc=org</literal> will be mapped to realm role mappings and role mappings from
-                            groups under <literal>ou=finance,dc=example,dc=org</literal> will be mapped to client role mappings of client <literal>finance</literal> .
-                        </para>
-                    </listitem>
-                </varlistentry>
-            </variablelist>
-        </para>
-        <para>By default, there is set of User Attribute mappers to map basic UserModel attributes username, first name, lastname and email to corresponding LDAP attributes. You are free to extend this and provide
-            more attribute mappings (For example to street, postalCode etc), delete firstName/lastname mapper and put fullName mapper instead, add role mappers etc.
-            Admin console provides tooltips, which should help on how to configure corresponding mappers.
-        </para>
-        <para>
-            We have an example, which is showing LDAP integration and set of base mappers and sample mappers (mappers for street and postalCode) . It's in <literal>examples/ldap</literal>
-            in the Keycloak example distribution or demo distribution download. You can also check the example sources directly <ulink url="https://github.com/keycloak/keycloak/blob/master/examples/ldap">here</ulink> .
-        </para>
-    </section>
-    <section>
-        <title>Writing your own User Federation Provider</title>
-        <para>
-            The keycloak examples directory contains an example of a simple User Federation Provider backed by
-            a simple properties file.  See <literal>examples/providers/federation-provider</literal>.  Most of how
-            to create a federation provider is explained directly within the example code, but some information is here too.
-        </para>
-        <para>
-            Writing a User Federation Provider starts by implementing the <literal>UserFederationProvider</literal>
-            and <literal>UserFederationProviderFactory</literal> interfaces.  Please see the Javadoc and example
-            for complete details on how to do this.  Some important methods of note:
-            getUserByUsername() and getUserByEmail() require that you query your federated storage and if the user exists
-            create and import the user into Keycloak storage.  How much metadata you import is fully up to you.  This
-            import is done by invoking methods on the object returned <literal>KeycloakSession.userStorage()</literal>
-            to add and import user information.  The proxy() method will be called whenever Keycloak has found an imported
-            UserModel.  This allows the federation provider to proxy the UserModel which is useful if you want to support
-            external storage updates on demand.
-        </para>
-        <para>
-            After your code is written you must package up all your classes within a JAR file.  This jar file must
-            contain a file called <literal>org.keycloak.models.UserFederationProviderFactory</literal>
-            within the <literal>META-INF/services</literal> directory of the JAR.  This file is a list
-            of fully qualified classnames of all implementations of <literal>UserFederationProviderFactory</literal>.
-            For more details on writing provider implementations and how to deploy to Keycloak refer to the
-            <link linkend='providers'>providers</link> section.
-        </para>
-    </section>
-
+<chapter id="user_federation">
+    <title>User Federation SPI and LDAP/AD Integration</title>
+    <para>
+        Keycloak can federate external user databases.  Out of the box we have support for LDAP and Active Directory.
+        Before you dive into this, you should understand how Keycloak does federation.
+    </para>
+    <para>
+        Keycloak performs federation a bit differently than other products/projects.  The vision of Keycloak is that it
+        is an out of the box solution that should provide a core set of feature irregardless of the backend user storage you
+        want to use.  Because of this requirement/vision, Keycloak has a set data model that all of its services use.
+        Most of the time when you want to federate an external user store, much of the metadata that would be needed to
+        provide this complete feature set does not exist in that external store.  For example your LDAP server may only
+        provide password validation, but not support TOTP or user role mappings.  The Keycloak User Federation SPI was
+        written to support these completely variable configurations.
+    </para>
+    <para>
+        The way user federation works is that Keycloak will import your federated users on demand to its local storage.  How
+        much metadata that is imported depends on the underlying federation plugin and how that plugin is configured.  Some
+        federation plugins may only import the username into Keycloak storage, others might import everything from name,
+        address, and phone number, to user role mappings.  Some plugins might want to import credentials directly into
+        Keycloak storage and let Keycloak handle credential validation.  Others might want to handle credential validation
+        themselves.  The goal of the Federation SPI is to support all of these scenarios.
+    </para>
+    <section>
+        <title>LDAP and Active Directory Plugin</title>
+        <para>
+            Keycloak comes with a built-in LDAP/AD plugin.  By default, it is set up only to import username, email, first and last name, but you are free
+            to configure <link linkend='ldap_mappers'>mappers</link> and add more attributes or delete default ones.
+            It supports password validation via LDAP/AD protocols and different user metadata synchronization modes.  To configure
+            a federated LDAP store go to the admin console.  Click on the <literal>Users</literal> menu option to get you
+            to the user management page.  Then click on the <literal>Federation</literal> submenu option.  When
+            you get to this page there is an "Add Provider" select box.  You should see "ldap" within this list.  Selecting
+            "ldap" will bring you to the ldap configuration page.
+        </para>
+        <section>
+            <title>Edit Mode</title>
+            <para>
+                Edit mode defines various synchronization options with your LDAP store depending on what privileges
+                you have.
+                <variablelist>
+                    <varlistentry>
+                        <term>READONLY</term>
+                        <listitem>
+                            <para>
+                                Username, email, first and last name and other mapped attributes will be unchangeable.  Keycloak will show an error
+                                anytime anybody tries to update these fields.  Also, password updates will not be supported.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>WRITABLE</term>
+                        <listitem>
+                            <para>
+                                Username, email, first and last name, other mapped attributes and passwords can all be updated and will
+                                be synchronized automatically with your LDAP store.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>UNSYNCED</term>
+                        <listitem>
+                            <para>
+                                Any changes to username, email, first and last name, and passwords will be stored
+                                in Keycloak local storage. It is up to you to figure out how to synchronize back to
+                                LDAP.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                </variablelist>
+            </para>
+        </section>
+        <section>
+            <title>Other config options</title>
+            <para>
+                <variablelist>
+                    <varlistentry>
+                        <term>Display Name</term>
+                        <listitem>
+                            <para>
+                                Name used when this provider is referenced in the admin console
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>Priority</term>
+                        <listitem>
+                            <para>
+                                The priority of this provider when looking up users or for adding registrations.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>Sync Registrations</term>
+                        <listitem>
+                            <para>
+                                If a new user is added through a registration page or admin console, should the user
+                                be eligible to be synchronized to this provider.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>Allow Kerberos authentication</term>
+                        <listitem>
+                            <para>
+                                Enable Kerberos/SPNEGO authentication in realm with users data provisioned from LDAP. More info in <link linkend="kerberos">Kerberos section</link>.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                        <term>Other options</term>
+                        <listitem>
+                            <para>
+                                The rest of the configuration options should be self explanatory. You can use tooltips in admin console
+                                to see some more details about them.
+                            </para>
+                        </listitem>
+                    </varlistentry>
+                </variablelist>
+            </para>
+        </section>
+    </section>
+    <section>
+        <title>Sync of LDAP users to Keycloak</title>
+        <para>
+            LDAP Federation Provider will automatically take care of synchronization (import) of needed LDAP users into Keycloak database.
+            For example once you first authenticate LDAP user <literal>john</literal> from Keycloak UI, LDAP Federation provider will
+            first import this LDAP user into Keycloak database and then authenticate against LDAP password.
+        </para>
+        <para>
+            Federation Provider imports just requested users by default, so if you click to <literal>View all users</literal>
+            in Keycloak admin console, you will see just those LDAP users, which were already authenticated/requested by Keycloak.
+        </para>
+        <para>If you want to sync all LDAP users into Keycloak database, you may configure and enable Sync, which is in
+            admin console on same page like the configuration of Federation provider itself. There are 2 types of sync:
+            <variablelist>
+                <varlistentry>
+                    <term>Full sync</term>
+                    <listitem>
+                        <para>
+                            This will synchronize all LDAP users into Keycloak DB. Those LDAP users, which already exist in Keycloak and were
+                            changed in LDAP directly will be updated in Keycloak DB (For example if user <literal>Mary Kelly</literal> was changed in LDAP to <literal>Mary Doe</literal>).
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>Changed users sync</term>
+                    <listitem>
+                        <para>
+                            This will check LDAP and it will sync into Keycloak just those users, which were created or updated in LDAP from the time of last sync.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+        <para>
+            In usual cases you may want to trigger full sync at the beginning, so you will import all LDAP users to Keycloak just once. Then you may setup
+            periodic sync of changed users, so Keycloak will periodically ask LDAP server for newly created or updated users and backport them to Keycloak DB.
+            Also you may want to trigger full sync again after some longer time or setup periodic full sync as well.
+        </para>
+        <para>In admin console, you can trigger sync directly or you can enable periodic changed or full sync.</para>
+    </section>
+    <section id="ldap_mappers">
+        <title>LDAP/Federation mappers</title>
+        <para>
+            LDAP mappers are <literal>listeners</literal>, which are triggered by LDAP Federation provider at various points and provide
+            another extension point to LDAP integration. They are triggered during import LDAP user into Keycloak, registration Keycloak user back to LDAP or when querying LDAP user from Keycloak.
+            When you create LDAP Federation provider, Keycloak will automatically provide set of builtin <literal>mappers</literal> for this provider.
+            You are free to change this set and create new mapper or update/delete existing ones.
+        </para>
+        <para>
+            By default, we have those implementation of LDAP federation mapper:
+            <variablelist>
+                <varlistentry>
+                    <term>User Attribute Mapper</term>
+                    <listitem>
+                        <para>
+                            This allows to specify which LDAP attribute is mapped to which attribute of Keycloak User. So for example you can configure
+                            that LDAP attribute <literal>mail</literal> is supposed to be mapped to the UserModel attribute <literal>email</literal> in Keycloak database.
+                            For this mapper implementation, there is always one-to-one mapping (one LDAP attribute mapped to one Keycloak UserModel attribute)
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>FullName Mapper</term>
+                    <listitem>
+                        <para>
+                            This allows to specify that fullname of user, which is saved in some LDAP attribute (usualy <literal>cn</literal> ) will be mapped to
+                            <literal>firstName</literal> and <literal>lastname</literal> attributes of UserModel. Having <literal>cn</literal> to contain full name of user
+                            is common case for some LDAP deployments.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>Role Mapper</term>
+                    <listitem>
+                        <para>
+                            This allows to configure role mappings from LDAP into Keycloak role mappings. One Role mapper can be used to map LDAP roles
+                            (usually groups from particular branch of LDAP tree) into roles corresponding to either realm roles or client roles of specified client.
+                            It's not a problem to configure more Role mappers for same LDAP provider. So for example you can specify that role mappings from groups under
+                            <literal>ou=main,dc=example,dc=org</literal> will be mapped to realm role mappings and role mappings from
+                            groups under <literal>ou=finance,dc=example,dc=org</literal> will be mapped to client role mappings of client <literal>finance</literal> .
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+        <para>By default, there is set of User Attribute mappers to map basic UserModel attributes username, first name, lastname and email to corresponding LDAP attributes. You are free to extend this and provide
+            more attribute mappings (For example to street, postalCode etc), delete firstName/lastname mapper and put fullName mapper instead, add role mappers etc.
+            Admin console provides tooltips, which should help on how to configure corresponding mappers.
+        </para>
+        <para>
+            We have an example, which is showing LDAP integration and set of base mappers and sample mappers (mappers for street and postalCode) . It's in <literal>examples/ldap</literal>
+            in the Keycloak example distribution or demo distribution download. You can also check the example sources directly <ulink url="https://github.com/keycloak/keycloak/blob/master/examples/ldap">here</ulink> .
+        </para>
+    </section>
+    <section>
+        <title>Writing your own User Federation Provider</title>
+        <para>
+            The keycloak examples directory contains an example of a simple User Federation Provider backed by
+            a simple properties file.  See <literal>examples/providers/federation-provider</literal>.  Most of how
+            to create a federation provider is explained directly within the example code, but some information is here too.
+        </para>
+        <para>
+            Writing a User Federation Provider starts by implementing the <literal>UserFederationProvider</literal>
+            and <literal>UserFederationProviderFactory</literal> interfaces.  Please see the Javadoc and example
+            for complete details on how to do this.  Some important methods of note:
+            getUserByUsername() and getUserByEmail() require that you query your federated storage and if the user exists
+            create and import the user into Keycloak storage.  How much metadata you import is fully up to you.  This
+            import is done by invoking methods on the object returned <literal>KeycloakSession.userStorage()</literal>
+            to add and import user information.  The proxy() method will be called whenever Keycloak has found an imported
+            UserModel.  This allows the federation provider to proxy the UserModel which is useful if you want to support
+            external storage updates on demand.
+        </para>
+        <para>
+            After your code is written you must package up all your classes within a JAR file.  This jar file must
+            contain a file called <literal>org.keycloak.models.UserFederationProviderFactory</literal>
+            within the <literal>META-INF/services</literal> directory of the JAR.  This file is a list
+            of fully qualified classnames of all implementations of <literal>UserFederationProviderFactory</literal>.
+            For more details on writing provider implementations and how to deploy to Keycloak refer to the
+            <link linkend='providers'>providers</link> section.
+        </para>
+    </section>
+
 </chapter>
\ No newline at end of file

events/api/pom.xml 76(+38 -38)

diff --git a/events/api/pom.xml b/events/api/pom.xml
index f447d5f..d9ec0b2 100755
--- a/events/api/pom.xml
+++ b/events/api/pom.xml
@@ -1,38 +1,38 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-events-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-events-api</artifactId>
-    <name>Keycloak Events API</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-   </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-events-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-events-api</artifactId>
+    <name>Keycloak Events API</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+   </dependencies>
+
+</project>

events/email/pom.xml 96(+48 -48)

diff --git a/events/email/pom.xml b/events/email/pom.xml
index 3972dc4..072dc52 100755
--- a/events/email/pom.xml
+++ b/events/email/pom.xml
@@ -1,48 +1,48 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-events-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-events-email</artifactId>
-    <name>Keycloak Events Email Provider</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-   </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-events-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-events-email</artifactId>
+    <name>Keycloak Events Email Provider</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+   </dependencies>
+
+</project>
diff --git a/events/jboss-logging/pom.xml b/events/jboss-logging/pom.xml
index e11effb..255b689 100755
--- a/events/jboss-logging/pom.xml
+++ b/events/jboss-logging/pom.xml
@@ -1,48 +1,48 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-events-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-events-jboss-logging</artifactId>
-    <name>Keycloak Events JBoss Logging Provider</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-   </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-events-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-events-jboss-logging</artifactId>
+    <name>Keycloak Events JBoss Logging Provider</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+   </dependencies>
+
+</project>

events/jpa/pom.xml 114(+57 -57)

diff --git a/events/jpa/pom.xml b/events/jpa/pom.xml
index 0a4736c..51eace9 100755
--- a/events/jpa/pom.xml
+++ b/events/jpa/pom.xml
@@ -1,57 +1,57 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-events-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-events-jpa</artifactId>
-    <name>Keycloak Events Store JPA Provider</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-   </dependencies>
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-events-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-events-jpa</artifactId>
+    <name>Keycloak Events Store JPA Provider</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+   </dependencies>
+</project>

events/mongo/pom.xml 94(+47 -47)

diff --git a/events/mongo/pom.xml b/events/mongo/pom.xml
index a686473..0b73e4f 100755
--- a/events/mongo/pom.xml
+++ b/events/mongo/pom.xml
@@ -1,47 +1,47 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-events-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-events-mongo</artifactId>
-    <name>Keycloak Events Store Mongo Provider</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-mongo</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <scope>provided</scope>
-        </dependency>
-   </dependencies>
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-events-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-events-mongo</artifactId>
+    <name>Keycloak Events Store Mongo Provider</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-mongo</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <scope>provided</scope>
+        </dependency>
+   </dependencies>
+</project>

events/pom.xml 52(+26 -26)

diff --git a/events/pom.xml b/events/pom.xml
index e956979..1c336c9 100755
--- a/events/pom.xml
+++ b/events/pom.xml
@@ -1,26 +1,26 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <name>Events Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.keycloak</groupId>
-    <artifactId>keycloak-events-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>api</module>
-        <module>email</module>
-        <module>jpa</module>
-        <module>jboss-logging</module>
-        <module>syslog</module>
-        <module>mongo</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <name>Events Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.keycloak</groupId>
+    <artifactId>keycloak-events-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>api</module>
+        <module>email</module>
+        <module>jpa</module>
+        <module>jboss-logging</module>
+        <module>syslog</module>
+        <module>mongo</module>
+    </modules>
+</project>
diff --git a/examples/admin-client/example-realm.json b/examples/admin-client/example-realm.json
index 5676c55..6b0921c 100755
--- a/examples/admin-client/example-realm.json
+++ b/examples/admin-client/example-realm.json
@@ -1,36 +1,36 @@
-{
-    "realm": "example",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users": [
-        {
-            "username": "examples-admin-client",
-            "enabled": true,
-            "credentials": [
-                {
-                    "type": "password",
-                    "value": "password"
-                }
-            ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "examples-admin-client",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "baseUrl": "/examples-admin-client",
-            "redirectUris": [
-                "/examples-admin-client/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "realm": "example",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users": [
+        {
+            "username": "examples-admin-client",
+            "enabled": true,
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "password"
+                }
+            ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "examples-admin-client",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "baseUrl": "/examples-admin-client",
+            "redirectUris": [
+                "/examples-admin-client/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/examples/basic-auth/basicauthrealm.json b/examples/basic-auth/basicauthrealm.json
index b17e7d8..4ff9d42 100644
--- a/examples/basic-auth/basicauthrealm.json
+++ b/examples/basic-auth/basicauthrealm.json
@@ -1,53 +1,53 @@
-{
-    "realm": "basic-auth",
-    "enabled": true,
-    "accessTokenLifespan": 60,
-    "accessCodeLifespan": 60,
-    "accessCodeLifespanUserAction": 300,
-    "ssoSessionIdleTimeout": 600,
-    "ssoSessionMaxLifespan": 36000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "basic-auth-service",
-            "enabled": true,
-            "adminUrl": "/basicauth",
-            "baseUrl": "/basicauth",
-            "secret": "password"
-        }
-    ]
-
-}
+{
+    "realm": "basic-auth",
+    "enabled": true,
+    "accessTokenLifespan": 60,
+    "accessCodeLifespan": 60,
+    "accessCodeLifespanUserAction": 300,
+    "ssoSessionIdleTimeout": 600,
+    "ssoSessionMaxLifespan": 36000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "basic-auth-service",
+            "enabled": true,
+            "adminUrl": "/basicauth",
+            "baseUrl": "/basicauth",
+            "secret": "password"
+        }
+    ]
+
+}
diff --git a/examples/basic-auth/pom.xml b/examples/basic-auth/pom.xml
index 3f61feb..660173b 100755
--- a/examples/basic-auth/pom.xml
+++ b/examples/basic-auth/pom.xml
@@ -1,75 +1,75 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Examples - Basic Auth</name>
-    <artifactId>examples-basicauth</artifactId>
-    <packaging>war</packaging>
-
-    <description>
-        Keycloak Basic Auth Example
-    </description>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>basicauth</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Examples - Basic Auth</name>
+    <artifactId>examples-basicauth</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        Keycloak Basic Auth Example
+    </description>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>basicauth</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
index aa6810f..0c9f0ce 100644
--- a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
+++ b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
@@ -1,62 +1,62 @@
-{
-    "realm": "facebook-identity-provider-realm",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "defaultRoles": [ "user" ],
-    "users" : [
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "facebook-authentication",
-            "enabled": true,
-            "publicClient" : true,
-            "adminUrl": "/facebook-authentication",
-            "baseUrl": "/facebook-authentication",
-            "redirectUris": [
-              "/facebook-authentication/*"
-            ],
-            "webOrigins": [
-              "http://localhost:8080"
-            ]
-        }
-    ],
-    "identityProviders": [
-        {
-          "alias" : "facebook",
-          "providerId" : "facebook",
-          "enabled": true,
-          "updateProfileFirstLogin" : "true",
-          "storeToken" : "true",
-          "addReadTokenRoleOnCreate" : true,
-          "config": {
-            "clientId": "CHANGE_CLIENT_ID",
-            "clientSecret": "CHANGE_CLIENT_SECRET"
-          }
-        }
-    ]
-}
+{
+    "realm": "facebook-identity-provider-realm",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "defaultRoles": [ "user" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "facebook-authentication",
+            "enabled": true,
+            "publicClient" : true,
+            "adminUrl": "/facebook-authentication",
+            "baseUrl": "/facebook-authentication",
+            "redirectUris": [
+              "/facebook-authentication/*"
+            ],
+            "webOrigins": [
+              "http://localhost:8080"
+            ]
+        }
+    ],
+    "identityProviders": [
+        {
+          "alias" : "facebook",
+          "providerId" : "facebook",
+          "enabled": true,
+          "updateProfileFirstLogin" : "true",
+          "storeToken" : "true",
+          "addReadTokenRoleOnCreate" : true,
+          "config": {
+            "clientId": "CHANGE_CLIENT_ID",
+            "clientSecret": "CHANGE_CLIENT_SECRET"
+          }
+        }
+    ]
+}
diff --git a/examples/broker/facebook-authentication/pom.xml b/examples/broker/facebook-authentication/pom.xml
index 0c36164..4636d2f 100755
--- a/examples/broker/facebook-authentication/pom.xml
+++ b/examples/broker/facebook-authentication/pom.xml
@@ -1,47 +1,47 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Broker Examples - Facebook Authentication</name>
-    <artifactId>facebook-authentication</artifactId>
-    <packaging>war</packaging>
-
-    <description>
-        An example about how to authenticate with Facebook
-    </description>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <build>
-        <finalName>facebook-authentication</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Broker Examples - Facebook Authentication</name>
+    <artifactId>facebook-authentication</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        An example about how to authenticate with Facebook
+    </description>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <finalName>facebook-authentication</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/broker/facebook-authentication/src/main/webapp/js/app.js b/examples/broker/facebook-authentication/src/main/webapp/js/app.js
index 3a8feeb..404ffea 100755
--- a/examples/broker/facebook-authentication/src/main/webapp/js/app.js
+++ b/examples/broker/facebook-authentication/src/main/webapp/js/app.js
@@ -1,100 +1,100 @@
-var module = angular.module('app', []);
-
-angular.element(document).ready(function ($http) {
-    var keycloakAuth = new Keycloak('keycloak.json');
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        module.factory('Auth', function() {
-            var Auth = {};
-
-            Auth.logout = function() {
-                keycloakAuth.logout();
-            }
-
-            Auth.getIdentity = function() {
-                return keycloakAuth.idTokenParsed;
-            }
-
-            Auth.getToken = function() {
-                return keycloakAuth.token;
-            }
-
-            Auth.refreshToken = function() {
-                return window.location = keycloakAuth.createLoginUrl({
-                    idpHint: 'facebook'
-                });
-            }
-
-            return Auth;
-        });
-
-        module.factory('authInterceptor', function($q) {
-            return {
-                request: function (config) {
-                    var deferred = $q.defer();
-
-                    config.headers = config.headers || {};
-
-                    if (!config.headers.Authorization) {
-                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
-                    }
-
-                    deferred.resolve(config);
-
-                    if (keycloakAuth.token) {
-                        keycloakAuth.updateToken(5).success(function() {
-                        }).error(function() {
-                            deferred.reject('Failed to refresh token');
-                        });
-                    }
-
-                    return deferred.promise;
-                }
-            };
-        });
-
-        module.config(function($httpProvider) {
-            $httpProvider.responseInterceptors.push('errorInterceptor');
-            $httpProvider.interceptors.push('authInterceptor');
-
-        });
-
-        module.factory('errorInterceptor', function($q) {
-            return function(promise) {
-                return promise.then(function(response) {
-                    return response;
-                }, function(response) {
-                    return $q.reject(response);
-                });
-            };
-        });
-
-        angular.bootstrap(document, ["app"]);
-    }).error(function () {
-        window.location.reload();
-    });
-});
-
-module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
-    $scope.logout = function() {
-        Auth.logout();
-    }
-
-    $scope.identity = Auth.getIdentity();
-
-    $scope.loadSocialProfile = function() {
-        $http.get('/auth/realms/facebook-identity-provider-realm/broker/facebook/token').success(function(data) {
-            var accessTokenParameter = 'access_token=';
-            var accessToken = data.substring(data.indexOf(accessTokenParameter) + accessTokenParameter.length, data.indexOf('&'));
-
-            $http.get('https://graph.facebook.com/me?access_token=' + accessToken)
-                .success(function(profile) {
-                    $scope.socialProfile = profile;
-                })
-                .error(function(data, status, headers, config) {
-                    $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
-                    Auth.refreshToken();
-                });
-        });
-    }
+var module = angular.module('app', []);
+
+angular.element(document).ready(function ($http) {
+    var keycloakAuth = new Keycloak('keycloak.json');
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        module.factory('Auth', function() {
+            var Auth = {};
+
+            Auth.logout = function() {
+                keycloakAuth.logout();
+            }
+
+            Auth.getIdentity = function() {
+                return keycloakAuth.idTokenParsed;
+            }
+
+            Auth.getToken = function() {
+                return keycloakAuth.token;
+            }
+
+            Auth.refreshToken = function() {
+                return window.location = keycloakAuth.createLoginUrl({
+                    idpHint: 'facebook'
+                });
+            }
+
+            return Auth;
+        });
+
+        module.factory('authInterceptor', function($q) {
+            return {
+                request: function (config) {
+                    var deferred = $q.defer();
+
+                    config.headers = config.headers || {};
+
+                    if (!config.headers.Authorization) {
+                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
+                    }
+
+                    deferred.resolve(config);
+
+                    if (keycloakAuth.token) {
+                        keycloakAuth.updateToken(5).success(function() {
+                        }).error(function() {
+                            deferred.reject('Failed to refresh token');
+                        });
+                    }
+
+                    return deferred.promise;
+                }
+            };
+        });
+
+        module.config(function($httpProvider) {
+            $httpProvider.responseInterceptors.push('errorInterceptor');
+            $httpProvider.interceptors.push('authInterceptor');
+
+        });
+
+        module.factory('errorInterceptor', function($q) {
+            return function(promise) {
+                return promise.then(function(response) {
+                    return response;
+                }, function(response) {
+                    return $q.reject(response);
+                });
+            };
+        });
+
+        angular.bootstrap(document, ["app"]);
+    }).error(function () {
+        window.location.reload();
+    });
+});
+
+module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
+    $scope.logout = function() {
+        Auth.logout();
+    }
+
+    $scope.identity = Auth.getIdentity();
+
+    $scope.loadSocialProfile = function() {
+        $http.get('/auth/realms/facebook-identity-provider-realm/broker/facebook/token').success(function(data) {
+            var accessTokenParameter = 'access_token=';
+            var accessToken = data.substring(data.indexOf(accessTokenParameter) + accessTokenParameter.length, data.indexOf('&'));
+
+            $http.get('https://graph.facebook.com/me?access_token=' + accessToken)
+                .success(function(profile) {
+                    $scope.socialProfile = profile;
+                })
+                .error(function(data, status, headers, config) {
+                    $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
+                    Auth.refreshToken();
+                });
+        });
+    }
 });
\ No newline at end of file
diff --git a/examples/broker/facebook-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js b/examples/broker/facebook-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/broker/facebook-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/broker/facebook-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/broker/google-authentication/google-identity-provider-realm.json b/examples/broker/google-authentication/google-identity-provider-realm.json
index 37af52b..771005d 100644
--- a/examples/broker/google-authentication/google-identity-provider-realm.json
+++ b/examples/broker/google-authentication/google-identity-provider-realm.json
@@ -1,62 +1,62 @@
-{
-    "realm": "google-identity-provider-realm",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "defaultRoles": [ "user" ],
-    "users" : [
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "google-authentication",
-            "enabled": true,
-            "publicClient" : true,
-            "adminUrl": "/google-authentication",
-            "baseUrl": "/google-authentication",
-            "redirectUris": [
-              "/google-authentication/*"
-            ],
-            "webOrigins": [
-              "http://localhost:8080"
-            ]
-        }
-    ],
-    "identityProviders": [
-        {
-          "alias" : "google",
-          "providerId" : "google",
-          "enabled": true,
-          "updateProfileFirstLogin" : "true",
-          "storeToken" : "true",
-          "addReadTokenRoleOnCreate" : true,
-          "config": {
-            "clientId": "CHANGE_CLIENT_ID",
-            "clientSecret": "CHANGE_CLIENT_SECRET"
-          }
-        }
-    ]
-}
+{
+    "realm": "google-identity-provider-realm",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "defaultRoles": [ "user" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "google-authentication",
+            "enabled": true,
+            "publicClient" : true,
+            "adminUrl": "/google-authentication",
+            "baseUrl": "/google-authentication",
+            "redirectUris": [
+              "/google-authentication/*"
+            ],
+            "webOrigins": [
+              "http://localhost:8080"
+            ]
+        }
+    ],
+    "identityProviders": [
+        {
+          "alias" : "google",
+          "providerId" : "google",
+          "enabled": true,
+          "updateProfileFirstLogin" : "true",
+          "storeToken" : "true",
+          "addReadTokenRoleOnCreate" : true,
+          "config": {
+            "clientId": "CHANGE_CLIENT_ID",
+            "clientSecret": "CHANGE_CLIENT_SECRET"
+          }
+        }
+    ]
+}
diff --git a/examples/broker/google-authentication/pom.xml b/examples/broker/google-authentication/pom.xml
index 4086d96..8f6f568 100755
--- a/examples/broker/google-authentication/pom.xml
+++ b/examples/broker/google-authentication/pom.xml
@@ -1,47 +1,47 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Broker Examples - Google Authentication</name>
-    <artifactId>google-authentication</artifactId>
-    <packaging>war</packaging>
-
-    <description>
-        An example about how to authenticate with Google
-    </description>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <build>
-        <finalName>google-authentication</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Broker Examples - Google Authentication</name>
+    <artifactId>google-authentication</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        An example about how to authenticate with Google
+    </description>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <finalName>google-authentication</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/broker/google-authentication/src/main/webapp/js/app.js b/examples/broker/google-authentication/src/main/webapp/js/app.js
index aa508cc..1ad583e 100755
--- a/examples/broker/google-authentication/src/main/webapp/js/app.js
+++ b/examples/broker/google-authentication/src/main/webapp/js/app.js
@@ -1,107 +1,107 @@
-var module = angular.module('app', []);
-
-angular.element(document).ready(function ($http) {
-    var keycloakAuth = new Keycloak('keycloak.json');
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        module.factory('Auth', function() {
-            var Auth = {};
-
-            Auth.logout = function() {
-                keycloakAuth.logout();
-            }
-
-            Auth.getIdentity = function() {
-                return keycloakAuth.idTokenParsed;
-            }
-
-            Auth.getToken = function() {
-                return keycloakAuth.token;
-            }
-
-            Auth.refreshToken = function() {
-                return window.location = keycloakAuth.createLoginUrl({
-                    idpHint: 'google'
-                });
-            }
-
-            return Auth;
-        });
-
-        module.factory('authInterceptor', function($q) {
-            return {
-                request: function (config) {
-                    var deferred = $q.defer();
-
-                    config.headers = config.headers || {};
-
-                    if (!config.headers.Authorization) {
-                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
-                    }
-
-                    deferred.resolve(config);
-
-                    if (keycloakAuth.token) {
-                        keycloakAuth.updateToken(5).success(function() {
-                        }).error(function() {
-                            deferred.reject('Failed to refresh token');
-                        });
-                    }
-
-                    return deferred.promise;
-                }
-            };
-        });
-
-        module.config(function($httpProvider) {
-            $httpProvider.responseInterceptors.push('errorInterceptor');
-            $httpProvider.interceptors.push('authInterceptor');
-
-        });
-
-        module.factory('errorInterceptor', function($q) {
-            return function(promise) {
-                return promise.then(function(response) {
-                    return response;
-                }, function(response) {
-                    return $q.reject(response);
-                });
-            };
-        });
-
-        angular.bootstrap(document, ["app"]);
-    }).error(function () {
-        window.location.reload();
-    });
-});
-
-module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
-    $scope.logout = function() {
-        Auth.logout();
-    }
-
-    $scope.identity = Auth.getIdentity();
-
-    $scope.loadSocialProfile = function() {
-        $http.get('/auth/realms/google-identity-provider-realm/broker/google/token').success(function(data) {
-            var accessToken = data.access_token;
-
-            var req = {
-                method: 'GET',
-                url: 'https://www.googleapis.com/plus/v1/people/me',
-                headers: {
-                    'Authorization': 'Bearer ' + accessToken
-                }
-            };
-
-            $http(req)
-                .success(function(profile) {
-                    $scope.socialProfile = profile;
-                })
-                .error(function(data, status, headers, config) {
-                    $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
-                    Auth.refreshToken();
-                });
-        });
-    }
+var module = angular.module('app', []);
+
+angular.element(document).ready(function ($http) {
+    var keycloakAuth = new Keycloak('keycloak.json');
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        module.factory('Auth', function() {
+            var Auth = {};
+
+            Auth.logout = function() {
+                keycloakAuth.logout();
+            }
+
+            Auth.getIdentity = function() {
+                return keycloakAuth.idTokenParsed;
+            }
+
+            Auth.getToken = function() {
+                return keycloakAuth.token;
+            }
+
+            Auth.refreshToken = function() {
+                return window.location = keycloakAuth.createLoginUrl({
+                    idpHint: 'google'
+                });
+            }
+
+            return Auth;
+        });
+
+        module.factory('authInterceptor', function($q) {
+            return {
+                request: function (config) {
+                    var deferred = $q.defer();
+
+                    config.headers = config.headers || {};
+
+                    if (!config.headers.Authorization) {
+                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
+                    }
+
+                    deferred.resolve(config);
+
+                    if (keycloakAuth.token) {
+                        keycloakAuth.updateToken(5).success(function() {
+                        }).error(function() {
+                            deferred.reject('Failed to refresh token');
+                        });
+                    }
+
+                    return deferred.promise;
+                }
+            };
+        });
+
+        module.config(function($httpProvider) {
+            $httpProvider.responseInterceptors.push('errorInterceptor');
+            $httpProvider.interceptors.push('authInterceptor');
+
+        });
+
+        module.factory('errorInterceptor', function($q) {
+            return function(promise) {
+                return promise.then(function(response) {
+                    return response;
+                }, function(response) {
+                    return $q.reject(response);
+                });
+            };
+        });
+
+        angular.bootstrap(document, ["app"]);
+    }).error(function () {
+        window.location.reload();
+    });
+});
+
+module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
+    $scope.logout = function() {
+        Auth.logout();
+    }
+
+    $scope.identity = Auth.getIdentity();
+
+    $scope.loadSocialProfile = function() {
+        $http.get('/auth/realms/google-identity-provider-realm/broker/google/token').success(function(data) {
+            var accessToken = data.access_token;
+
+            var req = {
+                method: 'GET',
+                url: 'https://www.googleapis.com/plus/v1/people/me',
+                headers: {
+                    'Authorization': 'Bearer ' + accessToken
+                }
+            };
+
+            $http(req)
+                .success(function(profile) {
+                    $scope.socialProfile = profile;
+                })
+                .error(function(data, status, headers, config) {
+                    $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
+                    Auth.refreshToken();
+                });
+        });
+    }
 });
\ No newline at end of file
diff --git a/examples/broker/google-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js b/examples/broker/google-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/broker/google-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/broker/google-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/broker/saml-broker-authentication/pom.xml b/examples/broker/saml-broker-authentication/pom.xml
index fff19ad..9072a2f 100755
--- a/examples/broker/saml-broker-authentication/pom.xml
+++ b/examples/broker/saml-broker-authentication/pom.xml
@@ -1,47 +1,47 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Broker Examples - SAML Identity Provider Brokering</name>
-    <artifactId>saml-broker-authentication</artifactId>
-    <packaging>war</packaging>
-
-    <description>
-        An example about how to broker a SAML v2 Identity Provider
-    </description>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <build>
-        <finalName>saml-broker-authentication</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Broker Examples - SAML Identity Provider Brokering</name>
+    <artifactId>saml-broker-authentication</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        An example about how to broker a SAML v2 Identity Provider
+    </description>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <finalName>saml-broker-authentication</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
index 7bd32b0..61aa80a 100755
--- a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
+++ b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
@@ -1,69 +1,69 @@
-{
-    "realm": "saml-broker-authentication-realm",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "defaultRoles": [ "user" ],
-    "users" : [
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "saml-broker-authentication",
-            "enabled": true,
-            "publicClient" : true,
-            "adminUrl": "/saml-broker-authentication",
-            "baseUrl": "/saml-broker-authentication",
-            "redirectUris": [
-              "/saml-broker-authentication/*"
-            ],
-            "webOrigins": [
-              "http://localhost:8080"
-            ]
-        }
-    ],
-    "identityProviders": [
-        {
-          "alias" : "saml-identity-provider",
-          "providerId" : "saml",
-          "enabled": true,
-          "updateProfileFirstLogin" : "true",
-          "storeToken" : "true",
-          "addReadTokenRoleOnCreate": true,
-          "config": {
-              "singleSignOnServiceUrl": "http://localhost:8080/auth/realms/saml-broker-realm/protocol/saml",
-              "singleLogoutServiceUrl": "http://localhost:8080/auth/realms/saml-broker-realm/protocol/saml",
-              "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
-              "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
-              "wantAuthnRequestsSigned": true,
-              "forceAuthn": true,
-              "validateSignature": true,
-              "postBindingResponse": true,
-              "postBindingAuthnRequest": true
-          }
-        }
-    ]
-}
+{
+    "realm": "saml-broker-authentication-realm",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "defaultRoles": [ "user" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "saml-broker-authentication",
+            "enabled": true,
+            "publicClient" : true,
+            "adminUrl": "/saml-broker-authentication",
+            "baseUrl": "/saml-broker-authentication",
+            "redirectUris": [
+              "/saml-broker-authentication/*"
+            ],
+            "webOrigins": [
+              "http://localhost:8080"
+            ]
+        }
+    ],
+    "identityProviders": [
+        {
+          "alias" : "saml-identity-provider",
+          "providerId" : "saml",
+          "enabled": true,
+          "updateProfileFirstLogin" : "true",
+          "storeToken" : "true",
+          "addReadTokenRoleOnCreate": true,
+          "config": {
+              "singleSignOnServiceUrl": "http://localhost:8080/auth/realms/saml-broker-realm/protocol/saml",
+              "singleLogoutServiceUrl": "http://localhost:8080/auth/realms/saml-broker-realm/protocol/saml",
+              "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
+              "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
+              "wantAuthnRequestsSigned": true,
+              "forceAuthn": true,
+              "validateSignature": true,
+              "postBindingResponse": true,
+              "postBindingAuthnRequest": true
+          }
+        }
+    ]
+}
diff --git a/examples/broker/saml-broker-authentication/saml-broker-realm.json b/examples/broker/saml-broker-authentication/saml-broker-realm.json
index 7ac492b..289fa2b 100644
--- a/examples/broker/saml-broker-authentication/saml-broker-realm.json
+++ b/examples/broker/saml-broker-authentication/saml-broker-realm.json
@@ -1,48 +1,48 @@
-{
-    "realm": "saml-broker-realm",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "defaultRoles": [ "user" ],
-    "users" : [
-        {
-            "username" : "user",
-            "enabled": true,
-            "email" : "user@saml-broker-realm",
-            "firstName": "User",
-            "lastName": "SAML",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ]
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "http://localhost:8080/auth/realms/saml-broker-authentication-realm",
-            "protocol": "saml",
-            "enabled": true,
-            "redirectUris": [
-              "http://localhost:8080/auth/realms/saml-broker-authentication-realm/broker/saml-identity-provider/endpoint"
-            ],
-          "attributes": {
-            "saml.assertion.signature": "true",
-            "saml.server.signature": "true",
-            "saml.signature.algorithm": "RSA_SHA256",
-            "saml.client.signature": "true",
-            "saml.authnstatement": "true",
-            "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-            "saml.signing.certificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"
-          }
-        }
-    ]
-}
+{
+    "realm": "saml-broker-realm",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "defaultRoles": [ "user" ],
+    "users" : [
+        {
+            "username" : "user",
+            "enabled": true,
+            "email" : "user@saml-broker-realm",
+            "firstName": "User",
+            "lastName": "SAML",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ]
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "http://localhost:8080/auth/realms/saml-broker-authentication-realm",
+            "protocol": "saml",
+            "enabled": true,
+            "redirectUris": [
+              "http://localhost:8080/auth/realms/saml-broker-authentication-realm/broker/saml-identity-provider/endpoint"
+            ],
+          "attributes": {
+            "saml.assertion.signature": "true",
+            "saml.server.signature": "true",
+            "saml.signature.algorithm": "RSA_SHA256",
+            "saml.client.signature": "true",
+            "saml.authnstatement": "true",
+            "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+            "saml.signing.certificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"
+          }
+        }
+    ]
+}
diff --git a/examples/broker/saml-broker-authentication/src/main/webapp/js/app.js b/examples/broker/saml-broker-authentication/src/main/webapp/js/app.js
index b46b5f6..2ff4b08 100755
--- a/examples/broker/saml-broker-authentication/src/main/webapp/js/app.js
+++ b/examples/broker/saml-broker-authentication/src/main/webapp/js/app.js
@@ -1,80 +1,80 @@
-var module = angular.module('app', []);
-
-angular.element(document).ready(function ($http) {
-    var keycloakAuth = new Keycloak('keycloak.json');
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        module.factory('Auth', function() {
-            var Auth = {};
-
-            Auth.logout = function() {
-                keycloakAuth.logout();
-            }
-
-            Auth.getIdentity = function() {
-                return keycloakAuth.idTokenParsed;
-            }
-
-            Auth.getToken = function() {
-                return keycloakAuth.token;
-            }
-
-            return Auth;
-        });
-
-        module.factory('authInterceptor', function($q) {
-            return {
-                request: function (config) {
-                    var deferred = $q.defer();
-
-                    config.headers = config.headers || {};
-
-                    if (!config.headers.Authorization) {
-                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
-                    }
-
-                    deferred.resolve(config);
-
-                    if (keycloakAuth.token) {
-                        keycloakAuth.updateToken(5).success(function() {
-                        }).error(function() {
-                            deferred.reject('Failed to refresh token');
-                        });
-                    }
-
-                    return deferred.promise;
-                }
-            };
-        });
-
-        module.config(function($httpProvider) {
-            $httpProvider.responseInterceptors.push('errorInterceptor');
-            $httpProvider.interceptors.push('authInterceptor');
-
-        });
-
-        module.factory('errorInterceptor', function($q) {
-            return function(promise) {
-                return promise.then(function(response) {
-                    return response;
-                }, function(response) {
-                    return $q.reject(response);
-                });
-            };
-        });
-
-        angular.bootstrap(document, ["app"]);
-    }).error(function () {
-        window.location = keycloakAuth.createLoginUrl({
-            idpHint: 'saml-identity-provider'
-        })
-    });
-});
-
-module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
-    $scope.logout = function() {
-        Auth.logout();
-    }
-
-    $scope.identity = Auth.getIdentity();
+var module = angular.module('app', []);
+
+angular.element(document).ready(function ($http) {
+    var keycloakAuth = new Keycloak('keycloak.json');
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        module.factory('Auth', function() {
+            var Auth = {};
+
+            Auth.logout = function() {
+                keycloakAuth.logout();
+            }
+
+            Auth.getIdentity = function() {
+                return keycloakAuth.idTokenParsed;
+            }
+
+            Auth.getToken = function() {
+                return keycloakAuth.token;
+            }
+
+            return Auth;
+        });
+
+        module.factory('authInterceptor', function($q) {
+            return {
+                request: function (config) {
+                    var deferred = $q.defer();
+
+                    config.headers = config.headers || {};
+
+                    if (!config.headers.Authorization) {
+                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
+                    }
+
+                    deferred.resolve(config);
+
+                    if (keycloakAuth.token) {
+                        keycloakAuth.updateToken(5).success(function() {
+                        }).error(function() {
+                            deferred.reject('Failed to refresh token');
+                        });
+                    }
+
+                    return deferred.promise;
+                }
+            };
+        });
+
+        module.config(function($httpProvider) {
+            $httpProvider.responseInterceptors.push('errorInterceptor');
+            $httpProvider.interceptors.push('authInterceptor');
+
+        });
+
+        module.factory('errorInterceptor', function($q) {
+            return function(promise) {
+                return promise.then(function(response) {
+                    return response;
+                }, function(response) {
+                    return $q.reject(response);
+                });
+            };
+        });
+
+        angular.bootstrap(document, ["app"]);
+    }).error(function () {
+        window.location = keycloakAuth.createLoginUrl({
+            idpHint: 'saml-identity-provider'
+        })
+    });
+});
+
+module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
+    $scope.logout = function() {
+        Auth.logout();
+    }
+
+    $scope.identity = Auth.getIdentity();
 });
\ No newline at end of file
diff --git a/examples/broker/saml-broker-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js b/examples/broker/saml-broker-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/broker/saml-broker-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/broker/saml-broker-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/broker/twitter-authentication/pom.xml b/examples/broker/twitter-authentication/pom.xml
index f2c2537..f52db1e 100755
--- a/examples/broker/twitter-authentication/pom.xml
+++ b/examples/broker/twitter-authentication/pom.xml
@@ -1,74 +1,74 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <artifactId>keycloak-examples-broker-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Broker Examples - Twitter Authentication</name>
-    <artifactId>twitter-authentication</artifactId>
-    <packaging>war</packaging>
-
-    <description>
-        An example about how to authenticate with Twitter
-    </description>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.twitter4j</groupId>
-            <artifactId>twitter4j-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <version>3.0.10.Final</version>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>twitter-authentication</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-broker-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Broker Examples - Twitter Authentication</name>
+    <artifactId>twitter-authentication</artifactId>
+    <packaging>war</packaging>
+
+    <description>
+        An example about how to authenticate with Twitter
+    </description>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.twitter4j</groupId>
+            <artifactId>twitter4j-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <version>3.0.10.Final</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>twitter-authentication</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/broker/twitter-authentication/src/main/webapp/js/app.js b/examples/broker/twitter-authentication/src/main/webapp/js/app.js
index 16683a2..46135a2 100755
--- a/examples/broker/twitter-authentication/src/main/webapp/js/app.js
+++ b/examples/broker/twitter-authentication/src/main/webapp/js/app.js
@@ -1,99 +1,99 @@
-var module = angular.module('app', []);
-
-angular.element(document).ready(function ($http) {
-    var keycloakAuth = new Keycloak('keycloak.json');
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        module.factory('Auth', function() {
-            var Auth = {};
-
-            Auth.logout = function() {
-                keycloakAuth.logout();
-            }
-
-            Auth.getIdentity = function() {
-                return keycloakAuth.idTokenParsed;
-            }
-
-            Auth.getToken = function() {
-                return keycloakAuth.token;
-            }
-
-            Auth.refreshToken = function() {
-                var url = keycloakAuth.createLoginUrl({
-                    idpHint: 'twitter'
-                });
-
-                console.log(url);
-
-                window.location = url;
-            }
-
-            return Auth;
-        });
-
-        module.factory('authInterceptor', function($q) {
-            return {
-                request: function (config) {
-                    var deferred = $q.defer();
-
-                    config.headers = config.headers || {};
-
-                    if (!config.headers.Authorization) {
-                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
-                    }
-
-                    deferred.resolve(config);
-
-                    if (keycloakAuth.token) {
-                        keycloakAuth.updateToken(5).success(function() {
-                        }).error(function() {
-                            deferred.reject('Failed to refresh token');
-                        });
-                    }
-
-                    return deferred.promise;
-                }
-            };
-        });
-
-        module.config(function($httpProvider) {
-            $httpProvider.responseInterceptors.push('errorInterceptor');
-            $httpProvider.interceptors.push('authInterceptor');
-
-        });
-
-        module.factory('errorInterceptor', function($q) {
-            return function(promise) {
-                return promise.then(function(response) {
-                    return response;
-                }, function(response) {
-                    return $q.reject(response);
-                });
-            };
-        });
-
-        angular.bootstrap(document, ["app"]);
-    }).error(function () {
-        window.location.reload();
-    });
-});
-
-module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
-    $scope.logout = function() {
-        Auth.logout();
-    }
-
-    $scope.identity = Auth.getIdentity();
-
-    $scope.loadSocialProfile = function() {
-        $http.get('/twitter-authentication/twitter/showUser')
-            .success(function(profile) {
-                $scope.socialProfile = profile;
-            })
-            .error(function(data, status, headers, config) {
-                $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
-                Auth.refreshToken();
-            });
-    }
+var module = angular.module('app', []);
+
+angular.element(document).ready(function ($http) {
+    var keycloakAuth = new Keycloak('keycloak.json');
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        module.factory('Auth', function() {
+            var Auth = {};
+
+            Auth.logout = function() {
+                keycloakAuth.logout();
+            }
+
+            Auth.getIdentity = function() {
+                return keycloakAuth.idTokenParsed;
+            }
+
+            Auth.getToken = function() {
+                return keycloakAuth.token;
+            }
+
+            Auth.refreshToken = function() {
+                var url = keycloakAuth.createLoginUrl({
+                    idpHint: 'twitter'
+                });
+
+                console.log(url);
+
+                window.location = url;
+            }
+
+            return Auth;
+        });
+
+        module.factory('authInterceptor', function($q) {
+            return {
+                request: function (config) {
+                    var deferred = $q.defer();
+
+                    config.headers = config.headers || {};
+
+                    if (!config.headers.Authorization) {
+                        config.headers.Authorization = 'Bearer ' + keycloakAuth.token;
+                    }
+
+                    deferred.resolve(config);
+
+                    if (keycloakAuth.token) {
+                        keycloakAuth.updateToken(5).success(function() {
+                        }).error(function() {
+                            deferred.reject('Failed to refresh token');
+                        });
+                    }
+
+                    return deferred.promise;
+                }
+            };
+        });
+
+        module.config(function($httpProvider) {
+            $httpProvider.responseInterceptors.push('errorInterceptor');
+            $httpProvider.interceptors.push('authInterceptor');
+
+        });
+
+        module.factory('errorInterceptor', function($q) {
+            return function(promise) {
+                return promise.then(function(response) {
+                    return response;
+                }, function(response) {
+                    return $q.reject(response);
+                });
+            };
+        });
+
+        angular.bootstrap(document, ["app"]);
+    }).error(function () {
+        window.location.reload();
+    });
+});
+
+module.controller('GlobalCtrl', function($scope, $http, $location, Auth) {
+    $scope.logout = function() {
+        Auth.logout();
+    }
+
+    $scope.identity = Auth.getIdentity();
+
+    $scope.loadSocialProfile = function() {
+        $http.get('/twitter-authentication/twitter/showUser')
+            .success(function(profile) {
+                $scope.socialProfile = profile;
+            })
+            .error(function(data, status, headers, config) {
+                $scope.socialProfile = 'Could not obtain social profile. Trying to refresh your token.';
+                Auth.refreshToken();
+            });
+    }
 });
\ No newline at end of file
diff --git a/examples/broker/twitter-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js b/examples/broker/twitter-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/broker/twitter-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/broker/twitter-authentication/src/main/webapp/js/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
index 691fd61..caae06d 100644
--- a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
+++ b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
@@ -1,72 +1,72 @@
-{
-    "realm": "twitter-identity-provider-realm",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "defaultRoles": [ "user" ],
-    "users" : [
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "clients": [
-        {
-            "clientId": "twitter-authentication",
-            "enabled": true,
-            "publicClient" : true,
-            "adminUrl": "/twitter-authentication",
-            "baseUrl": "/twitter-authentication",
-            "redirectUris": [
-                "/twitter-authentication/*"
-            ],
-            "webOrigins": [
-              "http://localhost:8080"
-            ]
-        },
-        {
-          "clientId": "admin-client",
-          "enabled": true,
-          "fullScopeAllowed": true,
-          "baseUrl": "/admin-client",
-          "redirectUris": [
-            "/admin-client/*"
-          ],
-          "secret": "password"
-        }
-    ],
-    "identityProviders": [
-        {
-          "alias" : "twitter",
-          "providerId" : "twitter",
-          "enabled": true,
-          "updateProfileFirstLogin" : "true",
-          "storeToken" : "true",
-          "addReadTokenRoleOnCreate" : true,
-          "config": {
-            "clientId": "CHANGE_CLIENT_ID",
-            "clientSecret": "CHANGE_CLIENT_SECRET"
-          }
-        }
-    ]
-}
+{
+    "realm": "twitter-identity-provider-realm",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "defaultRoles": [ "user" ],
+    "users" : [
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "twitter-authentication",
+            "enabled": true,
+            "publicClient" : true,
+            "adminUrl": "/twitter-authentication",
+            "baseUrl": "/twitter-authentication",
+            "redirectUris": [
+                "/twitter-authentication/*"
+            ],
+            "webOrigins": [
+              "http://localhost:8080"
+            ]
+        },
+        {
+          "clientId": "admin-client",
+          "enabled": true,
+          "fullScopeAllowed": true,
+          "baseUrl": "/admin-client",
+          "redirectUris": [
+            "/admin-client/*"
+          ],
+          "secret": "password"
+        }
+    ],
+    "identityProviders": [
+        {
+          "alias" : "twitter",
+          "providerId" : "twitter",
+          "enabled": true,
+          "updateProfileFirstLogin" : "true",
+          "storeToken" : "true",
+          "addReadTokenRoleOnCreate" : true,
+          "config": {
+            "clientId": "CHANGE_CLIENT_ID",
+            "clientSecret": "CHANGE_CLIENT_SECRET"
+          }
+        }
+    ]
+}
diff --git a/examples/cordova/example-realm.json b/examples/cordova/example-realm.json
index 13b2864..8dd787a 100755
--- a/examples/cordova/example-realm.json
+++ b/examples/cordova/example-realm.json
@@ -1,61 +1,61 @@
-{
-    "realm": "example",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "user",
-            "enabled": true,
-            "email" : "sample-user@example",
-            "firstName": "Sample",
-            "lastName": "User",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "account": ["view-profile", "manage-account"]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "cordova",
-            "roles": ["user"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "cordova",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": ["http://localhost"],
-            "webOrigins": ["localhost"]
-        }
-    ],
-    "clientScopeMappings": {
-        "account": [
-            {
-                "client": "cordova",
-                "roles": ["view-profile"]
-            }
-        ]
-    }
-}
+{
+    "realm": "example",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "user",
+            "enabled": true,
+            "email" : "sample-user@example",
+            "firstName": "Sample",
+            "lastName": "User",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": ["view-profile", "manage-account"]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "cordova",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "cordova",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": ["http://localhost"],
+            "webOrigins": ["localhost"]
+        }
+    ],
+    "clientScopeMappings": {
+        "account": [
+            {
+                "client": "cordova",
+                "roles": ["view-profile"]
+            }
+        ]
+    }
+}
diff --git a/examples/cors/angular-product-app/pom.xml b/examples/cors/angular-product-app/pom.xml
index 237bf5a..ebe1e55 100755
--- a/examples/cors/angular-product-app/pom.xml
+++ b/examples/cors/angular-product-app/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-cors-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>cors-angular-product-example</artifactId>
-    <packaging>war</packaging>
-    <name>Angular Product Portal JS</name>
-    <description/>
-
-    <build>
-        <finalName>angular-cors-product</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-cors-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>cors-angular-product-example</artifactId>
+    <packaging>war</packaging>
+    <name>Angular Product Portal JS</name>
+    <description/>
+
+    <build>
+        <finalName>angular-cors-product</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/cors/angular-product-app/src/main/webapp/js/app.js b/examples/cors/angular-product-app/src/main/webapp/js/app.js
index d6e9fd4..922c3a0 100755
--- a/examples/cors/angular-product-app/src/main/webapp/js/app.js
+++ b/examples/cors/angular-product-app/src/main/webapp/js/app.js
@@ -1,138 +1,138 @@
-var module = angular.module('product', []);
-
-var auth = {};
-var logout = function(){
-    console.log('*** LOGOUT');
-    auth.loggedIn = false;
-    auth.authz = null;
-    window.location = auth.logoutUrl;
-};
-
-
-angular.element(document).ready(function ($http) {
-    console.log("*** here");
-    var keycloakAuth = new Keycloak('keycloak.json');
-    auth.loggedIn = false;
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        console.log('here login');
-        auth.loggedIn = true;
-        auth.authz = keycloakAuth;
-        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/" + keycloakAuth.realm + "/tokens/logout?redirect_uri=http://localhost:8080/angular-cors-product/index.html";
-        module.factory('Auth', function() {
-            return auth;
-        });
-        angular.bootstrap(document, ["product"]);
-    }).error(function () {
-            alert("failed to login");
-        });
-
-});
-
-module.controller('GlobalCtrl', function($scope, $http) {
-    $scope.products = [];
-    $scope.roles = [];
-    $scope.serverInfo = [];
-    $scope.realm = [];
-    $scope.version = [];
-    $scope.reloadData = function() {
-        $http.get("http://localhost-db:8080/cors-database/products").success(function(data) {
-            $scope.products = angular.fromJson(data);
-
-        });
-
-    };
-    $scope.loadRoles = function() {
-        $http.get("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles").success(function(data) {
-            $scope.roles = angular.fromJson(data);
-
-        });
-
-    };
-    $scope.addRole = function() {
-        $http.post("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles", {name: 'stuff'}).success(function() {
-            $scope.loadRoles();
-        });
-
-    };
-    $scope.deleteRole = function() {
-        $http.delete("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles/stuff").success(function() {
-            $scope.loadRoles();
-        });
-
-    };
-
-    $scope.loadServerInfo = function() {
-        $http.get("http://localhost-auth:8080/auth/admin/serverinfo").success(function(data) {
-            $scope.serverInfo = angular.fromJson(data);
-        });
-
-    };
-
-    $scope.loadPublicRealmInfo = function() {
-        $http.get("http://localhost-auth:8080/auth/realms/cors").success(function(data) {
-            $scope.realm = angular.fromJson(data);
-        });
-    };
-
-    $scope.loadVersion = function() {
-        $http.get("http://localhost-auth:8080/auth/version").success(function(data) {
-            $scope.version = angular.fromJson(data);
-        });
-    };
-
-    $scope.logout = logout;
-});
-
-
-module.factory('authInterceptor', function($q, Auth) {
-    return {
-        request: function (config) {
-            var deferred = $q.defer();
-            if (Auth.authz.token) {
-                Auth.authz.updateToken(5).success(function() {
-                    config.headers = config.headers || {};
-                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
-
-                    deferred.resolve(config);
-                }).error(function() {
-                        deferred.reject('Failed to refresh token');
-                    });
-            }
-            return deferred.promise;
-        }
-    };
-});
-
-
-
-
-module.config(function($httpProvider) {
-    $httpProvider.responseInterceptors.push('errorInterceptor');
-    $httpProvider.interceptors.push('authInterceptor');
-
-});
-
-module.factory('errorInterceptor', function($q) {
-    return function(promise) {
-        return promise.then(function(response) {
-            return response;
-        }, function(response) {
-            if (response.status == 401) {
-                console.log('session timeout?');
-                logout();
-            } else if (response.status == 403) {
-                alert("Forbidden");
-            } else if (response.status == 404) {
-                alert("Not found");
-            } else if (response.status) {
-                if (response.data && response.data.errorMessage) {
-                    alert(response.data.errorMessage);
-                } else {
-                    alert("An unexpected server error has occurred");
-                }
-            }
-            return $q.reject(response);
-        });
-    };
-});
+var module = angular.module('product', []);
+
+var auth = {};
+var logout = function(){
+    console.log('*** LOGOUT');
+    auth.loggedIn = false;
+    auth.authz = null;
+    window.location = auth.logoutUrl;
+};
+
+
+angular.element(document).ready(function ($http) {
+    console.log("*** here");
+    var keycloakAuth = new Keycloak('keycloak.json');
+    auth.loggedIn = false;
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        console.log('here login');
+        auth.loggedIn = true;
+        auth.authz = keycloakAuth;
+        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/" + keycloakAuth.realm + "/tokens/logout?redirect_uri=http://localhost:8080/angular-cors-product/index.html";
+        module.factory('Auth', function() {
+            return auth;
+        });
+        angular.bootstrap(document, ["product"]);
+    }).error(function () {
+            alert("failed to login");
+        });
+
+});
+
+module.controller('GlobalCtrl', function($scope, $http) {
+    $scope.products = [];
+    $scope.roles = [];
+    $scope.serverInfo = [];
+    $scope.realm = [];
+    $scope.version = [];
+    $scope.reloadData = function() {
+        $http.get("http://localhost-db:8080/cors-database/products").success(function(data) {
+            $scope.products = angular.fromJson(data);
+
+        });
+
+    };
+    $scope.loadRoles = function() {
+        $http.get("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles").success(function(data) {
+            $scope.roles = angular.fromJson(data);
+
+        });
+
+    };
+    $scope.addRole = function() {
+        $http.post("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles", {name: 'stuff'}).success(function() {
+            $scope.loadRoles();
+        });
+
+    };
+    $scope.deleteRole = function() {
+        $http.delete("http://localhost-auth:8080/auth/admin/realms/" + auth.authz.realm + "/roles/stuff").success(function() {
+            $scope.loadRoles();
+        });
+
+    };
+
+    $scope.loadServerInfo = function() {
+        $http.get("http://localhost-auth:8080/auth/admin/serverinfo").success(function(data) {
+            $scope.serverInfo = angular.fromJson(data);
+        });
+
+    };
+
+    $scope.loadPublicRealmInfo = function() {
+        $http.get("http://localhost-auth:8080/auth/realms/cors").success(function(data) {
+            $scope.realm = angular.fromJson(data);
+        });
+    };
+
+    $scope.loadVersion = function() {
+        $http.get("http://localhost-auth:8080/auth/version").success(function(data) {
+            $scope.version = angular.fromJson(data);
+        });
+    };
+
+    $scope.logout = logout;
+});
+
+
+module.factory('authInterceptor', function($q, Auth) {
+    return {
+        request: function (config) {
+            var deferred = $q.defer();
+            if (Auth.authz.token) {
+                Auth.authz.updateToken(5).success(function() {
+                    config.headers = config.headers || {};
+                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
+
+                    deferred.resolve(config);
+                }).error(function() {
+                        deferred.reject('Failed to refresh token');
+                    });
+            }
+            return deferred.promise;
+        }
+    };
+});
+
+
+
+
+module.config(function($httpProvider) {
+    $httpProvider.responseInterceptors.push('errorInterceptor');
+    $httpProvider.interceptors.push('authInterceptor');
+
+});
+
+module.factory('errorInterceptor', function($q) {
+    return function(promise) {
+        return promise.then(function(response) {
+            return response;
+        }, function(response) {
+            if (response.status == 401) {
+                console.log('session timeout?');
+                logout();
+            } else if (response.status == 403) {
+                alert("Forbidden");
+            } else if (response.status == 404) {
+                alert("Not found");
+            } else if (response.status) {
+                if (response.data && response.data.errorMessage) {
+                    alert(response.data.errorMessage);
+                } else {
+                    alert("An unexpected server error has occurred");
+                }
+            }
+            return $q.reject(response);
+        });
+    };
+});
diff --git a/examples/cors/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js b/examples/cors/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/cors/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/cors/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/cors/cors-realm.json b/examples/cors/cors-realm.json
index 05321fb..e3f0ff2 100755
--- a/examples/cors/cors-realm.json
+++ b/examples/cors/cors-realm.json
@@ -1,68 +1,68 @@
-{
-    "realm": "cors",
-    "enabled": true,
-    "accessTokenLifespan": 60,
-    "accessCodeLifespan": 60,
-    "accessCodeLifespanUserAction": 300,
-    "ssoSessionIdleTimeout": 600,
-    "ssoSessionMaxLifespan": 36000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "angular-cors-product",
-            "roles": ["user"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "angular-cors-product",
-            "enabled": true,
-            "publicClient": true,
-            "baseUrl": "http://localhost:8080/angular-cors-product/index.html",
-            "redirectUris": [
-                "http://localhost:8080/angular-cors-product/*"
-            ],
-            "webOrigins": [
-                "http://localhost:8080"
-            ]
-        }
-    ],
-    "clientScopeMappings": {
-        "realm-management": [
-            {
-                "client": "angular-cors-product",
-                "roles": ["realm-admin"]
-            }
-        ]
-    }
-
-}
+{
+    "realm": "cors",
+    "enabled": true,
+    "accessTokenLifespan": 60,
+    "accessCodeLifespan": 60,
+    "accessCodeLifespanUserAction": 300,
+    "ssoSessionIdleTimeout": 600,
+    "ssoSessionMaxLifespan": 36000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "angular-cors-product",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "angular-cors-product",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "http://localhost:8080/angular-cors-product/index.html",
+            "redirectUris": [
+                "http://localhost:8080/angular-cors-product/*"
+            ],
+            "webOrigins": [
+                "http://localhost:8080"
+            ]
+        }
+    ],
+    "clientScopeMappings": {
+        "realm-management": [
+            {
+                "client": "angular-cors-product",
+                "roles": ["realm-admin"]
+            }
+        ]
+    }
+
+}
diff --git a/examples/cors/database-service/pom.xml b/examples/cors/database-service/pom.xml
index ee5eb63..185e802 100755
--- a/examples/cors/database-service/pom.xml
+++ b/examples/cors/database-service/pom.xml
@@ -1,73 +1,73 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-cors-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>cors-database-service</artifactId>
-    <packaging>war</packaging>
-    <name>JAX-RS Database Service Using OAuth Bearer Tokens</name>
-    <description/>
-    <url>http://maven.apache.org</url>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>cors-database</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-cors-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>cors-database-service</artifactId>
+    <packaging>war</packaging>
+    <name>JAX-RS Database Service Using OAuth Bearer Tokens</name>
+    <description/>
+    <url>http://maven.apache.org</url>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>cors-database</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

examples/cors/pom.xml 44(+22 -22)

diff --git a/examples/cors/pom.xml b/examples/cors/pom.xml
index a715cef..4900848 100755
--- a/examples/cors/pom.xml
+++ b/examples/cors/pom.xml
@@ -1,22 +1,22 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Keycloak Examples - CORS</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-examples-cors-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>angular-product-app</module>
-        <module>database-service</module>
-    </modules>
-
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Keycloak Examples - CORS</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-examples-cors-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>angular-product-app</module>
+        <module>database-service</module>
+    </modules>
+
+</project>
diff --git a/examples/cors/README.md b/examples/cors/README.md
index f2de71f..6506dd8 100755
--- a/examples/cors/README.md
+++ b/examples/cors/README.md
@@ -1,71 +1,71 @@
-Keycloak CORS support
-===================================
-The following examples requires Wildfly 8.0.0, JBoss EAP 6.x, or JBoss AS 7.1.1.  This example simulates Browser CORS
-requests.  While the examples will run on one machine, the servers/applications are configured to point to different domains:
-* **localhost-auth** is where the Keycloak auth server lives
-* **localhost-db** is where a database REST service lives
-* **localhost** is where the Javascript application lives
-
-In the demo you will visit the Javascript application and be redirected to Keycloak to login.  As part of the login process,
-the javascript application will have to make a CORS request to the auth server (localhost-auth) to obtain a token.  After it logs in, the
-application will make another CORS request to the REST database service (localhost-db).
-
-Here are some of the configuration additions to this example to enable CORS:
-1. The **angular-product** application in realm configuration has a Web Origin of **http://localhost:8080**.  When you log into
-the angular-product application, Keycloak will add the Web Origins for that application to the token.  Any CORS request made
-will check these allowed origins to make sure they match up with the Origin header the browser is sending
-2. The **angular-product** application config (keycloak.json) points the auth-server at **http://localhost-auth:8080/auth**
-3. The **database-service** config (keycloak.json) has an additional flag set **enable-cors**
-
-Step 1: Edit your hosts file
---------------------------------------
-The demo expects additional host mappings for localhost.  So, you need to edit your machine's host file (/etc/hosts or
-C:\Windows\System32\drivers\etc\hosts) and add the following entries:
-
-
-```
-127.0.0.1 localhost-auth
-127.0.0.1 localhost-db
-```
-
-
-Step 2: Make sure you've set up the Keycloak Server and have it running
---------------------------------------
-You will run this demo on the same server as the keycloak server.  Its best to use the appliance as everything is all set up.
-See documentation on how to set this up.
-
-Step 3: Import the Test Realm
----------------------------------------
-Next thing you have to do is import the test realm for the demo.  Clicking on the below link will bring you to the
-create realm page in the Admin UI.  The username/password is admin/admin to login in.  Keycloak will ask you to
-create a new admin password before you can go to the create realm page.
-
-[http://localhost-auth:8080/auth/admin/index.html#/create/realm](http://localhost-auth:8080/auth/admin/index.html#/create/realm)
-
-Import the cors-realm.json file that is in the cors/ example directory.  Feel free to browse the setup of the realm,
-particularly the angular-product application.
-
-
-Step 4: Build and deploy
----------------------------------------
-next you must build and deploy
-
-```
-cd cors
-mvn clean install wildfly:deploy
-```
-
-Step 5: Login and Observe Apps
----------------------------------------
-Try going to the customer app and view customer data:
-
-[http://localhost:8080/angular-cors-product/index.html](http://localhost:8080/angular-cors-product/index.html)
-
-This should take you to the auth-server login screen.  Enter username: bburke@redhat.com and password: password.  You
-should be brought back to a simple and boring HTML page.  Click the Reload button to show the product listing.  Reload
-causes an HTTP request to a different domain, this will trigger the browser's CORS protocol.
-
-
-
-
-
+Keycloak CORS support
+===================================
+The following examples requires Wildfly 8.0.0, JBoss EAP 6.x, or JBoss AS 7.1.1.  This example simulates Browser CORS
+requests.  While the examples will run on one machine, the servers/applications are configured to point to different domains:
+* **localhost-auth** is where the Keycloak auth server lives
+* **localhost-db** is where a database REST service lives
+* **localhost** is where the Javascript application lives
+
+In the demo you will visit the Javascript application and be redirected to Keycloak to login.  As part of the login process,
+the javascript application will have to make a CORS request to the auth server (localhost-auth) to obtain a token.  After it logs in, the
+application will make another CORS request to the REST database service (localhost-db).
+
+Here are some of the configuration additions to this example to enable CORS:
+1. The **angular-product** application in realm configuration has a Web Origin of **http://localhost:8080**.  When you log into
+the angular-product application, Keycloak will add the Web Origins for that application to the token.  Any CORS request made
+will check these allowed origins to make sure they match up with the Origin header the browser is sending
+2. The **angular-product** application config (keycloak.json) points the auth-server at **http://localhost-auth:8080/auth**
+3. The **database-service** config (keycloak.json) has an additional flag set **enable-cors**
+
+Step 1: Edit your hosts file
+--------------------------------------
+The demo expects additional host mappings for localhost.  So, you need to edit your machine's host file (/etc/hosts or
+C:\Windows\System32\drivers\etc\hosts) and add the following entries:
+
+
+```
+127.0.0.1 localhost-auth
+127.0.0.1 localhost-db
+```
+
+
+Step 2: Make sure you've set up the Keycloak Server and have it running
+--------------------------------------
+You will run this demo on the same server as the keycloak server.  Its best to use the appliance as everything is all set up.
+See documentation on how to set this up.
+
+Step 3: Import the Test Realm
+---------------------------------------
+Next thing you have to do is import the test realm for the demo.  Clicking on the below link will bring you to the
+create realm page in the Admin UI.  The username/password is admin/admin to login in.  Keycloak will ask you to
+create a new admin password before you can go to the create realm page.
+
+[http://localhost-auth:8080/auth/admin/index.html#/create/realm](http://localhost-auth:8080/auth/admin/index.html#/create/realm)
+
+Import the cors-realm.json file that is in the cors/ example directory.  Feel free to browse the setup of the realm,
+particularly the angular-product application.
+
+
+Step 4: Build and deploy
+---------------------------------------
+next you must build and deploy
+
+```
+cd cors
+mvn clean install wildfly:deploy
+```
+
+Step 5: Login and Observe Apps
+---------------------------------------
+Try going to the customer app and view customer data:
+
+[http://localhost:8080/angular-cors-product/index.html](http://localhost:8080/angular-cors-product/index.html)
+
+This should take you to the auth-server login screen.  Enter username: bburke@redhat.com and password: password.  You
+should be brought back to a simple and boring HTML page.  Click the Reload button to show the product listing.  Reload
+causes an HTTP request to a different domain, this will trigger the browser's CORS protocol.
+
+
+
+
+
diff --git a/examples/demo-template/admin-access-app/pom.xml b/examples/demo-template/admin-access-app/pom.xml
index 5894f73..10559a1 100755
--- a/examples/demo-template/admin-access-app/pom.xml
+++ b/examples/demo-template/admin-access-app/pom.xml
@@ -1,67 +1,67 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>admin-access-example</artifactId>
-    <packaging>war</packaging>
-    <name>Admin Access Example</name>
-    <description/>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>admin-access</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>admin-access-example</artifactId>
+    <packaging>war</packaging>
+    <name>Admin Access Example</name>
+    <description/>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>admin-access</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/admin-access-app/src/main/java/org/keycloak/example/AdminClient.java b/examples/demo-template/admin-access-app/src/main/java/org/keycloak/example/AdminClient.java
index 24a5cd8..d682d75 100755
--- a/examples/demo-template/admin-access-app/src/main/java/org/keycloak/example/AdminClient.java
+++ b/examples/demo-template/admin-access-app/src/main/java/org/keycloak/example/AdminClient.java
@@ -1,169 +1,169 @@
-package org.keycloak.example;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.message.BasicNameValuePair;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.constants.ServiceUrlConstants;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.util.HostUtils;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.KeycloakUriBuilder;
-import org.keycloak.util.UriUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AdminClient {
-
-    static class TypedList extends ArrayList<RoleRepresentation> {
-    }
-
-    public static class Failure extends Exception {
-        private int status;
-
-        public Failure(int status) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-    }
-
-    public static String getContent(HttpEntity entity) throws IOException {
-        if (entity == null) return null;
-        InputStream is = entity.getContent();
-        try {
-            ByteArrayOutputStream os = new ByteArrayOutputStream();
-            int c;
-            while ((c = is.read()) != -1) {
-                os.write(c);
-            }
-            byte[] bytes = os.toByteArray();
-            String data = new String(bytes);
-            return data;
-        } finally {
-            try {
-                is.close();
-            } catch (IOException ignored) {
-
-            }
-        }
-
-    }
-
-    public static AccessTokenResponse getToken(HttpServletRequest request) throws IOException {
-
-        HttpClient client = new DefaultHttpClient();
-
-
-        try {
-            HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
-                    .path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
-            List <NameValuePair> formparams = new ArrayList <NameValuePair>();
-            formparams.add(new BasicNameValuePair("username", "admin"));
-            formparams.add(new BasicNameValuePair("password", "password"));
-            formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "password"));
-            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "admin-client"));
-            UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-            post.setEntity(form);
-
-            HttpResponse response = client.execute(post);
-            int status = response.getStatusLine().getStatusCode();
-            HttpEntity entity = response.getEntity();
-            if (status != 200) {
-                String json = getContent(entity);
-                throw new IOException("Bad status: " + status + " response: " + json);
-            }
-            if (entity == null) {
-                throw new IOException("No Entity");
-            }
-            String json = getContent(entity);
-            return JsonSerialization.readValue(json, AccessTokenResponse.class);
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-    public static void logout(HttpServletRequest request, AccessTokenResponse res) throws IOException {
-
-        HttpClient client = new DefaultHttpClient();
-
-
-        try {
-            HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
-                    .path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
-                    .build("demo"));
-            List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-            formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, res.getRefreshToken()));
-            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "admin-client"));
-            UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-            post.setEntity(form);
-            HttpResponse response = client.execute(post);
-            boolean status = response.getStatusLine().getStatusCode() != 204;
-            HttpEntity entity = response.getEntity();
-            if (entity == null) {
-                return;
-            }
-            InputStream is = entity.getContent();
-            if (is != null) is.close();
-            if (status) {
-                throw new RuntimeException("failed to logout");
-            }
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-    public static List<RoleRepresentation> getRealmRoles(HttpServletRequest request, AccessTokenResponse res) throws Failure {
-
-        HttpClient client = new DefaultHttpClient();
-        try {
-            HttpGet get = new HttpGet(getBaseUrl(request) + "/auth/admin/realms/demo/roles");
-            get.addHeader("Authorization", "Bearer " + res.getToken());
-            try {
-                HttpResponse response = client.execute(get);
-                if (response.getStatusLine().getStatusCode() != 200) {
-                    throw new Failure(response.getStatusLine().getStatusCode());
-                }
-                HttpEntity entity = response.getEntity();
-                InputStream is = entity.getContent();
-                try {
-                    return JsonSerialization.readValue(is, TypedList.class);
-                } finally {
-                    is.close();
-                }
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-    public static String getBaseUrl(HttpServletRequest request) {
-        String useHostname = request.getServletContext().getInitParameter("useHostname");
-        if (useHostname != null && "true".equalsIgnoreCase(useHostname)) {
-            return "http://" + HostUtils.getHostName() + ":8080";
-        } else {
-            return UriUtils.getOrigin(request.getRequestURL().toString());
-        }
-    }
-
-}
+package org.keycloak.example;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.constants.ServiceUrlConstants;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.util.HostUtils;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.UriUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AdminClient {
+
+    static class TypedList extends ArrayList<RoleRepresentation> {
+    }
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+    public static String getContent(HttpEntity entity) throws IOException {
+        if (entity == null) return null;
+        InputStream is = entity.getContent();
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            int c;
+            while ((c = is.read()) != -1) {
+                os.write(c);
+            }
+            byte[] bytes = os.toByteArray();
+            String data = new String(bytes);
+            return data;
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ignored) {
+
+            }
+        }
+
+    }
+
+    public static AccessTokenResponse getToken(HttpServletRequest request) throws IOException {
+
+        HttpClient client = new DefaultHttpClient();
+
+
+        try {
+            HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
+                    .path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
+            List <NameValuePair> formparams = new ArrayList <NameValuePair>();
+            formparams.add(new BasicNameValuePair("username", "admin"));
+            formparams.add(new BasicNameValuePair("password", "password"));
+            formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "password"));
+            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "admin-client"));
+            UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+            post.setEntity(form);
+
+            HttpResponse response = client.execute(post);
+            int status = response.getStatusLine().getStatusCode();
+            HttpEntity entity = response.getEntity();
+            if (status != 200) {
+                String json = getContent(entity);
+                throw new IOException("Bad status: " + status + " response: " + json);
+            }
+            if (entity == null) {
+                throw new IOException("No Entity");
+            }
+            String json = getContent(entity);
+            return JsonSerialization.readValue(json, AccessTokenResponse.class);
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+    public static void logout(HttpServletRequest request, AccessTokenResponse res) throws IOException {
+
+        HttpClient client = new DefaultHttpClient();
+
+
+        try {
+            HttpPost post = new HttpPost(KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
+                    .path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
+                    .build("demo"));
+            List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+            formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, res.getRefreshToken()));
+            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "admin-client"));
+            UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+            post.setEntity(form);
+            HttpResponse response = client.execute(post);
+            boolean status = response.getStatusLine().getStatusCode() != 204;
+            HttpEntity entity = response.getEntity();
+            if (entity == null) {
+                return;
+            }
+            InputStream is = entity.getContent();
+            if (is != null) is.close();
+            if (status) {
+                throw new RuntimeException("failed to logout");
+            }
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+    public static List<RoleRepresentation> getRealmRoles(HttpServletRequest request, AccessTokenResponse res) throws Failure {
+
+        HttpClient client = new DefaultHttpClient();
+        try {
+            HttpGet get = new HttpGet(getBaseUrl(request) + "/auth/admin/realms/demo/roles");
+            get.addHeader("Authorization", "Bearer " + res.getToken());
+            try {
+                HttpResponse response = client.execute(get);
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new Failure(response.getStatusLine().getStatusCode());
+                }
+                HttpEntity entity = response.getEntity();
+                InputStream is = entity.getContent();
+                try {
+                    return JsonSerialization.readValue(is, TypedList.class);
+                } finally {
+                    is.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+    public static String getBaseUrl(HttpServletRequest request) {
+        String useHostname = request.getServletContext().getInitParameter("useHostname");
+        if (useHostname != null && "true".equalsIgnoreCase(useHostname)) {
+            return "http://" + HostUtils.getHostName() + ":8080";
+        } else {
+            return UriUtils.getOrigin(request.getRequestURL().toString());
+        }
+    }
+
+}
diff --git a/examples/demo-template/angular-product-app/pom.xml b/examples/demo-template/angular-product-app/pom.xml
index 5376a09..2b8477d 100755
--- a/examples/demo-template/angular-product-app/pom.xml
+++ b/examples/demo-template/angular-product-app/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>angular-product-example</artifactId>
-    <packaging>war</packaging>
-    <name>Angular Product Portal JS</name>
-    <description/>
-
-    <build>
-        <finalName>angular-product</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>angular-product-example</artifactId>
+    <packaging>war</packaging>
+    <name>Angular Product Portal JS</name>
+    <description/>
+
+    <build>
+        <finalName>angular-product</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/angular-product-app/src/main/webapp/js/app.js b/examples/demo-template/angular-product-app/src/main/webapp/js/app.js
index 05dafbb..44b7c4b 100755
--- a/examples/demo-template/angular-product-app/src/main/webapp/js/app.js
+++ b/examples/demo-template/angular-product-app/src/main/webapp/js/app.js
@@ -1,93 +1,93 @@
-var module = angular.module('product', []);
-
-var auth = {};
-var logout = function(){
-    console.log('*** LOGOUT');
-    auth.loggedIn = false;
-    auth.authz = null;
-    window.location = auth.logoutUrl;
-};
-
-
-angular.element(document).ready(function ($http) {
-    var keycloakAuth = new Keycloak('keycloak.json');
-    auth.loggedIn = false;
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        auth.loggedIn = true;
-        auth.authz = keycloakAuth;
-        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/demo/tokens/logout?redirect_uri=/angular-product/index.html";
-        module.factory('Auth', function() {
-            return auth;
-        });
-        angular.bootstrap(document, ["product"]);
-    }).error(function () {
-            window.location.reload();
-        });
-
-});
-
-module.controller('GlobalCtrl', function($scope, $http) {
-    $scope.products = [];
-    $scope.reloadData = function() {
-        $http.get("/database/products").success(function(data) {
-            $scope.products = angular.fromJson(data);
-
-        });
-
-    };
-    $scope.logout = logout;
-});
-
-
-module.factory('authInterceptor', function($q, Auth) {
-    return {
-        request: function (config) {
-            var deferred = $q.defer();
-            if (Auth.authz.token) {
-                Auth.authz.updateToken(5).success(function() {
-                    config.headers = config.headers || {};
-                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
-
-                    deferred.resolve(config);
-                }).error(function() {
-                        deferred.reject('Failed to refresh token');
-                    });
-            }
-            return deferred.promise;
-        }
-    };
-});
-
-
-
-
-module.config(function($httpProvider) {
-    $httpProvider.responseInterceptors.push('errorInterceptor');
-    $httpProvider.interceptors.push('authInterceptor');
-
-});
-
-module.factory('errorInterceptor', function($q) {
-    return function(promise) {
-        return promise.then(function(response) {
-            return response;
-        }, function(response) {
-            if (response.status == 401) {
-                console.log('session timeout?');
-                logout();
-            } else if (response.status == 403) {
-                alert("Forbidden");
-            } else if (response.status == 404) {
-                alert("Not found");
-            } else if (response.status) {
-                if (response.data && response.data.errorMessage) {
-                    alert(response.data.errorMessage);
-                } else {
-                    alert("An unexpected server error has occurred");
-                }
-            }
-            return $q.reject(response);
-        });
-    };
-});
+var module = angular.module('product', []);
+
+var auth = {};
+var logout = function(){
+    console.log('*** LOGOUT');
+    auth.loggedIn = false;
+    auth.authz = null;
+    window.location = auth.logoutUrl;
+};
+
+
+angular.element(document).ready(function ($http) {
+    var keycloakAuth = new Keycloak('keycloak.json');
+    auth.loggedIn = false;
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        auth.loggedIn = true;
+        auth.authz = keycloakAuth;
+        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/demo/tokens/logout?redirect_uri=/angular-product/index.html";
+        module.factory('Auth', function() {
+            return auth;
+        });
+        angular.bootstrap(document, ["product"]);
+    }).error(function () {
+            window.location.reload();
+        });
+
+});
+
+module.controller('GlobalCtrl', function($scope, $http) {
+    $scope.products = [];
+    $scope.reloadData = function() {
+        $http.get("/database/products").success(function(data) {
+            $scope.products = angular.fromJson(data);
+
+        });
+
+    };
+    $scope.logout = logout;
+});
+
+
+module.factory('authInterceptor', function($q, Auth) {
+    return {
+        request: function (config) {
+            var deferred = $q.defer();
+            if (Auth.authz.token) {
+                Auth.authz.updateToken(5).success(function() {
+                    config.headers = config.headers || {};
+                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
+
+                    deferred.resolve(config);
+                }).error(function() {
+                        deferred.reject('Failed to refresh token');
+                    });
+            }
+            return deferred.promise;
+        }
+    };
+});
+
+
+
+
+module.config(function($httpProvider) {
+    $httpProvider.responseInterceptors.push('errorInterceptor');
+    $httpProvider.interceptors.push('authInterceptor');
+
+});
+
+module.factory('errorInterceptor', function($q) {
+    return function(promise) {
+        return promise.then(function(response) {
+            return response;
+        }, function(response) {
+            if (response.status == 401) {
+                console.log('session timeout?');
+                logout();
+            } else if (response.status == 403) {
+                alert("Forbidden");
+            } else if (response.status == 404) {
+                alert("Not found");
+            } else if (response.status) {
+                if (response.data && response.data.errorMessage) {
+                    alert(response.data.errorMessage);
+                } else {
+                    alert("An unexpected server error has occurred");
+                }
+            }
+            return $q.reject(response);
+        });
+    };
+});
diff --git a/examples/demo-template/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js b/examples/demo-template/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/examples/demo-template/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
+++ b/examples/demo-template/angular-product-app/src/main/webapp/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/examples/demo-template/customer-app/pom.xml b/examples/demo-template/customer-app/pom.xml
index da6be3e..d9cc93f 100755
--- a/examples/demo-template/customer-app/pom.xml
+++ b/examples/demo-template/customer-app/pom.xml
@@ -1,67 +1,67 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>customer-portal-example</artifactId>
-    <packaging>war</packaging>
-    <name>Customer Portal - Secured via Valve</name>
-    <description/>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>customer-portal</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>customer-portal-example</artifactId>
+    <packaging>war</packaging>
+    <name>Customer Portal - Secured via Valve</name>
+    <description/>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>customer-portal</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/AdminClient.java b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/AdminClient.java
index c111f36..6a1b7f1 100755
--- a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/AdminClient.java
+++ b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/AdminClient.java
@@ -1,67 +1,67 @@
-package org.keycloak.example;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.util.JsonSerialization;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AdminClient {
-
-    static class TypedList extends ArrayList<RoleRepresentation> {
-    }
-
-    public static class Failure extends Exception {
-        private int status;
-
-        public Failure(int status) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-    }
-
-    public static List<RoleRepresentation> getRealmRoles(HttpServletRequest req) throws Failure {
-        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
-
-        HttpClient client = new DefaultHttpClient();
-        try {
-            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/auth/admin/realms/demo/roles");
-            get.addHeader("Authorization", "Bearer " + session.getTokenString());
-            try {
-                HttpResponse response = client.execute(get);
-                if (response.getStatusLine().getStatusCode() != 200) {
-                    throw new Failure(response.getStatusLine().getStatusCode());
-                }
-                HttpEntity entity = response.getEntity();
-                InputStream is = entity.getContent();
-                try {
-                    return JsonSerialization.readValue(is, TypedList.class);
-                } finally {
-                    is.close();
-                }
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-}
+package org.keycloak.example;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.util.JsonSerialization;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AdminClient {
+
+    static class TypedList extends ArrayList<RoleRepresentation> {
+    }
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+    public static List<RoleRepresentation> getRealmRoles(HttpServletRequest req) throws Failure {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
+
+        HttpClient client = new DefaultHttpClient();
+        try {
+            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/auth/admin/realms/demo/roles");
+            get.addHeader("Authorization", "Bearer " + session.getTokenString());
+            try {
+                HttpResponse response = client.execute(get);
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new Failure(response.getStatusLine().getStatusCode());
+                }
+                HttpEntity entity = response.getEntity();
+                InputStream is = entity.getContent();
+                try {
+                    return JsonSerialization.readValue(is, TypedList.class);
+                } finally {
+                    is.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+}
diff --git a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java
index e9dcbb1..a2c1b31 100755
--- a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java
+++ b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java
@@ -1,81 +1,81 @@
-package org.keycloak.example;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.representations.IDToken;
-import org.keycloak.util.JsonSerialization;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CustomerDatabaseClient {
-
-    static class TypedList extends ArrayList<String> {
-    }
-
-    public static class Failure extends Exception {
-        private int status;
-
-        public Failure(int status) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-    }
-
-    public static IDToken getIDToken(HttpServletRequest req) {
-        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
-        return session.getIdToken();
-
-    }
-
-    public static List<String> getCustomers(HttpServletRequest req) throws Failure {
-        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
-
-        HttpClient client = new DefaultHttpClient();
-        try {
-            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/customers");
-            get.addHeader("Authorization", "Bearer " + session.getTokenString());
-            try {
-                HttpResponse response = client.execute(get);
-                if (response.getStatusLine().getStatusCode() != 200) {
-                    throw new Failure(response.getStatusLine().getStatusCode());
-                }
-                HttpEntity entity = response.getEntity();
-                InputStream is = entity.getContent();
-                try {
-                    return JsonSerialization.readValue(is, TypedList.class);
-                } finally {
-                    is.close();
-                }
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-    public static String increaseAndGetCounter(HttpServletRequest req) {
-        HttpSession session = req.getSession();
-        Integer counter = (Integer)session.getAttribute("counter");
-        counter = (counter == null) ? 1 : counter + 1;
-        session.setAttribute("counter", counter);
-        return String.valueOf(counter);
-    }
-}
+package org.keycloak.example;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.representations.IDToken;
+import org.keycloak.util.JsonSerialization;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CustomerDatabaseClient {
+
+    static class TypedList extends ArrayList<String> {
+    }
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+    public static IDToken getIDToken(HttpServletRequest req) {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
+        return session.getIdToken();
+
+    }
+
+    public static List<String> getCustomers(HttpServletRequest req) throws Failure {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
+
+        HttpClient client = new DefaultHttpClient();
+        try {
+            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/customers");
+            get.addHeader("Authorization", "Bearer " + session.getTokenString());
+            try {
+                HttpResponse response = client.execute(get);
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new Failure(response.getStatusLine().getStatusCode());
+                }
+                HttpEntity entity = response.getEntity();
+                InputStream is = entity.getContent();
+                try {
+                    return JsonSerialization.readValue(is, TypedList.class);
+                } finally {
+                    is.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+    public static String increaseAndGetCounter(HttpServletRequest req) {
+        HttpSession session = req.getSession();
+        Integer counter = (Integer)session.getAttribute("counter");
+        counter = (counter == null) ? 1 : counter + 1;
+        session.setAttribute("counter", counter);
+        return String.valueOf(counter);
+    }
+}
diff --git a/examples/demo-template/customer-app-cli/pom.xml b/examples/demo-template/customer-app-cli/pom.xml
index 30c481b..9db1bc0 100755
--- a/examples/demo-template/customer-app-cli/pom.xml
+++ b/examples/demo-template/customer-app-cli/pom.xml
@@ -1,39 +1,39 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>customer-portal-cli-example</artifactId>
-    <packaging>jar</packaging>
-    <name>Customer Portal CLI</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-installed-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <mainClass>org.keycloak.example.CustomerCli</mainClass>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>customer-portal-cli-example</artifactId>
+    <packaging>jar</packaging>
+    <name>Customer Portal CLI</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-installed-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>org.keycloak.example.CustomerCli</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/customer-app-js/pom.xml b/examples/demo-template/customer-app-js/pom.xml
index 094d565..8d80465 100755
--- a/examples/demo-template/customer-app-js/pom.xml
+++ b/examples/demo-template/customer-app-js/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>customer-portal-js-example</artifactId>
-    <packaging>war</packaging>
-    <name>Customer Portal JS</name>
-    <description/>
-
-    <build>
-        <finalName>customer-portal-js</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>customer-portal-js-example</artifactId>
+    <packaging>war</packaging>
+    <name>Customer Portal JS</name>
+    <description/>
+
+    <build>
+        <finalName>customer-portal-js</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/database-service/pom.xml b/examples/demo-template/database-service/pom.xml
index d80b10f..7a5592f 100755
--- a/examples/demo-template/database-service/pom.xml
+++ b/examples/demo-template/database-service/pom.xml
@@ -1,73 +1,73 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>database-service</artifactId>
-    <packaging>war</packaging>
-    <name>JAX-RS Database Service Using OAuth Bearer Tokens</name>
-    <description/>
-    <url>http://maven.apache.org</url>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>database</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>database-service</artifactId>
+    <packaging>war</packaging>
+    <name>JAX-RS Database Service Using OAuth Bearer Tokens</name>
+    <description/>
+    <url>http://maven.apache.org</url>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>database</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/pom.xml b/examples/demo-template/pom.xml
index 20515f5..a0172c8 100755
--- a/examples/demo-template/pom.xml
+++ b/examples/demo-template/pom.xml
@@ -1,61 +1,61 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Examples</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-examples-demo-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <!-- <module>server</module> -->
-        <module>customer-app</module>
-        <module>customer-app-cli</module>
-        <module>customer-app-js</module>
-        <module>product-app</module>
-        <module>example-ear</module>
-        <module>admin-access-app</module>
-        <module>angular-product-app</module>
-        <module>database-service</module>
-        <module>third-party</module>
-        <module>third-party-cdi</module>
-    </modules>
-
-    <profiles>
-        <profile>
-            <id>no-keycloak-json</id>
-            <activation>
-                <property>
-                    <name>no-keycloak-json</name>
-                </property>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-war-plugin</artifactId>
-                        <configuration>
-                            <packagingExcludes>**/keycloak.json</packagingExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-examples-demo-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <!-- <module>server</module> -->
+        <module>customer-app</module>
+        <module>customer-app-cli</module>
+        <module>customer-app-js</module>
+        <module>product-app</module>
+        <module>example-ear</module>
+        <module>admin-access-app</module>
+        <module>angular-product-app</module>
+        <module>database-service</module>
+        <module>third-party</module>
+        <module>third-party-cdi</module>
+    </modules>
+
+    <profiles>
+        <profile>
+            <id>no-keycloak-json</id>
+            <activation>
+                <property>
+                    <name>no-keycloak-json</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-war-plugin</artifactId>
+                        <configuration>
+                            <packagingExcludes>**/keycloak.json</packagingExcludes>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/examples/demo-template/product-app/pom.xml b/examples/demo-template/product-app/pom.xml
index fca37fe..a121d34 100755
--- a/examples/demo-template/product-app/pom.xml
+++ b/examples/demo-template/product-app/pom.xml
@@ -1,67 +1,67 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>product-portal-example</artifactId>
-    <packaging>war</packaging>
-    <name>Product Portal </name>
-    <description/>
-
-    <repositories>
-        <repository>
-            <id>jboss</id>
-            <name>jboss repo</name>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>product-portal</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>product-portal-example</artifactId>
+    <packaging>war</packaging>
+    <name>Product Portal </name>
+    <description/>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>product-portal</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
index 3e86343..9f5f61b 100755
--- a/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
+++ b/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
@@ -1,65 +1,65 @@
-package org.keycloak.example.oauth;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.util.JsonSerialization;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProductDatabaseClient
-{
-    static class TypedList extends ArrayList<String> {}
-
-    public static class Failure extends Exception {
-        private int status;
-
-        public Failure(int status) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-    }
-
-    public static List<String> getProducts(HttpServletRequest req) throws Failure {
-        KeycloakSecurityContext session = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
-
-        HttpClient client = new DefaultHttpClient();
-        try {
-            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/products");
-            get.addHeader("Authorization", "Bearer " + session.getTokenString());
-            try {
-                HttpResponse response = client.execute(get);
-                if (response.getStatusLine().getStatusCode() != 200) {
-                    throw new Failure(response.getStatusLine().getStatusCode());
-                }
-                HttpEntity entity = response.getEntity();
-                InputStream is = entity.getContent();
-                try {
-                    return JsonSerialization.readValue(is, TypedList.class);
-                } finally {
-                    is.close();
-                }
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            client.getConnectionManager().shutdown();
-        }
-    }
-
-}
+package org.keycloak.example.oauth;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.util.JsonSerialization;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProductDatabaseClient
+{
+    static class TypedList extends ArrayList<String> {}
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+    public static List<String> getProducts(HttpServletRequest req) throws Failure {
+        KeycloakSecurityContext session = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
+
+        HttpClient client = new DefaultHttpClient();
+        try {
+            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/products");
+            get.addHeader("Authorization", "Bearer " + session.getTokenString());
+            try {
+                HttpResponse response = client.execute(get);
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new Failure(response.getStatusLine().getStatusCode());
+                }
+                HttpEntity entity = response.getEntity();
+                InputStream is = entity.getContent();
+                try {
+                    return JsonSerialization.readValue(is, TypedList.class);
+                } finally {
+                    is.close();
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } finally {
+            client.getConnectionManager().shutdown();
+        }
+    }
+
+}
diff --git a/examples/demo-template/product-app/src/main/webapp/products/servlet-logout.jsp b/examples/demo-template/product-app/src/main/webapp/products/servlet-logout.jsp
index c293f03..8bf4fa5 100755
--- a/examples/demo-template/product-app/src/main/webapp/products/servlet-logout.jsp
+++ b/examples/demo-template/product-app/src/main/webapp/products/servlet-logout.jsp
@@ -1,14 +1,14 @@
-<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
-         pageEncoding="ISO-8859-1"%>
-<%@ page session="false" %>
-<html>
-<head>
-    <title>Servlet Logout</title>
-</head>
-<body bgcolor="#F5F6CE">
-Performs a servlet logout
-<%
-    request.logout();
-%>
-</body>
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+         pageEncoding="ISO-8859-1"%>
+<%@ page session="false" %>
+<html>
+<head>
+    <title>Servlet Logout</title>
+</head>
+<body bgcolor="#F5F6CE">
+Performs a servlet logout
+<%
+    request.logout();
+%>
+</body>
 </html>
\ No newline at end of file
diff --git a/examples/demo-template/README.md b/examples/demo-template/README.md
index ec5e02e..1a896af 100755
--- a/examples/demo-template/README.md
+++ b/examples/demo-template/README.md
@@ -1,221 +1,221 @@
-Login, Distributed SSO, Distributed Logout, and OAuth Token Grant Examples
-===================================
-The following examples requires Wildfly 8.0.0, JBoss EAP 6.x, or JBoss AS 7.1.1.  Here's the highlights of the examples
-* Delegating authentication of a web app to the remote authentication server via OAuth 2 protocols
-* Distributed Single-Sign-On and Single-Logout
-* Transferring identity and role mappings via a special bearer token (Skeleton Key Token).
-* Bearer token authentication and authorization of JAX-RS services
-* Obtaining bearer tokens via the OAuth2 protocol
-* Interact with the Keycloak Admin REST Api
-
-There are multiple WAR projects.  These will all run on the same WildFly instance, but pretend each one is running on a different
-machine on the network or Internet.
-* **customer-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
-* **customer-app-js** A pure HTML/Javascript application that does remote login using OAuth2 browser redirects with the auth server
-* **customer-app-cli** A pure CLI application that does remote login using OAuth2 browser redirects with the auth server
-* **product-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
-* **admin-access-app** A WAR application that does remote REST login to admin console to obtain a list of realm roles from Admin REST API
-* **angular-product-app** An Angular JS pure HTML5/Javascript application.
-* **database-service** JAX-RS services authenticated by bearer tokens only. The customer and product app invoke on it to get data
-* **third-party** Simple WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
-* **third-party-cdi** Simple CDI/JSF WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
-
-The UI of each of these applications is very crude and exists just to show our OAuth2 implementation in action.
-
-_This demo is meant to run on the same server instance as the Keycloak Server!_
-
-
-Step 1: Make sure you've set up the Keycloak Server
---------------------------------------
-The Keycloak Appliance Distribution comes with a preconfigured Keycloak server (based on Wildfly).  You can use it out of
-the box to run these demos.  So, if you're using this, you can head to Step 2.
-
-Alternatively, you can install the Keycloak Server onto any EAP 6.x, or Wildfly 8.x server, but there is
-a few steps you must follow. You need to obtain latest keycloak-war-dist-all.zip.  This distro is used to install Keycloak onto an existing JBoss installation.
-This installs the server using a WAR file.
-
-    $ cd ${jboss.as7.home}/standalone
-    $ cp -r ${keycloak-war-dist-all}/deployments .
-
-To be able to run the demos you also need to install the Keycloak client adapter. For Wildfly:
-
-    $ cd ${wildfly.home}
-    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-wildfly-adapter-dist.zip
-
-For JBoss EAP 6.x
-
-    $ cd ${eap.home}
-    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-eap6-adapter-dist.zip
-
-For JBoss AS 7.1.1:
-
-    $ cd ${as7.home}
-    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-as7-adapter-dist.zip
-
-WARNING: Note that we don't officially support Keycloak auth-server running on JBoss AS 7.1.1. You can still test examples running on AS 7.1.1,
-but then you may need to do few additional changes in examples to point them into external Keycloak server running on WildFly or EAP 6.x.
-This is especially changing "auth-server-url" in keycloak.json files to be non-relative as examples and auth-server will run on different server!
-
-Unzipping the adapter ZIP only installs the JAR files.  You must also add the Keycloak Subsystem to the server's
-configuration (standalone/configuration/standalone.xml).
-
-For WildFly and JBoss EAP 6.x
-    <server xmlns="urn:jboss:domain:1.4">
-
-        <extensions>
-            <extension module="org.keycloak.keycloak-subsystem"/>
-            ...
-        </extensions>
-
-        <profile>
-            <subsystem xmlns="urn:jboss:domain:keycloak:1.0">
-                <auth-server name="main-auth-server">
-                    <enabled>true</enabled>
-                    <web-context>auth</web-context>
-                </auth-server>
-            </subsystem>
-            ...
-        </profile>
-
-For AS 7.1.1:
-    <server xmlns="urn:jboss:domain:1.4">
-
-        <extensions>
-            <extension module="org.keycloak.keycloak-as7-subsystem"/>
-            ...
-        </extensions>
-
-        <profile>
-            <subsystem xmlns="urn:jboss:domain:keycloak:1.0"/>
-            ...
-        </profile>
-
-Step 2: Boot Keycloak Server
----------------------------------------
-Where you go to start up the Keycloak Server depends on which distro you installed.
-
-From appliance:
-
-```
-$ cd keycloak/bin
-$ ./standalone.sh
-```
-
-
-From existing Wildfly/EAP6/AS7 distro
-
-```
-$ cd ${wildfly.jboss.home}/bin
-$ ./standalone.sh
-```
-
-
-Step 3: Import the Test Realm
----------------------------------------
-Next thing you have to do is import the test realm for the demo.  Clicking on the below link will bring you to the
-create realm page in the Admin UI.  The username/password is admin/admin to login in.  Keycloak will ask you to
-create a new admin password before you can go to the create realm page.
-
-[http://localhost:8080/auth/admin/master/console/#/create/realm](http://localhost:8080/auth/admin/master/console/#/create/realm)
-
-Import the testrealm.json file that is in the preconfigured-demo/ example directory.
-
-
-Step 4: Build and deploy
----------------------------------------
-next you must build and deploy
-
-```
-cd preconfigured-demo
-mvn clean install
-```
-
-On EAP6/AS7 run:
-
-```
-mvn jboss-as:deploy
-```
-
-Or for WildFly run:
-
-```
-mvn wildfly:deploy
-```
-
-
-Step 5: Login and Observe Apps
----------------------------------------
-Try going to the customer app and view customer data:
-
-[http://localhost:8080/customer-portal/customers/view.jsp](http://localhost:8080/customer-portal/customers/view.jsp)
-
-This should take you to the auth-server login screen.  Enter username: bburke@redhat.com and password: password.
-
-If you click on the products link, you'll be taken to the products app and show a product listing.  The redirects
-are still happening, but the auth-server knows you are already logged in so the login is bypassed.
-
-If you click on the logout link of either of the product or customer app, you'll be logged out of all the applications.
-
-If you click on [http://localhost:8080/customer-portal-js](http://localhost:8080/customer-portal-js) you can invoke
-on the pure HTML/Javascript application.
-
-Step 6: Traditional OAuth2 Example
-----------------------------------
-The customer and product apps are logins.  The third-party app is the traditional OAuth2 usecase of a client wanting
-to get permission to access a user's data. To run this example open
-
-[http://localhost:8080/oauth-client](http://localhost:8080/oauth-client)
-
-If you are already logged in, you will not be asked for a username and password, but you will be redirected to
-an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
-
-Step 7: Try the CLI Example
----------------------------
-To try the CLI example run the following commands:
-
-$ cd customer-app-cli
-$ mvn exec:java
-
-This will open a shell that lets you specify a few different commands. For example type 'login' and press enter to login. Pressing enter with a blank line will display the available commands.
-
-The CLI example has two alternative methods for login. When a browser is available the CLI opens the login form in a browser, and will automatically retrieve the return code by starting a 
-temporary web server on a free port. If a browser is not available the URL to login is displayed on the CLI. The user can copy this URL to another computer that has a browser available. The code
-is displayed to the user after login and the user has to copy this code back to the application.
-
-Step 8: Admin REST API
-----------------------------------
-Keycloak has a Admin REST API.  This example shows an application making a remove direct login to Keycloak to obtain a token
-then using that token to access the Admin REST API.
-
-[http://localhost:8080/admin-access](http://localhost:8080/admin-access)
-
-If you are already logged in, you will not be asked for a username and password, but you will be redirected to
-an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
-
-Step 9: Angular JS Example
-----------------------------------
-An Angular JS example using Keycloak to secure it.
-
-[http://localhost:8080/angular-product](http://localhost:8080/angular-product)
-
-If you are already logged in, you will not be asked for a username and password, but you will be redirected to
-an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
-
-Step 9: Pure HTML5/Javascript Example
-----------------------------------
-An pure HTML5/Javascript example using Keycloak to secure it.
-
-[http://localhost:8080/customer-portal-js](http://localhost:8080/customer-portal-js)
-
-If you are already logged in, you will not be asked for a username and password, but you will be redirected to
-an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
-
-Admin Console
-==========================
-
-[http://localhost:8080/auth/admin/index.html](http://localhost:8080/auth/admin/index.html)
-
-
-
-
-
+Login, Distributed SSO, Distributed Logout, and OAuth Token Grant Examples
+===================================
+The following examples requires Wildfly 8.0.0, JBoss EAP 6.x, or JBoss AS 7.1.1.  Here's the highlights of the examples
+* Delegating authentication of a web app to the remote authentication server via OAuth 2 protocols
+* Distributed Single-Sign-On and Single-Logout
+* Transferring identity and role mappings via a special bearer token (Skeleton Key Token).
+* Bearer token authentication and authorization of JAX-RS services
+* Obtaining bearer tokens via the OAuth2 protocol
+* Interact with the Keycloak Admin REST Api
+
+There are multiple WAR projects.  These will all run on the same WildFly instance, but pretend each one is running on a different
+machine on the network or Internet.
+* **customer-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
+* **customer-app-js** A pure HTML/Javascript application that does remote login using OAuth2 browser redirects with the auth server
+* **customer-app-cli** A pure CLI application that does remote login using OAuth2 browser redirects with the auth server
+* **product-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
+* **admin-access-app** A WAR application that does remote REST login to admin console to obtain a list of realm roles from Admin REST API
+* **angular-product-app** An Angular JS pure HTML5/Javascript application.
+* **database-service** JAX-RS services authenticated by bearer tokens only. The customer and product app invoke on it to get data
+* **third-party** Simple WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
+* **third-party-cdi** Simple CDI/JSF WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
+
+The UI of each of these applications is very crude and exists just to show our OAuth2 implementation in action.
+
+_This demo is meant to run on the same server instance as the Keycloak Server!_
+
+
+Step 1: Make sure you've set up the Keycloak Server
+--------------------------------------
+The Keycloak Appliance Distribution comes with a preconfigured Keycloak server (based on Wildfly).  You can use it out of
+the box to run these demos.  So, if you're using this, you can head to Step 2.
+
+Alternatively, you can install the Keycloak Server onto any EAP 6.x, or Wildfly 8.x server, but there is
+a few steps you must follow. You need to obtain latest keycloak-war-dist-all.zip.  This distro is used to install Keycloak onto an existing JBoss installation.
+This installs the server using a WAR file.
+
+    $ cd ${jboss.as7.home}/standalone
+    $ cp -r ${keycloak-war-dist-all}/deployments .
+
+To be able to run the demos you also need to install the Keycloak client adapter. For Wildfly:
+
+    $ cd ${wildfly.home}
+    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-wildfly-adapter-dist.zip
+
+For JBoss EAP 6.x
+
+    $ cd ${eap.home}
+    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-eap6-adapter-dist.zip
+
+For JBoss AS 7.1.1:
+
+    $ cd ${as7.home}
+    $ unzip ${keycloak-war-dist-all}/adapters/keycloak-as7-adapter-dist.zip
+
+WARNING: Note that we don't officially support Keycloak auth-server running on JBoss AS 7.1.1. You can still test examples running on AS 7.1.1,
+but then you may need to do few additional changes in examples to point them into external Keycloak server running on WildFly or EAP 6.x.
+This is especially changing "auth-server-url" in keycloak.json files to be non-relative as examples and auth-server will run on different server!
+
+Unzipping the adapter ZIP only installs the JAR files.  You must also add the Keycloak Subsystem to the server's
+configuration (standalone/configuration/standalone.xml).
+
+For WildFly and JBoss EAP 6.x
+    <server xmlns="urn:jboss:domain:1.4">
+
+        <extensions>
+            <extension module="org.keycloak.keycloak-subsystem"/>
+            ...
+        </extensions>
+
+        <profile>
+            <subsystem xmlns="urn:jboss:domain:keycloak:1.0">
+                <auth-server name="main-auth-server">
+                    <enabled>true</enabled>
+                    <web-context>auth</web-context>
+                </auth-server>
+            </subsystem>
+            ...
+        </profile>
+
+For AS 7.1.1:
+    <server xmlns="urn:jboss:domain:1.4">
+
+        <extensions>
+            <extension module="org.keycloak.keycloak-as7-subsystem"/>
+            ...
+        </extensions>
+
+        <profile>
+            <subsystem xmlns="urn:jboss:domain:keycloak:1.0"/>
+            ...
+        </profile>
+
+Step 2: Boot Keycloak Server
+---------------------------------------
+Where you go to start up the Keycloak Server depends on which distro you installed.
+
+From appliance:
+
+```
+$ cd keycloak/bin
+$ ./standalone.sh
+```
+
+
+From existing Wildfly/EAP6/AS7 distro
+
+```
+$ cd ${wildfly.jboss.home}/bin
+$ ./standalone.sh
+```
+
+
+Step 3: Import the Test Realm
+---------------------------------------
+Next thing you have to do is import the test realm for the demo.  Clicking on the below link will bring you to the
+create realm page in the Admin UI.  The username/password is admin/admin to login in.  Keycloak will ask you to
+create a new admin password before you can go to the create realm page.
+
+[http://localhost:8080/auth/admin/master/console/#/create/realm](http://localhost:8080/auth/admin/master/console/#/create/realm)
+
+Import the testrealm.json file that is in the preconfigured-demo/ example directory.
+
+
+Step 4: Build and deploy
+---------------------------------------
+next you must build and deploy
+
+```
+cd preconfigured-demo
+mvn clean install
+```
+
+On EAP6/AS7 run:
+
+```
+mvn jboss-as:deploy
+```
+
+Or for WildFly run:
+
+```
+mvn wildfly:deploy
+```
+
+
+Step 5: Login and Observe Apps
+---------------------------------------
+Try going to the customer app and view customer data:
+
+[http://localhost:8080/customer-portal/customers/view.jsp](http://localhost:8080/customer-portal/customers/view.jsp)
+
+This should take you to the auth-server login screen.  Enter username: bburke@redhat.com and password: password.
+
+If you click on the products link, you'll be taken to the products app and show a product listing.  The redirects
+are still happening, but the auth-server knows you are already logged in so the login is bypassed.
+
+If you click on the logout link of either of the product or customer app, you'll be logged out of all the applications.
+
+If you click on [http://localhost:8080/customer-portal-js](http://localhost:8080/customer-portal-js) you can invoke
+on the pure HTML/Javascript application.
+
+Step 6: Traditional OAuth2 Example
+----------------------------------
+The customer and product apps are logins.  The third-party app is the traditional OAuth2 usecase of a client wanting
+to get permission to access a user's data. To run this example open
+
+[http://localhost:8080/oauth-client](http://localhost:8080/oauth-client)
+
+If you are already logged in, you will not be asked for a username and password, but you will be redirected to
+an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
+
+Step 7: Try the CLI Example
+---------------------------
+To try the CLI example run the following commands:
+
+$ cd customer-app-cli
+$ mvn exec:java
+
+This will open a shell that lets you specify a few different commands. For example type 'login' and press enter to login. Pressing enter with a blank line will display the available commands.
+
+The CLI example has two alternative methods for login. When a browser is available the CLI opens the login form in a browser, and will automatically retrieve the return code by starting a 
+temporary web server on a free port. If a browser is not available the URL to login is displayed on the CLI. The user can copy this URL to another computer that has a browser available. The code
+is displayed to the user after login and the user has to copy this code back to the application.
+
+Step 8: Admin REST API
+----------------------------------
+Keycloak has a Admin REST API.  This example shows an application making a remove direct login to Keycloak to obtain a token
+then using that token to access the Admin REST API.
+
+[http://localhost:8080/admin-access](http://localhost:8080/admin-access)
+
+If you are already logged in, you will not be asked for a username and password, but you will be redirected to
+an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
+
+Step 9: Angular JS Example
+----------------------------------
+An Angular JS example using Keycloak to secure it.
+
+[http://localhost:8080/angular-product](http://localhost:8080/angular-product)
+
+If you are already logged in, you will not be asked for a username and password, but you will be redirected to
+an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
+
+Step 9: Pure HTML5/Javascript Example
+----------------------------------
+An pure HTML5/Javascript example using Keycloak to secure it.
+
+[http://localhost:8080/customer-portal-js](http://localhost:8080/customer-portal-js)
+
+If you are already logged in, you will not be asked for a username and password, but you will be redirected to
+an oauth grant page.  This page asks you if you want to grant certain permissions to the third-part app.
+
+Admin Console
+==========================
+
+[http://localhost:8080/auth/admin/index.html](http://localhost:8080/auth/admin/index.html)
+
+
+
+
+
diff --git a/examples/demo-template/README.md.unconfigured b/examples/demo-template/README.md.unconfigured
index 2752997..a7d1893 100755
--- a/examples/demo-template/README.md.unconfigured
+++ b/examples/demo-template/README.md.unconfigured
@@ -1,137 +1,137 @@
-Unconfigured Examples
-===================================
-This set of projects contains a stripped down version of the demo described in preconfigured-demo.  All keycloak specific
-configuration has been removed. Use this project in conjunction with instructions below and/or the online screencast tutorials at
-[http://keycloak.org/docs](http://keycloak.org/docs).
-
-
-# Run Demo with an external Keycloak Server
-
-These instructions assume you've already installed and started a Keycloak Server. Keycloak can be running on your locally or remotely (for example on OpenShift). If you're not running Keycloak locally you'll also need a locally running WildFly server.
-
-## Create Realm
-
-Open the Keycloak admin console and click on `Add Realm`. Enter `demo` as the name for the realm and click `Save`.
-
-The demo applications uses two realm roles, `user` and `admin`, so the next step is to create these. Click on `Roles` then click on `Add Role`. Use `user` as the role name and click `Save`. Repeat to create a role with the name `admin`.
-
-Next you'll either want to enable user registration or create a new user.
-
-### Enable user registration
-
-To enable user registration first click on `Roles` then `Default Roles`. Select the `user` role and click on the right arrow. This will make sure that all new users are automatically assigned the `user` role. Next step is to enable user registration for the realm. Click on `Settings` then `Login`. Click on the toggle for `user registration` to allow users to self-register.
-
-### Create user
-
-To create a new user click on `Users` then `Add User`. You are required to at least fill in the `username` field, but you may want to fill in values for the other fields as well. After you've completed the form click on `Save`. To allow the user to login you also need to set a password for the user. To do this click on `Credentials`. Enter a new password for the user. If you leave the `Temporary` toggle ON the user will be required to reset the password on the next login.
-
-
-## Deploy Demo Applications
-
-First you need to install WildFly application server. Second step is to install the Keycloak WildFly subsystem. To do this run:
-
-    # cd <WILDFLY HOME>
-    # unzip <KEYCLOAK DIST>/adapters/keycloak-wildfly-adapter-dist-<KEYCLOAK VERSION>.zip
-
-Next configure the Keycloak adapter by editing `standalone/configuration/standalone.xml`. Add a new child-element to `<extensions>`:
-
-    <extensions>
-        ....
-        <extension module="org.keycloak.keycloak-subsystem"/>
-    </extensions>
-
-You also need to add realm config to the same file. Add a new child-element to `<profile>`:
-
-    <profile>
-        ....
-        <subsystem xmlns="urn:jboss:domain:keycloak:1.0">
-            <realm name="demo">
-                <realm-public-key>REALM PUBLIC KEY</realm-public-key>
-                <auth-server-url>KEYCLOAK URL</auth-server-url>
-                <ssl-required>external</ssl-required>
-            </realm>
-        </subsystem>
-    </profile>
-
-In the above snippet replace the following:
-
-* `REALM PUBLIC KEY` - replace with the public key for the realm. You can find this in the admin console by selecting the realm, then clicking on `Keys`
-* `KEYCLOAK URL` - replace with the base url of Keycloak (for example http://localhost:8080/auth or http://keycloak.example.org/auth)
-
-Don't start the WildFly server until you've configured and deployed the demo applications.
-
-### Database Services
-
-Most demo applications connects to the REST services provided by the database-services application, so start with deploying this.
-
-Run the following to deploy it:
-
-    # cd database-services
-    # mvn install
-    # cp target/database.war <WILDFLY HOME>/standalone/deployments
-
-Next add the configuration for it to the Keycloak subsystem. Edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">` add:
-
-    <secure-deployment name="database.war">
-        <realm>demo</realm>
-        <resource>database-service</resource>
-        <bearer-only>true</bearer-only>
-    </secure-deployment>
-
-### Customer Portal
-
-Next deploy the customer portal application.
-
-Run the following to deploy it:
-
-    # cd customer-app
-    # mvn install
-    # cp target/customer-portal.war <WILDFLY HOME>/standalone/deployments
-
-Then open the Keycloak admin console to add a configuration for it. Navigate to the realm and click on `Applications` then `Add Application`. Fill in the form with:
-
-* Name - `customer-portal`
-* Redirect URI - `http://localhost:8080/customer-portal/*` (click `Add` after filling in the field)
-
-Then click on `Save`. As it's a confidential (non-public) application you need the secret for it. Click on `Credentials` and note the value of the `Secret` field.
-
-Then edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` and add the following to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">`:
-
-    <secure-deployment name="customer-portal.war">
-        <realm>demo</realm>
-        <resource>customer-portal</resource>
-        <credential name="secret">APPLICATION SECRET</credential>
-    </secure-deployment>
-
-In the above snippet replace the following:
-
-* `APPLICATION SECRET` - replace with the applications secret you just noted from the Keycloak admin console
-
-### Product Portal
-
-Next deploy the product portal application.
-
-Run the following to deploy it:
-
-    # cd product-app
-    # mvn install
-    # cp target/product-portal.war <WILDFLY HOME>/standalone/deployments
-
-Then open the Keycloak admin console to add a configuration for it. Navigate to the realm and click on `Applications` then `Add Application`. Fill in the form with:
-
-* Name - `product-portal`
-* Redirect URI - `http://localhost:8080/product-portal/*` (click `Add` after filling in the field)
-
-Then click on `Save`. As it's a confidential (non-public) application you need the secret for it. Click on `Credentials` and note the value of the `Secret` field.
-
-Then edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` and add the following to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">`:
-
-    <secure-deployment name="product-portal.war">
-        <realm>demo</realm>
-        <resource>product-portal</resource>
-        <credential name="secret">APPLICATION SECRET</credential>
-    </secure-deployment>
-
-In the above snippet replace the following:
-
+Unconfigured Examples
+===================================
+This set of projects contains a stripped down version of the demo described in preconfigured-demo.  All keycloak specific
+configuration has been removed. Use this project in conjunction with instructions below and/or the online screencast tutorials at
+[http://keycloak.org/docs](http://keycloak.org/docs).
+
+
+# Run Demo with an external Keycloak Server
+
+These instructions assume you've already installed and started a Keycloak Server. Keycloak can be running on your locally or remotely (for example on OpenShift). If you're not running Keycloak locally you'll also need a locally running WildFly server.
+
+## Create Realm
+
+Open the Keycloak admin console and click on `Add Realm`. Enter `demo` as the name for the realm and click `Save`.
+
+The demo applications uses two realm roles, `user` and `admin`, so the next step is to create these. Click on `Roles` then click on `Add Role`. Use `user` as the role name and click `Save`. Repeat to create a role with the name `admin`.
+
+Next you'll either want to enable user registration or create a new user.
+
+### Enable user registration
+
+To enable user registration first click on `Roles` then `Default Roles`. Select the `user` role and click on the right arrow. This will make sure that all new users are automatically assigned the `user` role. Next step is to enable user registration for the realm. Click on `Settings` then `Login`. Click on the toggle for `user registration` to allow users to self-register.
+
+### Create user
+
+To create a new user click on `Users` then `Add User`. You are required to at least fill in the `username` field, but you may want to fill in values for the other fields as well. After you've completed the form click on `Save`. To allow the user to login you also need to set a password for the user. To do this click on `Credentials`. Enter a new password for the user. If you leave the `Temporary` toggle ON the user will be required to reset the password on the next login.
+
+
+## Deploy Demo Applications
+
+First you need to install WildFly application server. Second step is to install the Keycloak WildFly subsystem. To do this run:
+
+    # cd <WILDFLY HOME>
+    # unzip <KEYCLOAK DIST>/adapters/keycloak-wildfly-adapter-dist-<KEYCLOAK VERSION>.zip
+
+Next configure the Keycloak adapter by editing `standalone/configuration/standalone.xml`. Add a new child-element to `<extensions>`:
+
+    <extensions>
+        ....
+        <extension module="org.keycloak.keycloak-subsystem"/>
+    </extensions>
+
+You also need to add realm config to the same file. Add a new child-element to `<profile>`:
+
+    <profile>
+        ....
+        <subsystem xmlns="urn:jboss:domain:keycloak:1.0">
+            <realm name="demo">
+                <realm-public-key>REALM PUBLIC KEY</realm-public-key>
+                <auth-server-url>KEYCLOAK URL</auth-server-url>
+                <ssl-required>external</ssl-required>
+            </realm>
+        </subsystem>
+    </profile>
+
+In the above snippet replace the following:
+
+* `REALM PUBLIC KEY` - replace with the public key for the realm. You can find this in the admin console by selecting the realm, then clicking on `Keys`
+* `KEYCLOAK URL` - replace with the base url of Keycloak (for example http://localhost:8080/auth or http://keycloak.example.org/auth)
+
+Don't start the WildFly server until you've configured and deployed the demo applications.
+
+### Database Services
+
+Most demo applications connects to the REST services provided by the database-services application, so start with deploying this.
+
+Run the following to deploy it:
+
+    # cd database-services
+    # mvn install
+    # cp target/database.war <WILDFLY HOME>/standalone/deployments
+
+Next add the configuration for it to the Keycloak subsystem. Edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">` add:
+
+    <secure-deployment name="database.war">
+        <realm>demo</realm>
+        <resource>database-service</resource>
+        <bearer-only>true</bearer-only>
+    </secure-deployment>
+
+### Customer Portal
+
+Next deploy the customer portal application.
+
+Run the following to deploy it:
+
+    # cd customer-app
+    # mvn install
+    # cp target/customer-portal.war <WILDFLY HOME>/standalone/deployments
+
+Then open the Keycloak admin console to add a configuration for it. Navigate to the realm and click on `Applications` then `Add Application`. Fill in the form with:
+
+* Name - `customer-portal`
+* Redirect URI - `http://localhost:8080/customer-portal/*` (click `Add` after filling in the field)
+
+Then click on `Save`. As it's a confidential (non-public) application you need the secret for it. Click on `Credentials` and note the value of the `Secret` field.
+
+Then edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` and add the following to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">`:
+
+    <secure-deployment name="customer-portal.war">
+        <realm>demo</realm>
+        <resource>customer-portal</resource>
+        <credential name="secret">APPLICATION SECRET</credential>
+    </secure-deployment>
+
+In the above snippet replace the following:
+
+* `APPLICATION SECRET` - replace with the applications secret you just noted from the Keycloak admin console
+
+### Product Portal
+
+Next deploy the product portal application.
+
+Run the following to deploy it:
+
+    # cd product-app
+    # mvn install
+    # cp target/product-portal.war <WILDFLY HOME>/standalone/deployments
+
+Then open the Keycloak admin console to add a configuration for it. Navigate to the realm and click on `Applications` then `Add Application`. Fill in the form with:
+
+* Name - `product-portal`
+* Redirect URI - `http://localhost:8080/product-portal/*` (click `Add` after filling in the field)
+
+Then click on `Save`. As it's a confidential (non-public) application you need the secret for it. Click on `Credentials` and note the value of the `Secret` field.
+
+Then edit `<WILDFLY HOME>/standalone/configuration/standalone.xml` and add the following to `<subsystem xmlns="urn:jboss:domain:keycloak:1.0">`:
+
+    <secure-deployment name="product-portal.war">
+        <realm>demo</realm>
+        <resource>product-portal</resource>
+        <credential name="secret">APPLICATION SECRET</credential>
+    </secure-deployment>
+
+In the above snippet replace the following:
+
 * `APPLICATION SECRET` - replace with the applications secret you just noted from the Keycloak admin console
\ No newline at end of file
diff --git a/examples/demo-template/subsystem-config.xml b/examples/demo-template/subsystem-config.xml
index b2b2c8e..e9dce6b 100755
--- a/examples/demo-template/subsystem-config.xml
+++ b/examples/demo-template/subsystem-config.xml
@@ -1,23 +1,23 @@
-<!-- works with keycloak.json that comes with example -->
-<subsystem xmlns="urn:jboss:domain:keycloak:1.0">
-    <realm name="demo">
-        <realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</realm-public-key>
-        <auth-server-url>/auth</auth-server-url>
-        <ssl-required>external</ssl-required>
-    </realm>
-    <secure-deployment name="customer-portal.war">
-        <realm>demo</realm>
-        <resource>customer-portal</resource>
-        <credential name="secret">password</credential>
-    </secure-deployment>
-    <secure-deployment name="product-portal.war">
-        <realm>demo</realm>
-        <resource>product-portal</resource>
-        <credential name="secret">password</credential>
-    </secure-deployment>
-    <secure-deployment name="database.war">
-        <realm>demo</realm>
-        <resource>database-service</resource>
-        <bearer-only>true</bearer-only>
-    </secure-deployment>
-</subsystem>
+<!-- works with keycloak.json that comes with example -->
+<subsystem xmlns="urn:jboss:domain:keycloak:1.0">
+    <realm name="demo">
+        <realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</realm-public-key>
+        <auth-server-url>/auth</auth-server-url>
+        <ssl-required>external</ssl-required>
+    </realm>
+    <secure-deployment name="customer-portal.war">
+        <realm>demo</realm>
+        <resource>customer-portal</resource>
+        <credential name="secret">password</credential>
+    </secure-deployment>
+    <secure-deployment name="product-portal.war">
+        <realm>demo</realm>
+        <resource>product-portal</resource>
+        <credential name="secret">password</credential>
+    </secure-deployment>
+    <secure-deployment name="database.war">
+        <realm>demo</realm>
+        <resource>database-service</resource>
+        <bearer-only>true</bearer-only>
+    </secure-deployment>
+</subsystem>
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index 9b83dfa..d592010 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -1,181 +1,181 @@
-{
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 60,
-    "accessCodeLifespan": 60,
-    "accessCodeLifespanUserAction": 300,
-    "ssoSessionIdleTimeout": 600,
-    "ssoSessionMaxLifespan": 36000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "stian",
-            "enabled": true,
-            "email" : "stian@redhat.com",
-            "firstName": "Stian",
-            "lastName": "Thorgersen",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda@redhat.com",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin@admin.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user","admin" ],
-            "clientRoles": {
-                "realm-management": [ "realm-admin" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "customer-portal",
-            "enabled": true,
-            "adminUrl": "/customer-portal",
-            "baseUrl": "/customer-portal",
-            "redirectUris": [
-                "/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "clientId": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "baseUrl": "/customer-portal-js",
-            "redirectUris": [
-                "/customer-portal-js/*"
-            ]
-        },
-        {
-            "clientId": "angular-product",
-            "enabled": true,
-            "publicClient": true,
-            "baseUrl": "/angular-product/index.html",
-            "redirectUris": [
-                "/angular-product/*"
-            ]
-        },
-        {
-            "clientId": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "clientId": "product-portal",
-            "enabled": true,
-            "adminUrl": "/product-portal",
-            "baseUrl": "/product-portal",
-            "redirectUris": [
-                "/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "clientId": "database-service",
-            "enabled": true,
-            "adminUrl": "/database",
-            "baseUrl": "/database",
-            "bearerOnly": true
-        },
-        {
-            "clientId": "third-party",
-            "enabled": true,
-            "consentRequired": true,
-            "redirectUris": [
-                "/oauth-client/*",
-                "/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "clientId": "admin-client",
-            "enabled": true,
-            "publicClient": true,
-            "directGrantsOnly": true,
-            "consentRequired": true
-        }
-    ],
-    "clientScopeMappings": {
-        "realm-management": [
-            {
-                "client": "admin-client",
-                "roles": ["realm-admin"]
-            },
-            {
-                "client": "customer-portal",
-                "roles": ["realm-admin"]
-            }
-        ]
-    }
-
-
-}
+{
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 60,
+    "accessCodeLifespan": 60,
+    "accessCodeLifespanUserAction": 300,
+    "ssoSessionIdleTimeout": 600,
+    "ssoSessionMaxLifespan": 36000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "stian",
+            "enabled": true,
+            "email" : "stian@redhat.com",
+            "firstName": "Stian",
+            "lastName": "Thorgersen",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda@redhat.com",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin@admin.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user","admin" ],
+            "clientRoles": {
+                "realm-management": [ "realm-admin" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "customer-portal",
+            "enabled": true,
+            "adminUrl": "/customer-portal",
+            "baseUrl": "/customer-portal",
+            "redirectUris": [
+                "/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "clientId": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "/customer-portal-js",
+            "redirectUris": [
+                "/customer-portal-js/*"
+            ]
+        },
+        {
+            "clientId": "angular-product",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "/angular-product/index.html",
+            "redirectUris": [
+                "/angular-product/*"
+            ]
+        },
+        {
+            "clientId": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "clientId": "product-portal",
+            "enabled": true,
+            "adminUrl": "/product-portal",
+            "baseUrl": "/product-portal",
+            "redirectUris": [
+                "/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "clientId": "database-service",
+            "enabled": true,
+            "adminUrl": "/database",
+            "baseUrl": "/database",
+            "bearerOnly": true
+        },
+        {
+            "clientId": "third-party",
+            "enabled": true,
+            "consentRequired": true,
+            "redirectUris": [
+                "/oauth-client/*",
+                "/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "clientId": "admin-client",
+            "enabled": true,
+            "publicClient": true,
+            "directGrantsOnly": true,
+            "consentRequired": true
+        }
+    ],
+    "clientScopeMappings": {
+        "realm-management": [
+            {
+                "client": "admin-client",
+                "roles": ["realm-admin"]
+            },
+            {
+                "client": "customer-portal",
+                "roles": ["realm-admin"]
+            }
+        ]
+    }
+
+
+}
diff --git a/examples/demo-template/third-party/pom.xml b/examples/demo-template/third-party/pom.xml
index e5e3ac4..6b25ae9 100755
--- a/examples/demo-template/third-party/pom.xml
+++ b/examples/demo-template/third-party/pom.xml
@@ -1,65 +1,65 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>oauth-client-example</artifactId>
-    <packaging>war</packaging>
-    <name>Simple OAuth Client</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <version>1.0.1.Final</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-servlet-oauth-client</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>oauth-client</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>oauth-client-example</artifactId>
+    <packaging>war</packaging>
+    <name>Simple OAuth Client</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <version>1.0.1.Final</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-servlet-oauth-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>oauth-client</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
index b0e0e00..3c4af78 100755
--- a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
+++ b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java
@@ -1,120 +1,120 @@
-package org.keycloak.example.oauth;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.ServerRequest;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.servlet.ServletOAuthClient;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.UriUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProductDatabaseClient {
-
-    public static class Failure extends Exception {
-        private int status;
-
-        public Failure(int status) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-    }
-
-
-    public static void redirect(HttpServletRequest request, HttpServletResponse response) {
-        // The ServletOAuthClient is obtained by getting a context attribute
-        // that is set in the Bootstrap context listener in this project.
-        // You really should come up with a better way to initialize
-        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
-        // and take a look how it works. You can also take a look at third-party-cdi example
-        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
-        try {
-            oAuthClient.redirectRelative("pull_data.jsp", request, response);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static class TypedList extends ArrayList<String> {}
-
-    public static AccessTokenResponse getTokenResponse(HttpServletRequest request) {
-        // The ServletOAuthClient is obtained by getting a context attribute
-        // that is set in the Bootstrap context listener in this project.
-        // You really should come up with a better way to initialize
-        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
-        // and take a look how it works. You can also take a look at third-party-cdi example
-        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
-        try {
-            return oAuthClient.getBearerToken(request);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        } catch (ServerRequest.HttpFailure failure) {
-            throw new RuntimeException(failure);
-        }
-
-    }
-
-    public static List<String> getProducts(HttpServletRequest request, String accessToken) throws Failure {
-        KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
-
-        // The ServletOAuthClient is obtained by getting a context attribute
-        // that is set in the Bootstrap context listener in this project.
-        // You really should come up with a better way to initialize
-        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
-        // and take a look how it works. You can also take a look at third-party-cdi example
-        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
-        HttpClient client = new DefaultHttpClient();
-
-        HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session) + "/database/products");
-        get.addHeader("Authorization", "Bearer " + accessToken);
-        try {
-            HttpResponse response = client.execute(get);
-            if (response.getStatusLine().getStatusCode() != 200) {
-                throw new Failure(response.getStatusLine().getStatusCode());
-            }
-            HttpEntity entity = response.getEntity();
-            InputStream is = entity.getContent();
-            try {
-                return JsonSerialization.readValue(is, TypedList.class);
-            } finally {
-                is.close();
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static String getBaseUrl(ServletOAuthClient oAuthClient, HttpServletRequest request) {
-        switch (oAuthClient.getRelativeUrlsUsed()) {
-            case ALL_REQUESTS:
-                // Resolve baseURI from the request
-                return UriUtils.getOrigin(request.getRequestURL().toString());
-            case BROWSER_ONLY:
-                // Resolve baseURI from the codeURL (This is already non-relative and based on our hostname)
-                return UriUtils.getOrigin(oAuthClient.getTokenUrl());
-            case NEVER:
-                return "";
-            default:
-                return "";
-        }
-    }
-
-}
+package org.keycloak.example.oauth;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.ServerRequest;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.servlet.ServletOAuthClient;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.UriUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProductDatabaseClient {
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+
+    public static void redirect(HttpServletRequest request, HttpServletResponse response) {
+        // The ServletOAuthClient is obtained by getting a context attribute
+        // that is set in the Bootstrap context listener in this project.
+        // You really should come up with a better way to initialize
+        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
+        // and take a look how it works. You can also take a look at third-party-cdi example
+        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
+        try {
+            oAuthClient.redirectRelative("pull_data.jsp", request, response);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class TypedList extends ArrayList<String> {}
+
+    public static AccessTokenResponse getTokenResponse(HttpServletRequest request) {
+        // The ServletOAuthClient is obtained by getting a context attribute
+        // that is set in the Bootstrap context listener in this project.
+        // You really should come up with a better way to initialize
+        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
+        // and take a look how it works. You can also take a look at third-party-cdi example
+        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
+        try {
+            return oAuthClient.getBearerToken(request);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } catch (ServerRequest.HttpFailure failure) {
+            throw new RuntimeException(failure);
+        }
+
+    }
+
+    public static List<String> getProducts(HttpServletRequest request, String accessToken) throws Failure {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
+
+        // The ServletOAuthClient is obtained by getting a context attribute
+        // that is set in the Bootstrap context listener in this project.
+        // You really should come up with a better way to initialize
+        // and obtain the ServletOAuthClient.  I actually suggest downloading the ServletOAuthClient code
+        // and take a look how it works. You can also take a look at third-party-cdi example
+        ServletOAuthClient oAuthClient = (ServletOAuthClient) request.getServletContext().getAttribute(ServletOAuthClient.class.getName());
+        HttpClient client = new DefaultHttpClient();
+
+        HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session) + "/database/products");
+        get.addHeader("Authorization", "Bearer " + accessToken);
+        try {
+            HttpResponse response = client.execute(get);
+            if (response.getStatusLine().getStatusCode() != 200) {
+                throw new Failure(response.getStatusLine().getStatusCode());
+            }
+            HttpEntity entity = response.getEntity();
+            InputStream is = entity.getContent();
+            try {
+                return JsonSerialization.readValue(is, TypedList.class);
+            } finally {
+                is.close();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String getBaseUrl(ServletOAuthClient oAuthClient, HttpServletRequest request) {
+        switch (oAuthClient.getRelativeUrlsUsed()) {
+            case ALL_REQUESTS:
+                // Resolve baseURI from the request
+                return UriUtils.getOrigin(request.getRequestURL().toString());
+            case BROWSER_ONLY:
+                // Resolve baseURI from the codeURL (This is already non-relative and based on our hostname)
+                return UriUtils.getOrigin(oAuthClient.getTokenUrl());
+            case NEVER:
+                return "";
+            default:
+                return "";
+        }
+    }
+
+}
diff --git a/examples/demo-template/third-party-cdi/pom.xml b/examples/demo-template/third-party-cdi/pom.xml
index d8b3f44..98489e2 100755
--- a/examples/demo-template/third-party-cdi/pom.xml
+++ b/examples/demo-template/third-party-cdi/pom.xml
@@ -1,83 +1,83 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-demo-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>oauth-client-cdi-example</artifactId>
-    <packaging>war</packaging>
-    <name>Simple OAuth Client Using CDI and JSF</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <version>1.0.1.Final</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.enterprise</groupId>
-            <artifactId>cdi-api</artifactId>
-            <version>1.0-SP4</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.faces</groupId>
-            <artifactId>jboss-jsf-api_2.1_spec</artifactId>
-            <version>2.0.1.Final</version>
-            <scope>provided</scope>
-        </dependency>
-        <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-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-servlet-oauth-client</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>oauth-client-cdi</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>oauth-client-cdi-example</artifactId>
+    <packaging>war</packaging>
+    <name>Simple OAuth Client Using CDI and JSF</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <version>1.0.1.Final</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.0-SP4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.faces</groupId>
+            <artifactId>jboss-jsf-api_2.1_spec</artifactId>
+            <version>2.0.1.Final</version>
+            <scope>provided</scope>
+        </dependency>
+        <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-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-servlet-oauth-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>oauth-client-cdi</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/DatabaseClient.java b/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/DatabaseClient.java
index 0a44037..981c973 100755
--- a/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/DatabaseClient.java
+++ b/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/DatabaseClient.java
@@ -1,113 +1,113 @@
-package org.keycloak.example.oauth;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.servlet.ServletOAuthClient;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.UriUtils;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- * @version $Revision: 1 $
- */
-@ApplicationScoped
-@Named("databaseClient")
-public class DatabaseClient {
-
-    @Inject
-    @ServletRequestQualifier
-    private HttpServletRequest request;
-
-    @Inject
-    private HttpServletResponse response;
-
-    @Inject
-    private FacesContext facesContext;
-
-    @Inject
-    private ServletOAuthClient oauthClient;
-
-    @Inject
-    private UserData userData;
-
-    private static final Logger logger = Logger.getLogger(DatabaseClient.class);
-
-    public void retrieveAccessToken() {
-        try {
-            oauthClient.redirectRelative("client.jsf", request, response);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static class TypedList extends ArrayList<String> {}
-
-    public void sendCustomersRequest() {
-        List<String> customers = sendRequestToDBApplication(getBaseUrl() + "/database/customers");
-        userData.setCustomers(customers);
-    }
-
-    public void sendProductsRequest() {
-        List<String> products = sendRequestToDBApplication(getBaseUrl() + "/database/products");
-        userData.setProducts(products);
-    }
-
-    protected List<String> sendRequestToDBApplication(String dbUri) {
-        HttpClient client = new DefaultHttpClient();
-        HttpGet get = new HttpGet(dbUri);
-        try {
-
-            if (userData.isHasAccessToken()) {
-                get.addHeader("Authorization", "Bearer " + userData.getAccessToken());
-            }
-
-            HttpResponse response = client.execute(get);
-            switch (response.getStatusLine().getStatusCode()) {
-                case 200: HttpEntity entity = response.getEntity();
-                    InputStream is = entity.getContent();
-                    try {
-                        return JsonSerialization.readValue(is, TypedList.class);
-                    } finally {
-                        is.close();
-                    }
-                case 401: facesContext.addMessage(null, new FacesMessage("Status: 401. Request not authenticated! You need to retrieve access token first."));
-                    break;
-                case 403: facesContext.addMessage(null, new FacesMessage("Status: 403. Access token has insufficient privileges"));
-                    break;
-                default: facesContext.addMessage(null, new FacesMessage("Status: " + response.getStatusLine() + ". Not able to retrieve data. See log for details"));
-                    logger.warn("Error occured. Status: " + response.getStatusLine());
-            }
-
-            return null;
-        } catch (IOException e) {
-            e.printStackTrace();
-            facesContext.addMessage(null, new FacesMessage("Unknown error. See log for details"));
-            return null;
-        }
-    }
-
-    public String getBaseUrl() {
-        KeycloakSecurityContext session = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
-        return AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session);
-    }
-
-}
+package org.keycloak.example.oauth;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.servlet.ServletOAuthClient;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.UriUtils;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @version $Revision: 1 $
+ */
+@ApplicationScoped
+@Named("databaseClient")
+public class DatabaseClient {
+
+    @Inject
+    @ServletRequestQualifier
+    private HttpServletRequest request;
+
+    @Inject
+    private HttpServletResponse response;
+
+    @Inject
+    private FacesContext facesContext;
+
+    @Inject
+    private ServletOAuthClient oauthClient;
+
+    @Inject
+    private UserData userData;
+
+    private static final Logger logger = Logger.getLogger(DatabaseClient.class);
+
+    public void retrieveAccessToken() {
+        try {
+            oauthClient.redirectRelative("client.jsf", request, response);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class TypedList extends ArrayList<String> {}
+
+    public void sendCustomersRequest() {
+        List<String> customers = sendRequestToDBApplication(getBaseUrl() + "/database/customers");
+        userData.setCustomers(customers);
+    }
+
+    public void sendProductsRequest() {
+        List<String> products = sendRequestToDBApplication(getBaseUrl() + "/database/products");
+        userData.setProducts(products);
+    }
+
+    protected List<String> sendRequestToDBApplication(String dbUri) {
+        HttpClient client = new DefaultHttpClient();
+        HttpGet get = new HttpGet(dbUri);
+        try {
+
+            if (userData.isHasAccessToken()) {
+                get.addHeader("Authorization", "Bearer " + userData.getAccessToken());
+            }
+
+            HttpResponse response = client.execute(get);
+            switch (response.getStatusLine().getStatusCode()) {
+                case 200: HttpEntity entity = response.getEntity();
+                    InputStream is = entity.getContent();
+                    try {
+                        return JsonSerialization.readValue(is, TypedList.class);
+                    } finally {
+                        is.close();
+                    }
+                case 401: facesContext.addMessage(null, new FacesMessage("Status: 401. Request not authenticated! You need to retrieve access token first."));
+                    break;
+                case 403: facesContext.addMessage(null, new FacesMessage("Status: 403. Access token has insufficient privileges"));
+                    break;
+                default: facesContext.addMessage(null, new FacesMessage("Status: " + response.getStatusLine() + ". Not able to retrieve data. See log for details"));
+                    logger.warn("Error occured. Status: " + response.getStatusLine());
+            }
+
+            return null;
+        } catch (IOException e) {
+            e.printStackTrace();
+            facesContext.addMessage(null, new FacesMessage("Unknown error. See log for details"));
+            return null;
+        }
+    }
+
+    public String getBaseUrl() {
+        KeycloakSecurityContext session = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
+        return AdapterUtils.getOriginForRestCalls(request.getRequestURL().toString(), session);
+    }
+
+}
diff --git a/examples/js-console/example-realm.json b/examples/js-console/example-realm.json
index 260e938..826fbee 100755
--- a/examples/js-console/example-realm.json
+++ b/examples/js-console/example-realm.json
@@ -1,64 +1,64 @@
-{
-    "realm": "example",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "user",
-            "enabled": true,
-            "email" : "sample-user@example",
-            "firstName": "Sample",
-            "lastName": "User",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "account": ["view-profile", "manage-account"]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "js-console",
-            "roles": ["user"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "js-console",
-            "enabled": true,
-            "publicClient": true,
-            "baseUrl": "/js-console",
-            "redirectUris": [
-                "/js-console/*"
-            ],
-            "webOrigins": []
-        }
-    ],
-    "clientScopeMappings": {
-        "account": [
-            {
-                "client": "js-console",
-                "roles": ["view-profile"]
-            }
-        ]
-    }
-}
+{
+    "realm": "example",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "user",
+            "enabled": true,
+            "email" : "sample-user@example",
+            "firstName": "Sample",
+            "lastName": "User",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": ["view-profile", "manage-account"]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "js-console",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "js-console",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "/js-console",
+            "redirectUris": [
+                "/js-console/*"
+            ],
+            "webOrigins": []
+        }
+    ],
+    "clientScopeMappings": {
+        "account": [
+            {
+                "client": "js-console",
+                "roles": ["view-profile"]
+            }
+        ]
+    }
+}
diff --git a/examples/js-console/pom.xml b/examples/js-console/pom.xml
index 02a2e32..7e32dbe 100755
--- a/examples/js-console/pom.xml
+++ b/examples/js-console/pom.xml
@@ -1,36 +1,36 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.keycloak.example.demo</groupId>
-    <artifactId>js-console</artifactId>
-    <packaging>war</packaging>
-    <name>JS Console</name>
-    <description/>
-
-    <build>
-        <finalName>js-console</finalName>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.as.plugins</groupId>
-                <artifactId>jboss-as-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.wildfly.plugins</groupId>
-                <artifactId>wildfly-maven-plugin</artifactId>
-                <configuration>
-                    <skip>false</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>js-console</artifactId>
+    <packaging>war</packaging>
+    <name>JS Console</name>
+    <description/>
+
+    <build>
+        <finalName>js-console</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/examples/multi-tenant/tenant1-realm.json b/examples/multi-tenant/tenant1-realm.json
index 9dcaa00..95c4afd 100644
--- a/examples/multi-tenant/tenant1-realm.json
+++ b/examples/multi-tenant/tenant1-realm.json
@@ -1,54 +1,54 @@
-{
-    "id": "tenant1",
-    "realm": "tenant1",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "user-tenant1",
-            "enabled": true,
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "user-tenant1" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "multi-tenant",
-            "roles": ["user"]
-        }
-
-    ],
-    "clients": [
-        {
-            "clientId": "multi-tenant",
-            "enabled": true,
-            "adminUrl": "/multitenant/tenant1",
-            "baseUrl": "/multitenant/tenant1",
-            "redirectUris": [
-                "/multitenant/tenant1/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "tenant1",
+    "realm": "tenant1",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "user-tenant1",
+            "enabled": true,
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant1" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "multi-tenant",
+            "roles": ["user"]
+        }
+
+    ],
+    "clients": [
+        {
+            "clientId": "multi-tenant",
+            "enabled": true,
+            "adminUrl": "/multitenant/tenant1",
+            "baseUrl": "/multitenant/tenant1",
+            "redirectUris": [
+                "/multitenant/tenant1/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/examples/multi-tenant/tenant2-realm.json b/examples/multi-tenant/tenant2-realm.json
index 643d550..1adec4b 100644
--- a/examples/multi-tenant/tenant2-realm.json
+++ b/examples/multi-tenant/tenant2-realm.json
@@ -1,55 +1,55 @@
-{
-    "id": "tenant2",
-    "realm": "tenant2",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "updateProfileOnInitialSocialLogin": false,
-    "privateKey": "MIICXQIBAAKBgQDA0oJjgPQJhnVhOo51KauQGfLLreMFu64OJdKXRnfvAQJQTuKNwc5JrR63l/byyW1B6FgclABF818TtLvMCAkn4EuFwQZCZhg3x3+lFGiB/IzC6UAt4Bi0JQrTbdh83/U97GIPegvaDqiqEiQESEkbCZWxM6sh/34hQaAhCaFpMwIDAQABAoGADwFSvEOQuh0IjWRtKZjwjOo4BrmlbRDJ3rf6x2LoemTttSouXzGxx/H87fSZdxNNuU9HbBHoY4ko4POzmZEWhS0gV6UjM7VArc4YjID6Hh2tfU9vCbuuKZrRs7RjxL70b51WxycKc49PQ4JiR3g04punrpq2UzToPrm66zI+ICECQQD2Jauo6cXXoxHR0QychQf4dityZwFXUoR/8oI/YFiu9XwcWgSMwrFKUdWWNKYmrIRNqCBzrGyeiGdaAjsw41T3AkEAyIpn+XL7bek/uLno5/7ULauf2dFI6MEaHJixQJD7S6Tfo/CGuDK93H4K0GAdjgR0LA0tCnB09yyPCd5NmAYKpQJBAO7+BH4s/PsyScr+vs/6GpMTqXuap6KxbBUO0YfXdEPr9mVQwboqDxmp+0esNua1+n+sDlZBw/TpW+/42p/NGmECQF0sOQyjyH+TfGCmN7j6I7ioYZeA7h/9/9TDeK8n7SmDC8kOanlQUfgMs5eG4JRoK1WANaoA/8cLc9XA7EoynGUCQQDx/Gjg6qyWheVujxjKufH1XkqDNiQHClDRM1ntChCmGq/RmpVmce+mYeOYZ9eofv7UJUCBdamllRlB+056Ld2h",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA0oJjgPQJhnVhOo51KauQGfLLreMFu64OJdKXRnfvAQJQTuKNwc5JrR63l/byyW1B6FgclABF818TtLvMCAkn4EuFwQZCZhg3x3+lFGiB/IzC6UAt4Bi0JQrTbdh83/U97GIPegvaDqiqEiQESEkbCZWxM6sh/34hQaAhCaFpMwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "user-tenant2",
-            "enabled": true,
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "user-tenant2" }
-            ],
-            "realmRoles": [ "user" ],
-            "clientRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "multi-tenant",
-            "roles": ["user"]
-        }
-
-    ],
-    "clients": [
-        {
-            "clientId": "multi-tenant",
-            "enabled": true,
-            "adminUrl": "/multitenant/tenant2",
-            "baseUrl": "/multitenant/tenant2",
-            "redirectUris": [
-                "/multitenant/tenant2/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "tenant2",
+    "realm": "tenant2",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "updateProfileOnInitialSocialLogin": false,
+    "privateKey": "MIICXQIBAAKBgQDA0oJjgPQJhnVhOo51KauQGfLLreMFu64OJdKXRnfvAQJQTuKNwc5JrR63l/byyW1B6FgclABF818TtLvMCAkn4EuFwQZCZhg3x3+lFGiB/IzC6UAt4Bi0JQrTbdh83/U97GIPegvaDqiqEiQESEkbCZWxM6sh/34hQaAhCaFpMwIDAQABAoGADwFSvEOQuh0IjWRtKZjwjOo4BrmlbRDJ3rf6x2LoemTttSouXzGxx/H87fSZdxNNuU9HbBHoY4ko4POzmZEWhS0gV6UjM7VArc4YjID6Hh2tfU9vCbuuKZrRs7RjxL70b51WxycKc49PQ4JiR3g04punrpq2UzToPrm66zI+ICECQQD2Jauo6cXXoxHR0QychQf4dityZwFXUoR/8oI/YFiu9XwcWgSMwrFKUdWWNKYmrIRNqCBzrGyeiGdaAjsw41T3AkEAyIpn+XL7bek/uLno5/7ULauf2dFI6MEaHJixQJD7S6Tfo/CGuDK93H4K0GAdjgR0LA0tCnB09yyPCd5NmAYKpQJBAO7+BH4s/PsyScr+vs/6GpMTqXuap6KxbBUO0YfXdEPr9mVQwboqDxmp+0esNua1+n+sDlZBw/TpW+/42p/NGmECQF0sOQyjyH+TfGCmN7j6I7ioYZeA7h/9/9TDeK8n7SmDC8kOanlQUfgMs5eG4JRoK1WANaoA/8cLc9XA7EoynGUCQQDx/Gjg6qyWheVujxjKufH1XkqDNiQHClDRM1ntChCmGq/RmpVmce+mYeOYZ9eofv7UJUCBdamllRlB+056Ld2h",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA0oJjgPQJhnVhOo51KauQGfLLreMFu64OJdKXRnfvAQJQTuKNwc5JrR63l/byyW1B6FgclABF818TtLvMCAkn4EuFwQZCZhg3x3+lFGiB/IzC6UAt4Bi0JQrTbdh83/U97GIPegvaDqiqEiQESEkbCZWxM6sh/34hQaAhCaFpMwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "user-tenant2",
+            "enabled": true,
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant2" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "multi-tenant",
+            "roles": ["user"]
+        }
+
+    ],
+    "clients": [
+        {
+            "clientId": "multi-tenant",
+            "enabled": true,
+            "adminUrl": "/multitenant/tenant2",
+            "baseUrl": "/multitenant/tenant2",
+            "redirectUris": [
+                "/multitenant/tenant2/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}

examples/pom.xml 98(+49 -49)

diff --git a/examples/pom.xml b/examples/pom.xml
index 4815c39..ac62ef5 100755
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -1,49 +1,49 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Examples</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-examples-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-war-plugin</artifactId>
-                <configuration>
-                    <failOnMissingWebXml>false</failOnMissingWebXml>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>admin-client</module>
-        <module>broker</module>
-        <module>cors</module>
-        <module>demo-template</module>
-        <module>providers</module>
-        <module>js-console</module>
-        <module>multi-tenant</module>
-        <module>basic-auth</module>
-        <module>fuse</module>
-        <module>kerberos</module>
-        <module>themes</module>
-        <module>saml</module>
-        <module>ldap</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-examples-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>admin-client</module>
+        <module>broker</module>
+        <module>cors</module>
+        <module>demo-template</module>
+        <module>providers</module>
+        <module>js-console</module>
+        <module>multi-tenant</module>
+        <module>basic-auth</module>
+        <module>fuse</module>
+        <module>kerberos</module>
+        <module>themes</module>
+        <module>saml</module>
+        <module>ldap</module>
+    </modules>
+</project>
diff --git a/examples/providers/event-listener-sysout/pom.xml b/examples/providers/event-listener-sysout/pom.xml
index 875396b..1ad8e15 100755
--- a/examples/providers/event-listener-sysout/pom.xml
+++ b/examples/providers/event-listener-sysout/pom.xml
@@ -1,34 +1,34 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-providers-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Event Listener System.out Example</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>event-listener-sysout-example</artifactId>
-    <packaging>jar</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>event-listener-sysout-example</finalName>
-    </build>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-providers-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Event Listener System.out Example</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>event-listener-sysout-example</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>event-listener-sysout-example</finalName>
+    </build>
+</project>
diff --git a/examples/providers/event-store-mem/pom.xml b/examples/providers/event-store-mem/pom.xml
index eef62a1..4eaeb5b 100755
--- a/examples/providers/event-store-mem/pom.xml
+++ b/examples/providers/event-store-mem/pom.xml
@@ -1,34 +1,34 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-providers-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Event Store In-Mem Example</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>event-store-mem-example</artifactId>
-    <packaging>jar</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>event-store-mem-example</finalName>
-    </build>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-providers-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Event Store In-Mem Example</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>event-store-mem-example</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>event-store-mem-example</finalName>
+    </build>
+</project>
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
index 5c585f3..e9393ef 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationFactory.java
@@ -1,135 +1,135 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakSessionTask;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserFederationSyncResult;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class BasePropertiesFederationFactory implements UserFederationProviderFactory {
-    static final Set<String> configOptions = new HashSet<String>();
-    protected ConcurrentHashMap<String, Properties> files = new ConcurrentHashMap<String, Properties>();
-
-    static {
-        configOptions.add("path");
-    }
-
-    @Override
-    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        // first get the path to our properties file from the stored configuration of this provider instance.
-        String path = model.getConfig().get("path");
-        if (path == null) {
-            throw new IllegalStateException("Path attribute not configured for provider");
-        }
-        // see if we already loaded the config file
-        Properties props = files.get(path);
-        if (props != null) return createProvider(session, model, props);
-
-
-        props = new Properties();
-        InputStream is = getPropertiesFileStream(path);
-        try {
-            props.load(is);
-            is.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        // remember the properties file for next time
-        files.put(path, props);
-        return createProvider(session, model, props);
-    }
-
-    protected abstract InputStream getPropertiesFileStream(String path);
-
-    protected abstract BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props);
-
-    /**
-     * List the configuration options to render and display in the admin console's generic management page for this
-     * plugin
-     *
-     * @return
-     */
-    @Override
-    public Set<String> getConfigurationOptions() {
-        return configOptions;
-    }
-
-    @Override
-    public UserFederationProvider create(KeycloakSession session) {
-        return null;
-    }
-
-    /**
-     * You can import additional plugin configuration from keycloak-server.json here.
-     *
-     * @param config
-     */
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
-        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
-
-        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
-            @Override
-            public void run(KeycloakSession session) {
-                RealmModel realm = session.realms().getRealm(realmId);
-                BasePropertiesFederationProvider federationProvider = (BasePropertiesFederationProvider)getInstance(session, model);
-                Set<String> allUsernames = federationProvider.getProperties().stringPropertyNames();
-                UserProvider localProvider = session.userStorage();
-                for (String username : allUsernames) {
-                    UserModel localUser = localProvider.getUserByUsername(username, realm);
-
-                    if (localUser == null) {
-                        // New user, let's import him
-                        UserModel imported = federationProvider.getUserByUsername(realm, username);
-                        if (imported != null) {
-                            syncResult.increaseAdded();
-                        }
-                    }
-                }
-            }
-
-        });
-
-        return syncResult;
-    }
-
-    @Override
-    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
-        return syncAllUsers(sessionFactory, realmId, model);
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakSessionTask;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderFactory;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserFederationSyncResult;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class BasePropertiesFederationFactory implements UserFederationProviderFactory {
+    static final Set<String> configOptions = new HashSet<String>();
+    protected ConcurrentHashMap<String, Properties> files = new ConcurrentHashMap<String, Properties>();
+
+    static {
+        configOptions.add("path");
+    }
+
+    @Override
+    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
+        // first get the path to our properties file from the stored configuration of this provider instance.
+        String path = model.getConfig().get("path");
+        if (path == null) {
+            throw new IllegalStateException("Path attribute not configured for provider");
+        }
+        // see if we already loaded the config file
+        Properties props = files.get(path);
+        if (props != null) return createProvider(session, model, props);
+
+
+        props = new Properties();
+        InputStream is = getPropertiesFileStream(path);
+        try {
+            props.load(is);
+            is.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        // remember the properties file for next time
+        files.put(path, props);
+        return createProvider(session, model, props);
+    }
+
+    protected abstract InputStream getPropertiesFileStream(String path);
+
+    protected abstract BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props);
+
+    /**
+     * List the configuration options to render and display in the admin console's generic management page for this
+     * plugin
+     *
+     * @return
+     */
+    @Override
+    public Set<String> getConfigurationOptions() {
+        return configOptions;
+    }
+
+    @Override
+    public UserFederationProvider create(KeycloakSession session) {
+        return null;
+    }
+
+    /**
+     * You can import additional plugin configuration from keycloak-server.json here.
+     *
+     * @param config
+     */
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
+        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
+
+        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+
+            @Override
+            public void run(KeycloakSession session) {
+                RealmModel realm = session.realms().getRealm(realmId);
+                BasePropertiesFederationProvider federationProvider = (BasePropertiesFederationProvider)getInstance(session, model);
+                Set<String> allUsernames = federationProvider.getProperties().stringPropertyNames();
+                UserProvider localProvider = session.userStorage();
+                for (String username : allUsernames) {
+                    UserModel localUser = localProvider.getUserByUsername(username, realm);
+
+                    if (localUser == null) {
+                        // New user, let's import him
+                        UserModel imported = federationProvider.getUserByUsername(realm, username);
+                        if (imported != null) {
+                            syncResult.increaseAdded();
+                        }
+                    }
+                }
+            }
+
+        });
+
+        return syncResult;
+    }
+
+    @Override
+    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
+        return syncAllUsers(sessionFactory, realmId, model);
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationProvider.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationProvider.java
index 9c4d01f..f622895 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationProvider.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/BasePropertiesFederationProvider.java
@@ -1,173 +1,173 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class BasePropertiesFederationProvider implements UserFederationProvider {
-    protected static final Set<String> supportedCredentialTypes = new HashSet<String>();
-    protected KeycloakSession session;
-    protected Properties properties;
-    protected UserFederationProviderModel model;
-
-    public BasePropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
-        this.session = session;
-        this.model = model;
-        this.properties = properties;
-    }
-
-    static
-    {
-        supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
-    }
-
-
-    public KeycloakSession getSession() {
-        return session;
-    }
-
-    public Properties getProperties() {
-        return properties;
-    }
-
-    public UserFederationProviderModel getModel() {
-        return model;
-    }
-
-    @Override
-    public UserModel getUserByUsername(RealmModel realm, String username) {
-        String password = properties.getProperty(username);
-        if (password != null) {
-            UserModel userModel = session.userStorage().addUser(realm, username);
-            userModel.setEnabled(true);
-            userModel.setFederationLink(model.getId());
-            return userModel;
-        }
-        return null;
-    }
-
-    @Override
-    public UserModel getUserByEmail(RealmModel realm, String email) {
-        return null;
-    }
-
-    /**
-     * We only search for Usernames as that is all that is stored in the properties file.  Not that if the user
-     * does exist in the properties file, we only import it if the user hasn't been imported already.
-     *
-     * @param attributes
-     * @param realm
-     * @param maxResults
-     * @return
-     */
-    @Override
-    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
-        String username = attributes.get(USERNAME);
-        if (username != null) {
-            // make sure user isn't already in storage
-            if (session.userStorage().getUserByUsername(username, realm) == null) {
-                // user is not already imported, so let's import it until local storage.
-                UserModel user = getUserByUsername(realm, username);
-                if (user != null) {
-                    List<UserModel> list = new ArrayList<UserModel>(1);
-                    list.add(user);
-                    return list;
-                }
-            }
-        }
-        return Collections.emptyList();
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-       // complete  We don't care about the realm being removed
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        // complete we dont'care if a role is removed
-
-    }
-
-    /**
-     * See if the user is still in the properties file
-     *
-     * @param local
-     * @return
-     */
-    @Override
-    public boolean isValid(RealmModel realm, UserModel local) {
-        return properties.containsKey(local.getUsername());
-    }
-
-    /**
-     * hardcoded to only return PASSWORD
-     *
-     * @param user
-     * @return
-     */
-    @Override
-    public Set<String> getSupportedCredentialTypes(UserModel user) {
-        return supportedCredentialTypes;
-    }
-
-    @Override
-    public Set<String> getSupportedCredentialTypes() {
-        return supportedCredentialTypes;
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        for (UserCredentialModel cred : input) {
-            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                String password = properties.getProperty(user.getUsername());
-                if (password == null) return false;
-                return password.equals(cred.getValue());
-            } else {
-                return false; // invalid cred type
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        for (UserCredentialModel cred : input) {
-            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                String password = properties.getProperty(user.getUsername());
-                if (password == null) return false;
-                return password.equals(cred.getValue());
-            } else {
-                return false; // invalid cred type
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
-        return CredentialValidationOutput.failed();
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class BasePropertiesFederationProvider implements UserFederationProvider {
+    protected static final Set<String> supportedCredentialTypes = new HashSet<String>();
+    protected KeycloakSession session;
+    protected Properties properties;
+    protected UserFederationProviderModel model;
+
+    public BasePropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
+        this.session = session;
+        this.model = model;
+        this.properties = properties;
+    }
+
+    static
+    {
+        supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
+    }
+
+
+    public KeycloakSession getSession() {
+        return session;
+    }
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public UserFederationProviderModel getModel() {
+        return model;
+    }
+
+    @Override
+    public UserModel getUserByUsername(RealmModel realm, String username) {
+        String password = properties.getProperty(username);
+        if (password != null) {
+            UserModel userModel = session.userStorage().addUser(realm, username);
+            userModel.setEnabled(true);
+            userModel.setFederationLink(model.getId());
+            return userModel;
+        }
+        return null;
+    }
+
+    @Override
+    public UserModel getUserByEmail(RealmModel realm, String email) {
+        return null;
+    }
+
+    /**
+     * We only search for Usernames as that is all that is stored in the properties file.  Not that if the user
+     * does exist in the properties file, we only import it if the user hasn't been imported already.
+     *
+     * @param attributes
+     * @param realm
+     * @param maxResults
+     * @return
+     */
+    @Override
+    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
+        String username = attributes.get(USERNAME);
+        if (username != null) {
+            // make sure user isn't already in storage
+            if (session.userStorage().getUserByUsername(username, realm) == null) {
+                // user is not already imported, so let's import it until local storage.
+                UserModel user = getUserByUsername(realm, username);
+                if (user != null) {
+                    List<UserModel> list = new ArrayList<UserModel>(1);
+                    list.add(user);
+                    return list;
+                }
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+       // complete  We don't care about the realm being removed
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        // complete we dont'care if a role is removed
+
+    }
+
+    /**
+     * See if the user is still in the properties file
+     *
+     * @param local
+     * @return
+     */
+    @Override
+    public boolean isValid(RealmModel realm, UserModel local) {
+        return properties.containsKey(local.getUsername());
+    }
+
+    /**
+     * hardcoded to only return PASSWORD
+     *
+     * @param user
+     * @return
+     */
+    @Override
+    public Set<String> getSupportedCredentialTypes(UserModel user) {
+        return supportedCredentialTypes;
+    }
+
+    @Override
+    public Set<String> getSupportedCredentialTypes() {
+        return supportedCredentialTypes;
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        for (UserCredentialModel cred : input) {
+            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+                String password = properties.getProperty(user.getUsername());
+                if (password == null) return false;
+                return password.equals(cred.getValue());
+            } else {
+                return false; // invalid cred type
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        for (UserCredentialModel cred : input) {
+            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+                String password = properties.getProperty(user.getUsername());
+                if (password == null) return false;
+                return password.equals(cred.getValue());
+            } else {
+                return false; // invalid cred type
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
+        return CredentialValidationOutput.failed();
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationFactory.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationFactory.java
index 49ad517..39bb372 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationFactory.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationFactory.java
@@ -1,37 +1,37 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.UserFederationProviderModel;
-
-import java.io.InputStream;
-import java.util.Properties;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
-
-    public static final String PROVIDER_NAME = "classpath-properties";
-
-    @Override
-    protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
-        return new ClasspathPropertiesFederationProvider(session, model, props);
-    }
-
-    protected InputStream getPropertiesFileStream(String path) {
-        InputStream is = getClass().getClassLoader().getResourceAsStream(path);
-        if (is == null) {
-            throw new IllegalStateException("Path not found for properties file");
-
-        }
-        return is;
-    }
-
-
-
-    @Override
-    public String getId() {
-        return PROVIDER_NAME;
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.UserFederationProviderModel;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
+
+    public static final String PROVIDER_NAME = "classpath-properties";
+
+    @Override
+    protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
+        return new ClasspathPropertiesFederationProvider(session, model, props);
+    }
+
+    protected InputStream getPropertiesFileStream(String path) {
+        InputStream is = getClass().getClassLoader().getResourceAsStream(path);
+        if (is == null) {
+            throw new IllegalStateException("Path not found for properties file");
+
+        }
+        return is;
+    }
+
+
+
+    @Override
+    public String getId() {
+        return PROVIDER_NAME;
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationProvider.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationProvider.java
index 781331f..164cf79 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationProvider.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ClasspathPropertiesFederationProvider.java
@@ -1,66 +1,66 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-
-import java.util.Properties;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
-
-    public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
-        super(session, model, properties);
-    }
-
-    /**
-     * Keycloak will call this method if it finds an imported UserModel.  Here we proxy the UserModel with
-     * a Readonly proxy which will barf if password is updated.
-     *
-     * @param local
-     * @return
-     */
-    @Override
-    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
-        if (isValid(realm, local)) {
-            return new ReadonlyUserModelProxy(local);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * The properties file is readonly so don't suppport registration.
-     *
-     * @return
-     */
-    @Override
-    public boolean synchronizeRegistrations() {
-        return false;
-    }
-
-    /**
-     * The properties file is readonly so don't suppport registration.
-     *
-     * @return
-     */
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        throw new IllegalStateException("Registration not supported");
-    }
-
-    /**
-     * The properties file is readonly so don't removing a user
-     *
-     * @return
-     */
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        throw new IllegalStateException("Remove not supported");
-    }
-
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
+
+    public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
+        super(session, model, properties);
+    }
+
+    /**
+     * Keycloak will call this method if it finds an imported UserModel.  Here we proxy the UserModel with
+     * a Readonly proxy which will barf if password is updated.
+     *
+     * @param local
+     * @return
+     */
+    @Override
+    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
+        if (isValid(realm, local)) {
+            return new ReadonlyUserModelProxy(local);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * The properties file is readonly so don't suppport registration.
+     *
+     * @return
+     */
+    @Override
+    public boolean synchronizeRegistrations() {
+        return false;
+    }
+
+    /**
+     * The properties file is readonly so don't suppport registration.
+     *
+     * @return
+     */
+    @Override
+    public UserModel register(RealmModel realm, UserModel user) {
+        throw new IllegalStateException("Registration not supported");
+    }
+
+    /**
+     * The properties file is readonly so don't removing a user
+     *
+     * @return
+     */
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        throw new IllegalStateException("Remove not supported");
+    }
+
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationFactory.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationFactory.java
index 2f89575..588dca2 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationFactory.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationFactory.java
@@ -1,42 +1,42 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.UserFederationProviderModel;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Properties;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
-
-    public static final String PROVIDER_NAME = "file-properties";
-
-    @Override
-    protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
-        return new FilePropertiesFederationProvider(session, props, model);
-    }
-    protected InputStream getPropertiesFileStream(String path) {
-        try {
-            return new FileInputStream(path);
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    /**
-     * Name of the provider.  This will show up under the "Add Provider" select box on the Federation page in the
-     * admin console
-     *
-     * @return
-     */
-    @Override
-    public String getId() {
-        return PROVIDER_NAME;
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.UserFederationProviderModel;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
+
+    public static final String PROVIDER_NAME = "file-properties";
+
+    @Override
+    protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
+        return new FilePropertiesFederationProvider(session, props, model);
+    }
+    protected InputStream getPropertiesFileStream(String path) {
+        try {
+            return new FileInputStream(path);
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    /**
+     * Name of the provider.  This will show up under the "Add Provider" select box on the Federation page in the
+     * admin console
+     *
+     * @return
+     */
+    @Override
+    public String getId() {
+        return PROVIDER_NAME;
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationProvider.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationProvider.java
index 0b6941f..80f9d8d 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationProvider.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/FilePropertiesFederationProvider.java
@@ -1,86 +1,86 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class FilePropertiesFederationProvider extends BasePropertiesFederationProvider {
-
-    public FilePropertiesFederationProvider(KeycloakSession session, Properties properties, UserFederationProviderModel model) {
-        super(session, model, properties);
-    }
-
-    /**
-     * Keycloak will call this method if it finds an imported UserModel.  Here we proxy the UserModel with
-     * a Writable proxy which will synchronize updates to username and password back to the properties file
-     *
-     * @param local
-     * @return
-     */
-    @Override
-    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
-        if (isValid(realm, local)) {
-            return new WritableUserModelProxy(local, this);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Adding new users is supported
-     *
-     * @return
-     */
-    @Override
-    public boolean synchronizeRegistrations() {
-        return true;
-    }
-
-    public void save() {
-        String path = getModel().getConfig().get("path");
-        try {
-            FileOutputStream fos = new FileOutputStream(path);
-            properties.store(fos, "");
-            fos.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Update the properties file with the new user.
-     *
-     * @param realm
-     * @param user
-     * @return
-     */
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        synchronized (properties) {
-            properties.setProperty(user.getUsername(), "");
-            save();
-        }
-        return validateAndProxy(realm, user);
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        synchronized (properties) {
-            if (properties.remove(user.getUsername()) == null) return false;
-            save();
-            return true;
-        }
-    }
-
-
-
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class FilePropertiesFederationProvider extends BasePropertiesFederationProvider {
+
+    public FilePropertiesFederationProvider(KeycloakSession session, Properties properties, UserFederationProviderModel model) {
+        super(session, model, properties);
+    }
+
+    /**
+     * Keycloak will call this method if it finds an imported UserModel.  Here we proxy the UserModel with
+     * a Writable proxy which will synchronize updates to username and password back to the properties file
+     *
+     * @param local
+     * @return
+     */
+    @Override
+    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
+        if (isValid(realm, local)) {
+            return new WritableUserModelProxy(local, this);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Adding new users is supported
+     *
+     * @return
+     */
+    @Override
+    public boolean synchronizeRegistrations() {
+        return true;
+    }
+
+    public void save() {
+        String path = getModel().getConfig().get("path");
+        try {
+            FileOutputStream fos = new FileOutputStream(path);
+            properties.store(fos, "");
+            fos.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Update the properties file with the new user.
+     *
+     * @param realm
+     * @param user
+     * @return
+     */
+    @Override
+    public UserModel register(RealmModel realm, UserModel user) {
+        synchronized (properties) {
+            properties.setProperty(user.getUsername(), "");
+            save();
+        }
+        return validateAndProxy(realm, user);
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        synchronized (properties) {
+            if (properties.remove(user.getUsername()) == null) return false;
+            save();
+            return true;
+        }
+    }
+
+
+
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ReadonlyUserModelProxy.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ReadonlyUserModelProxy.java
index e63a9e9..30b86a4 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ReadonlyUserModelProxy.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/ReadonlyUserModelProxy.java
@@ -1,40 +1,40 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * Readonly proxy for a UserModel that prevents passwords from being updated.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ReadonlyUserModelProxy extends UserModelDelegate {
-
-    public ReadonlyUserModelProxy(UserModel delegate) {
-        super(delegate);
-    }
-
-    @Override
-    public void setUsername(String username) {
-        throw new IllegalStateException("Username is readonly");
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel cred) {
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            throw new IllegalStateException("Passwords are readonly");
-        }
-        super.updateCredentialDirectly(cred);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            throw new IllegalStateException("Passwords are readonly");
-        }
-        super.updateCredential(cred);
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.UserModelDelegate;
+
+/**
+ * Readonly proxy for a UserModel that prevents passwords from being updated.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ReadonlyUserModelProxy extends UserModelDelegate {
+
+    public ReadonlyUserModelProxy(UserModel delegate) {
+        super(delegate);
+    }
+
+    @Override
+    public void setUsername(String username) {
+        throw new IllegalStateException("Username is readonly");
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel cred) {
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            throw new IllegalStateException("Passwords are readonly");
+        }
+        super.updateCredentialDirectly(cred);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            throw new IllegalStateException("Passwords are readonly");
+        }
+        super.updateCredential(cred);
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/WritableUserModelProxy.java b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/WritableUserModelProxy.java
index e47d5f2..dd90ab4 100755
--- a/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/WritableUserModelProxy.java
+++ b/examples/providers/federation-provider/src/main/java/org/keycloak/examples/federation/properties/WritableUserModelProxy.java
@@ -1,72 +1,72 @@
-package org.keycloak.examples.federation.properties;
-
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-import java.util.Properties;
-
-/**
- * Proxy that will synchronize password updates to the properties file.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class WritableUserModelProxy extends UserModelDelegate {
-    protected FilePropertiesFederationProvider provider;
-
-    public WritableUserModelProxy(UserModel delegate, FilePropertiesFederationProvider provider) {
-        super(delegate);
-        this.provider = provider;
-    }
-
-
-    /**
-     * Updates the properties file if the username changes.  If you have a more complex user storage, you can
-     * override other methods on UserModel to synchronize updates back to your external storage.
-     *
-     * @param username
-     */
-    @Override
-    public void setUsername(String username) {
-        if (delegate.getUsername().equals(username)) return;
-        delegate.setUsername(username);
-        Properties properties = provider.getProperties();
-        synchronized (properties) {
-            if (properties.containsKey(username)) {
-                throw new IllegalStateException("Can't change username to existing user");
-            }
-            String password = (String) properties.remove(username);
-            if (password == null) {
-                throw new IllegalStateException("User doesn't exist");
-            }
-            properties.setProperty(username, password);
-            provider.save();
-        }
-
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel cred) {
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            throw new IllegalStateException("Shouldn't be using this method");
-        }
-        super.updateCredentialDirectly(cred);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            synchronized (provider.getProperties()) {
-                if (!provider.getProperties().containsKey(delegate.getUsername())) {
-                    throw new IllegalStateException("no user of that in properties file");
-                }
-                provider.getProperties().setProperty(delegate.getUsername(), cred.getValue());
-                provider.save();
-            }
-        } else {
-            super.updateCredential(cred);
-        }
-    }
-}
+package org.keycloak.examples.federation.properties;
+
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.UserModelDelegate;
+
+import java.util.Properties;
+
+/**
+ * Proxy that will synchronize password updates to the properties file.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class WritableUserModelProxy extends UserModelDelegate {
+    protected FilePropertiesFederationProvider provider;
+
+    public WritableUserModelProxy(UserModel delegate, FilePropertiesFederationProvider provider) {
+        super(delegate);
+        this.provider = provider;
+    }
+
+
+    /**
+     * Updates the properties file if the username changes.  If you have a more complex user storage, you can
+     * override other methods on UserModel to synchronize updates back to your external storage.
+     *
+     * @param username
+     */
+    @Override
+    public void setUsername(String username) {
+        if (delegate.getUsername().equals(username)) return;
+        delegate.setUsername(username);
+        Properties properties = provider.getProperties();
+        synchronized (properties) {
+            if (properties.containsKey(username)) {
+                throw new IllegalStateException("Can't change username to existing user");
+            }
+            String password = (String) properties.remove(username);
+            if (password == null) {
+                throw new IllegalStateException("User doesn't exist");
+            }
+            properties.setProperty(username, password);
+            provider.save();
+        }
+
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel cred) {
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            throw new IllegalStateException("Shouldn't be using this method");
+        }
+        super.updateCredentialDirectly(cred);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            synchronized (provider.getProperties()) {
+                if (!provider.getProperties().containsKey(delegate.getUsername())) {
+                    throw new IllegalStateException("no user of that in properties file");
+                }
+                provider.getProperties().setProperty(delegate.getUsername(), cred.getValue());
+                provider.save();
+            }
+        } else {
+            super.updateCredential(cred);
+        }
+    }
+}
diff --git a/examples/providers/federation-provider/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory b/examples/providers/federation-provider/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory
index fbbc583..51b2921 100755
--- a/examples/providers/federation-provider/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory
+++ b/examples/providers/federation-provider/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory
@@ -1,2 +1,2 @@
-org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
+org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
 org.keycloak.examples.federation.properties.FilePropertiesFederationFactory
\ No newline at end of file
diff --git a/examples/providers/federation-provider/src/main/resources/test2-users.properties b/examples/providers/federation-provider/src/main/resources/test2-users.properties
index 6623bcc..7ff83ba 100755
--- a/examples/providers/federation-provider/src/main/resources/test2-users.properties
+++ b/examples/providers/federation-provider/src/main/resources/test2-users.properties
@@ -1,3 +1,3 @@
-#
-#Sun Aug 03 10:52:57 EDT 2014
-belichick=superbowl
+#
+#Sun Aug 03 10:52:57 EDT 2014
+belichick=superbowl
diff --git a/examples/providers/pom.xml b/examples/providers/pom.xml
index 65d719a..681237c 100755
--- a/examples/providers/pom.xml
+++ b/examples/providers/pom.xml
@@ -1,21 +1,21 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Provider Examples</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-examples-providers-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>event-listener-sysout</module>
-        <module>event-store-mem</module>
-        <module>federation-provider</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Provider Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-examples-providers-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>event-listener-sysout</module>
+        <module>event-store-mem</module>
+        <module>federation-provider</module>
+    </modules>
+</project>

examples/saml/pom.xml 68(+34 -34)

diff --git a/examples/saml/pom.xml b/examples/saml/pom.xml
index 61ac3fb..63a54e7 100755
--- a/examples/saml/pom.xml
+++ b/examples/saml/pom.xml
@@ -1,34 +1,34 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Provider Examples</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-examples-saml-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>post-basic</module>
-        <module>post-with-signature</module>
-        <module>post-with-encryption</module>
-        <module>redirect-basic</module>
-        <module>redirect-with-signature</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Provider Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-examples-saml-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>post-basic</module>
+        <module>post-with-signature</module>
+        <module>post-with-encryption</module>
+        <module>redirect-basic</module>
+        <module>redirect-with-signature</module>
+    </modules>
+</project>
diff --git a/examples/saml/testsaml.json b/examples/saml/testsaml.json
index 4d9e7d4..69e28fd 100755
--- a/examples/saml/testsaml.json
+++ b/examples/saml/testsaml.json
@@ -1,125 +1,125 @@
-{
-    "id": "saml-demo",
-    "realm": "saml-demo",
-    "enabled": true,
-    "sslRequired": "external",
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "user" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "bburke",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": ["manager"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "http://localhost:8080/sales-post/",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "protocol": "saml",
-            "baseUrl": "http://localhost:8080/sales-post/",
-            "adminUrl": "http://localhost:8080/sales-post/",
-            "redirectUris": [
-                "http://localhost:8080/sales-post/*"
-            ],
-            "attributes": {
-                "saml.authnstatement": "true"
-            }
-        },
-        {
-            "clientId": "http://localhost:8080/sales-post-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8080/sales-post-sig/",
-            "adminUrl": "http://localhost:8080/sales-post-sig/",
-            "redirectUris": [
-                "http://localhost:8080/sales-post-sig/*"
-            ],
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "clientId": "http://localhost:8080/sales-post-enc/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8080/sales-post-enc/",
-            "adminUrl": "http://localhost:8080/sales-post-enc/",
-            "redirectUris": [
-                "http://localhost:8080/sales-post-enc/*"
-            ],
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA512",
-                "saml.client.signature": "true",
-                "saml.encrypt": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g==",
-                "saml.encryption.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
-                "saml.encryption.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
-            }
-        },
-        {
-            "clientId": "http://localhost:8080/employee/",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "protocol": "saml",
-            "baseUrl": "http://localhost:8080/employee/",
-            "adminUrl": "http://localhost:8080/employee/",
-            "redirectUris": [
-                "http://localhost:8080/employee/*"
-            ],
-            "attributes": {
-                "saml.authnstatement": "true"
-            }
-        },
-        {
-            "clientId": "http://localhost:8080/employee-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8080/employee-sig/",
-            "adminUrl": "http://localhost:8080/employee-sig/",
-            "redirectUris": [
-                "http://localhost:8080/employee-sig/*"
-            ],
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.client.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA1",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
-                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            }
-        ]
-    }
-}
+{
+    "id": "saml-demo",
+    "realm": "saml-demo",
+    "enabled": true,
+    "sslRequired": "external",
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "user" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "bburke",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": ["manager"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "http://localhost:8080/sales-post/",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "protocol": "saml",
+            "baseUrl": "http://localhost:8080/sales-post/",
+            "adminUrl": "http://localhost:8080/sales-post/",
+            "redirectUris": [
+                "http://localhost:8080/sales-post/*"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true"
+            }
+        },
+        {
+            "clientId": "http://localhost:8080/sales-post-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/sales-post-sig/",
+            "adminUrl": "http://localhost:8080/sales-post-sig/",
+            "redirectUris": [
+                "http://localhost:8080/sales-post-sig/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "clientId": "http://localhost:8080/sales-post-enc/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/sales-post-enc/",
+            "adminUrl": "http://localhost:8080/sales-post-enc/",
+            "redirectUris": [
+                "http://localhost:8080/sales-post-enc/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA512",
+                "saml.client.signature": "true",
+                "saml.encrypt": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g==",
+                "saml.encryption.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
+                "saml.encryption.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
+            }
+        },
+        {
+            "clientId": "http://localhost:8080/employee/",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "protocol": "saml",
+            "baseUrl": "http://localhost:8080/employee/",
+            "adminUrl": "http://localhost:8080/employee/",
+            "redirectUris": [
+                "http://localhost:8080/employee/*"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true"
+            }
+        },
+        {
+            "clientId": "http://localhost:8080/employee-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/employee-sig/",
+            "adminUrl": "http://localhost:8080/employee-sig/",
+            "redirectUris": [
+                "http://localhost:8080/employee-sig/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA1",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
+                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            }
+        ]
+    }
+}
diff --git a/examples/themes/pom.xml b/examples/themes/pom.xml
index 2f4982a..ee80a9b 100755
--- a/examples/themes/pom.xml
+++ b/examples/themes/pom.xml
@@ -1,19 +1,19 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-examples-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <name>Themes Examples</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-example-themes</artifactId>
-    <packaging>jar</packaging>
-
-    <build>
-        <finalName>keycloak-example-themes</finalName>
-    </build>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <name>Themes Examples</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-example-themes</artifactId>
+    <packaging>jar</packaging>
+
+    <build>
+        <finalName>keycloak-example-themes</finalName>
+    </build>
+</project>
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
index b5598e9..597f9fe 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
@@ -1,452 +1,452 @@
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
-import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.QueryParameter;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionTask;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.mappers.UserFederationMapper;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserFederationSyncResult;
-import org.keycloak.models.UserModel;
-import org.keycloak.constants.KerberosConstants;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class LDAPFederationProvider implements UserFederationProvider {
-    private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class);
-
-    protected LDAPFederationProviderFactory factory;
-    protected KeycloakSession session;
-    protected UserFederationProviderModel model;
-    protected LDAPIdentityStore ldapIdentityStore;
-    protected EditMode editMode;
-    protected LDAPProviderKerberosConfig kerberosConfig;
-
-    protected final Set<String> supportedCredentialTypes = new HashSet<>();
-
-    public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) {
-        this.factory = factory;
-        this.session = session;
-        this.model = model;
-        this.ldapIdentityStore = ldapIdentityStore;
-        this.kerberosConfig = new LDAPProviderKerberosConfig(model);
-        this.editMode = ldapIdentityStore.getConfig().getEditMode();
-
-        supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
-        if (kerberosConfig.isAllowKerberosAuthentication()) {
-            supportedCredentialTypes.add(UserCredentialModel.KERBEROS);
-        }
-    }
-
-    public KeycloakSession getSession() {
-        return session;
-    }
-
-    public UserFederationProviderModel getModel() {
-        return model;
-    }
-
-    public LDAPIdentityStore getLdapIdentityStore() {
-        return this.ldapIdentityStore;
-    }
-
-    public EditMode getEditMode() {
-        return editMode;
-    }
-
-    @Override
-    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
-        LDAPObject ldapObject = loadAndValidateUser(realm, local);
-        if (ldapObject == null) {
-            return null;
-        }
-
-        return proxy(realm, local, ldapObject);
-    }
-
-    protected UserModel proxy(RealmModel realm, UserModel local, LDAPObject ldapObject) {
-        UserModel proxied = local;
-        switch (editMode) {
-            case READ_ONLY:
-                proxied = new ReadonlyLDAPUserModelDelegate(local, this);
-                break;
-            case WRITABLE:
-                proxied = new WritableLDAPUserModelDelegate(local, this, ldapObject);
-                break;
-            case UNSYNCED:
-                proxied = new UnsyncedLDAPUserModelDelegate(local, this);
-        }
-
-        Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
-        for (UserFederationMapperModel mapperModel : federationMappers) {
-            LDAPFederationMapper ldapMapper = getMapper(mapperModel);
-            proxied = ldapMapper.proxy(mapperModel, this, ldapObject, proxied, realm);
-        }
-
-        return proxied;
-    }
-
-    @Override
-    public Set<String> getSupportedCredentialTypes(UserModel local) {
-        Set<String> supportedCredentialTypes = new HashSet<String>(this.supportedCredentialTypes);
-        if (editMode == EditMode.UNSYNCED ) {
-            for (UserCredentialValueModel cred : local.getCredentialsDirectly()) {
-                if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                    // User has changed password in KC local database. Use KC password instead of LDAP password
-                    supportedCredentialTypes.remove(UserCredentialModel.PASSWORD);
-                }
-            }
-        }
-        return supportedCredentialTypes;
-    }
-
-    @Override
-    public Set<String> getSupportedCredentialTypes() {
-        return new HashSet<String>(this.supportedCredentialTypes);
-    }
-
-    @Override
-    public boolean synchronizeRegistrations() {
-        return "true".equalsIgnoreCase(model.getConfig().get(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE;
-    }
-
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
-        if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
-
-        LDAPObject ldapObject = LDAPUtils.addUserToLDAP(this, realm, user);
-        user.setSingleAttribute(LDAPConstants.LDAP_ID, ldapObject.getUuid());
-        user.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapObject.getDn().toString());
-
-        return proxy(realm, user, ldapObject);
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) {
-            logger.warnf("User '%s' can't be deleted in LDAP as editMode is '%s'", user.getUsername(), editMode.toString());
-            return false;
-        }
-
-        LDAPObject ldapObject = loadAndValidateUser(realm, user);
-        if (ldapObject == null) {
-            logger.warnf("User '%s' can't be deleted from LDAP as it doesn't exist here", user.getUsername());
-            return false;
-        }
-
-        ldapIdentityStore.remove(ldapObject);
-        return true;
-    }
-
-    @Override
-    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
-        List<UserModel> searchResults =new LinkedList<UserModel>();
-
-        List<LDAPObject> ldapUsers = searchLDAP(realm, attributes, maxResults);
-        for (LDAPObject ldapUser : ldapUsers) {
-            String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
-            if (session.userStorage().getUserByUsername(ldapUsername, realm) == null) {
-                UserModel imported = importUserFromLDAP(session, realm, ldapUser);
-                searchResults.add(imported);
-            }
-        }
-
-        return searchResults;
-    }
-
-    protected List<LDAPObject> searchLDAP(RealmModel realm, Map<String, String> attributes, int maxResults) {
-
-        List<LDAPObject> results = new ArrayList<LDAPObject>();
-        if (attributes.containsKey(USERNAME)) {
-            LDAPObject user = loadLDAPUserByUsername(realm, attributes.get(USERNAME));
-            if (user != null) {
-                results.add(user);
-            }
-        }
-
-        if (attributes.containsKey(EMAIL)) {
-            LDAPObject user = queryByEmail(realm, attributes.get(EMAIL));
-            if (user != null) {
-                results.add(user);
-            }
-        }
-
-        if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
-            LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
-            LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
-            // Mapper should replace parameter with correct LDAP mapped attributes
-            if (attributes.containsKey(FIRST_NAME)) {
-                ldapQuery.where(conditionsBuilder.equal(new QueryParameter(FIRST_NAME), attributes.get(FIRST_NAME)));
-            }
-            if (attributes.containsKey(LAST_NAME)) {
-                ldapQuery.where(conditionsBuilder.equal(new QueryParameter(LAST_NAME), attributes.get(LAST_NAME)));
-            }
-
-            List<LDAPObject> ldapObjects = ldapQuery.getResultList();
-            results.addAll(ldapObjects);
-        }
-
-        return results;
-    }
-
-    /**
-     * @param local
-     * @return ldapUser corresponding to local user or null if user is no longer in LDAP
-     */
-    protected LDAPObject loadAndValidateUser(RealmModel realm, UserModel local) {
-        LDAPObject ldapUser = loadLDAPUserByUsername(realm, local.getUsername());
-        if (ldapUser == null) {
-            return null;
-        }
-        if (ldapUser.getUuid().equals(local.getFirstAttribute(LDAPConstants.LDAP_ID))) {
-            return ldapUser;
-        } else {
-            logger.warnf("LDAP User invalid. ID doesn't match. ID from LDAP [%s], LDAP ID from local DB: [%s]", ldapUser.getUuid(), local.getFirstAttribute(LDAPConstants.LDAP_ID));
-            return null;
-        }
-    }
-
-    @Override
-    public boolean isValid(RealmModel realm, UserModel local) {
-        return loadAndValidateUser(realm, local) != null;
-    }
-
-    @Override
-    public UserModel getUserByUsername(RealmModel realm, String username) {
-        LDAPObject ldapUser = loadLDAPUserByUsername(realm, username);
-        if (ldapUser == null) {
-            return null;
-        }
-
-        return importUserFromLDAP(session, realm, ldapUser);
-    }
-
-    protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) {
-        String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
-
-        if (ldapUsername == null) {
-            throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. Mapped username LDAP attribute: " +
-                    ldapIdentityStore.getConfig().getUsernameLdapAttribute() + ", attributes from LDAP: " + ldapUser.getAttributes());
-        }
-
-        UserModel imported = session.userStorage().addUser(realm, ldapUsername);
-        imported.setEnabled(true);
-
-        Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(getModel().getId());
-        for (UserFederationMapperModel mapperModel : federationMappers) {
-            LDAPFederationMapper ldapMapper = getMapper(mapperModel);
-            ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, imported, realm, true);
-        }
-
-        String userDN = ldapUser.getDn().toString();
-        imported.setFederationLink(model.getId());
-        imported.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
-        imported.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, userDN);
-
-        logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(),
-                ldapUser.getUuid(), userDN);
-        return proxy(realm, imported, ldapUser);
-    }
-
-    protected LDAPObject queryByEmail(RealmModel realm, String email) {
-        LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
-        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
-        // Mapper should replace "email" in parameter name with correct LDAP mapped attribute
-        Condition emailCondition = conditionsBuilder.equal(new QueryParameter(UserModel.EMAIL), email);
-        ldapQuery.where(emailCondition);
-
-        return ldapQuery.getFirstResult();
-    }
-
-
-    @Override
-    public UserModel getUserByEmail(RealmModel realm, String email) {
-        LDAPObject ldapUser = queryByEmail(realm, email);
-        if (ldapUser == null) {
-            return null;
-        }
-
-        return importUserFromLDAP(session, realm, ldapUser);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        // complete Don't think we have to do anything
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        // TODO: Maybe mappers callback to ensure role deletion propagated to LDAP by RoleLDAPFederationMapper?
-    }
-
-    public boolean validPassword(RealmModel realm, UserModel user, String password) {
-        if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) {
-            // Use Kerberos JAAS (Krb5LoginModule)
-            KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
-            return authenticator.validUser(user.getUsername(), password);
-        } else {
-            // Use Naming LDAP API
-            LDAPObject ldapUser = loadAndValidateUser(realm, user);
-            return ldapIdentityStore.validatePassword(ldapUser, password);
-        }
-    }
-
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        for (UserCredentialModel cred : input) {
-            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                return validPassword(realm, user, cred.getValue());
-            } else {
-                return false; // invalid cred type
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return validCredentials(realm, user, Arrays.asList(input));
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
-        if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
-            if (kerberosConfig.isAllowKerberosAuthentication()) {
-                String spnegoToken = credential.getValue();
-                SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
-
-                spnegoAuthenticator.authenticate();
-
-                Map<String, String> state = new HashMap<String, String>();
-                if (spnegoAuthenticator.isAuthenticated()) {
-
-                    // TODO: This assumes that LDAP "uid" is equal to kerberos principal name. Like uid "hnelson" and kerberos principal "hnelson@KEYCLOAK.ORG".
-                    // Check if it's correct or if LDAP attribute for mapping kerberos principal should be available (For ApacheDS it seems to be attribute "krb5PrincipalName" but on MSAD it's likely different)
-                    String username = spnegoAuthenticator.getAuthenticatedUsername();
-                    UserModel user = findOrCreateAuthenticatedUser(realm, username);
-
-                    if (user == null) {
-                        logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getDisplayName());
-                        return CredentialValidationOutput.failed();
-                    } else {
-                        String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
-                        if (delegationCredential != null) {
-                            state.put(KerberosConstants.GSS_DELEGATION_CREDENTIAL, delegationCredential);
-                        }
-
-                        return new CredentialValidationOutput(user, CredentialValidationOutput.Status.AUTHENTICATED, state);
-                    }
-                }  else {
-                    state.put(KerberosConstants.RESPONSE_TOKEN, spnegoAuthenticator.getResponseToken());
-                    return new CredentialValidationOutput(null, CredentialValidationOutput.Status.CONTINUE, state);
-                }
-            }
-        }
-
-        return CredentialValidationOutput.failed();
-    }
-
-    @Override
-    public void close() {
-    }
-
-    /**
-     * Called after successful kerberos authentication
-     *
-     * @param realm realm
-     * @param username username without realm prefix
-     * @return finded or newly created user
-     */
-    protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
-        UserModel user = session.userStorage().getUserByUsername(username, realm);
-        if (user != null) {
-            logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username);
-            if (!model.getId().equals(user.getFederationLink())) {
-                logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getDisplayName());
-                return null;
-            } else {
-                LDAPObject ldapObject = loadAndValidateUser(realm, user);
-                if (ldapObject != null) {
-                    return proxy(realm, user, ldapObject);
-                } else {
-                    logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s",
-                            username,  model.getDisplayName(), user.getFirstAttribute(LDAPConstants.LDAP_ID));
-                    logger.warn("Will re-create user");
-                    session.userStorage().removeUser(realm, user);
-                }
-            }
-        }
-
-        // Creating user to local storage
-        logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username);
-        return getUserByUsername(realm, username);
-    }
-
-    public LDAPObject loadLDAPUserByUsername(RealmModel realm, String username) {
-        LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
-        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
-        String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute();
-        Condition usernameCondition = conditionsBuilder.equal(new QueryParameter(usernameMappedAttribute), username);
-        ldapQuery.where(usernameCondition);
-
-        LDAPObject ldapUser = ldapQuery.getFirstResult();
-        if (ldapUser == null) {
-            return null;
-        }
-
-        // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
-        String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
-        if (!username.equals(ldapUsername)) {
-            logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, ldapUsername);
-            return null;
-        }
-
-        return ldapUser;
-    }
-
-    public LDAPFederationMapper getMapper(UserFederationMapperModel mapperModel) {
-        LDAPFederationMapper ldapMapper = (LDAPFederationMapper) getSession().getProvider(UserFederationMapper.class, mapperModel.getFederationMapperType());
-        if (ldapMapper == null) {
-            throw new ModelException("Can't find mapper type with ID: " + mapperModel.getFederationMapperType());
-        }
-
-        return ldapMapper;
-    }
-}
+package org.keycloak.federation.ldap;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
+import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
+import org.keycloak.federation.ldap.idm.model.LDAPObject;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
+import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
+import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig;
+import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionTask;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.mappers.UserFederationMapper;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserFederationSyncResult;
+import org.keycloak.models.UserModel;
+import org.keycloak.constants.KerberosConstants;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class LDAPFederationProvider implements UserFederationProvider {
+    private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class);
+
+    protected LDAPFederationProviderFactory factory;
+    protected KeycloakSession session;
+    protected UserFederationProviderModel model;
+    protected LDAPIdentityStore ldapIdentityStore;
+    protected EditMode editMode;
+    protected LDAPProviderKerberosConfig kerberosConfig;
+
+    protected final Set<String> supportedCredentialTypes = new HashSet<>();
+
+    public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) {
+        this.factory = factory;
+        this.session = session;
+        this.model = model;
+        this.ldapIdentityStore = ldapIdentityStore;
+        this.kerberosConfig = new LDAPProviderKerberosConfig(model);
+        this.editMode = ldapIdentityStore.getConfig().getEditMode();
+
+        supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
+        if (kerberosConfig.isAllowKerberosAuthentication()) {
+            supportedCredentialTypes.add(UserCredentialModel.KERBEROS);
+        }
+    }
+
+    public KeycloakSession getSession() {
+        return session;
+    }
+
+    public UserFederationProviderModel getModel() {
+        return model;
+    }
+
+    public LDAPIdentityStore getLdapIdentityStore() {
+        return this.ldapIdentityStore;
+    }
+
+    public EditMode getEditMode() {
+        return editMode;
+    }
+
+    @Override
+    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
+        LDAPObject ldapObject = loadAndValidateUser(realm, local);
+        if (ldapObject == null) {
+            return null;
+        }
+
+        return proxy(realm, local, ldapObject);
+    }
+
+    protected UserModel proxy(RealmModel realm, UserModel local, LDAPObject ldapObject) {
+        UserModel proxied = local;
+        switch (editMode) {
+            case READ_ONLY:
+                proxied = new ReadonlyLDAPUserModelDelegate(local, this);
+                break;
+            case WRITABLE:
+                proxied = new WritableLDAPUserModelDelegate(local, this, ldapObject);
+                break;
+            case UNSYNCED:
+                proxied = new UnsyncedLDAPUserModelDelegate(local, this);
+        }
+
+        Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
+        for (UserFederationMapperModel mapperModel : federationMappers) {
+            LDAPFederationMapper ldapMapper = getMapper(mapperModel);
+            proxied = ldapMapper.proxy(mapperModel, this, ldapObject, proxied, realm);
+        }
+
+        return proxied;
+    }
+
+    @Override
+    public Set<String> getSupportedCredentialTypes(UserModel local) {
+        Set<String> supportedCredentialTypes = new HashSet<String>(this.supportedCredentialTypes);
+        if (editMode == EditMode.UNSYNCED ) {
+            for (UserCredentialValueModel cred : local.getCredentialsDirectly()) {
+                if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+                    // User has changed password in KC local database. Use KC password instead of LDAP password
+                    supportedCredentialTypes.remove(UserCredentialModel.PASSWORD);
+                }
+            }
+        }
+        return supportedCredentialTypes;
+    }
+
+    @Override
+    public Set<String> getSupportedCredentialTypes() {
+        return new HashSet<String>(this.supportedCredentialTypes);
+    }
+
+    @Override
+    public boolean synchronizeRegistrations() {
+        return "true".equalsIgnoreCase(model.getConfig().get(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE;
+    }
+
+    @Override
+    public UserModel register(RealmModel realm, UserModel user) {
+        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
+        if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
+
+        LDAPObject ldapObject = LDAPUtils.addUserToLDAP(this, realm, user);
+        user.setSingleAttribute(LDAPConstants.LDAP_ID, ldapObject.getUuid());
+        user.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapObject.getDn().toString());
+
+        return proxy(realm, user, ldapObject);
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) {
+            logger.warnf("User '%s' can't be deleted in LDAP as editMode is '%s'", user.getUsername(), editMode.toString());
+            return false;
+        }
+
+        LDAPObject ldapObject = loadAndValidateUser(realm, user);
+        if (ldapObject == null) {
+            logger.warnf("User '%s' can't be deleted from LDAP as it doesn't exist here", user.getUsername());
+            return false;
+        }
+
+        ldapIdentityStore.remove(ldapObject);
+        return true;
+    }
+
+    @Override
+    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
+        List<UserModel> searchResults =new LinkedList<UserModel>();
+
+        List<LDAPObject> ldapUsers = searchLDAP(realm, attributes, maxResults);
+        for (LDAPObject ldapUser : ldapUsers) {
+            String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
+            if (session.userStorage().getUserByUsername(ldapUsername, realm) == null) {
+                UserModel imported = importUserFromLDAP(session, realm, ldapUser);
+                searchResults.add(imported);
+            }
+        }
+
+        return searchResults;
+    }
+
+    protected List<LDAPObject> searchLDAP(RealmModel realm, Map<String, String> attributes, int maxResults) {
+
+        List<LDAPObject> results = new ArrayList<LDAPObject>();
+        if (attributes.containsKey(USERNAME)) {
+            LDAPObject user = loadLDAPUserByUsername(realm, attributes.get(USERNAME));
+            if (user != null) {
+                results.add(user);
+            }
+        }
+
+        if (attributes.containsKey(EMAIL)) {
+            LDAPObject user = queryByEmail(realm, attributes.get(EMAIL));
+            if (user != null) {
+                results.add(user);
+            }
+        }
+
+        if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
+            LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
+            LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
+
+            // Mapper should replace parameter with correct LDAP mapped attributes
+            if (attributes.containsKey(FIRST_NAME)) {
+                ldapQuery.where(conditionsBuilder.equal(new QueryParameter(FIRST_NAME), attributes.get(FIRST_NAME)));
+            }
+            if (attributes.containsKey(LAST_NAME)) {
+                ldapQuery.where(conditionsBuilder.equal(new QueryParameter(LAST_NAME), attributes.get(LAST_NAME)));
+            }
+
+            List<LDAPObject> ldapObjects = ldapQuery.getResultList();
+            results.addAll(ldapObjects);
+        }
+
+        return results;
+    }
+
+    /**
+     * @param local
+     * @return ldapUser corresponding to local user or null if user is no longer in LDAP
+     */
+    protected LDAPObject loadAndValidateUser(RealmModel realm, UserModel local) {
+        LDAPObject ldapUser = loadLDAPUserByUsername(realm, local.getUsername());
+        if (ldapUser == null) {
+            return null;
+        }
+        if (ldapUser.getUuid().equals(local.getFirstAttribute(LDAPConstants.LDAP_ID))) {
+            return ldapUser;
+        } else {
+            logger.warnf("LDAP User invalid. ID doesn't match. ID from LDAP [%s], LDAP ID from local DB: [%s]", ldapUser.getUuid(), local.getFirstAttribute(LDAPConstants.LDAP_ID));
+            return null;
+        }
+    }
+
+    @Override
+    public boolean isValid(RealmModel realm, UserModel local) {
+        return loadAndValidateUser(realm, local) != null;
+    }
+
+    @Override
+    public UserModel getUserByUsername(RealmModel realm, String username) {
+        LDAPObject ldapUser = loadLDAPUserByUsername(realm, username);
+        if (ldapUser == null) {
+            return null;
+        }
+
+        return importUserFromLDAP(session, realm, ldapUser);
+    }
+
+    protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) {
+        String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
+
+        if (ldapUsername == null) {
+            throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. Mapped username LDAP attribute: " +
+                    ldapIdentityStore.getConfig().getUsernameLdapAttribute() + ", attributes from LDAP: " + ldapUser.getAttributes());
+        }
+
+        UserModel imported = session.userStorage().addUser(realm, ldapUsername);
+        imported.setEnabled(true);
+
+        Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(getModel().getId());
+        for (UserFederationMapperModel mapperModel : federationMappers) {
+            LDAPFederationMapper ldapMapper = getMapper(mapperModel);
+            ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, imported, realm, true);
+        }
+
+        String userDN = ldapUser.getDn().toString();
+        imported.setFederationLink(model.getId());
+        imported.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
+        imported.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, userDN);
+
+        logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(),
+                ldapUser.getUuid(), userDN);
+        return proxy(realm, imported, ldapUser);
+    }
+
+    protected LDAPObject queryByEmail(RealmModel realm, String email) {
+        LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
+        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
+
+        // Mapper should replace "email" in parameter name with correct LDAP mapped attribute
+        Condition emailCondition = conditionsBuilder.equal(new QueryParameter(UserModel.EMAIL), email);
+        ldapQuery.where(emailCondition);
+
+        return ldapQuery.getFirstResult();
+    }
+
+
+    @Override
+    public UserModel getUserByEmail(RealmModel realm, String email) {
+        LDAPObject ldapUser = queryByEmail(realm, email);
+        if (ldapUser == null) {
+            return null;
+        }
+
+        return importUserFromLDAP(session, realm, ldapUser);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        // complete Don't think we have to do anything
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        // TODO: Maybe mappers callback to ensure role deletion propagated to LDAP by RoleLDAPFederationMapper?
+    }
+
+    public boolean validPassword(RealmModel realm, UserModel user, String password) {
+        if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) {
+            // Use Kerberos JAAS (Krb5LoginModule)
+            KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
+            return authenticator.validUser(user.getUsername(), password);
+        } else {
+            // Use Naming LDAP API
+            LDAPObject ldapUser = loadAndValidateUser(realm, user);
+            return ldapIdentityStore.validatePassword(ldapUser, password);
+        }
+    }
+
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        for (UserCredentialModel cred : input) {
+            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+                return validPassword(realm, user, cred.getValue());
+            } else {
+                return false; // invalid cred type
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return validCredentials(realm, user, Arrays.asList(input));
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
+        if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
+            if (kerberosConfig.isAllowKerberosAuthentication()) {
+                String spnegoToken = credential.getValue();
+                SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
+
+                spnegoAuthenticator.authenticate();
+
+                Map<String, String> state = new HashMap<String, String>();
+                if (spnegoAuthenticator.isAuthenticated()) {
+
+                    // TODO: This assumes that LDAP "uid" is equal to kerberos principal name. Like uid "hnelson" and kerberos principal "hnelson@KEYCLOAK.ORG".
+                    // Check if it's correct or if LDAP attribute for mapping kerberos principal should be available (For ApacheDS it seems to be attribute "krb5PrincipalName" but on MSAD it's likely different)
+                    String username = spnegoAuthenticator.getAuthenticatedUsername();
+                    UserModel user = findOrCreateAuthenticatedUser(realm, username);
+
+                    if (user == null) {
+                        logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getDisplayName());
+                        return CredentialValidationOutput.failed();
+                    } else {
+                        String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
+                        if (delegationCredential != null) {
+                            state.put(KerberosConstants.GSS_DELEGATION_CREDENTIAL, delegationCredential);
+                        }
+
+                        return new CredentialValidationOutput(user, CredentialValidationOutput.Status.AUTHENTICATED, state);
+                    }
+                }  else {
+                    state.put(KerberosConstants.RESPONSE_TOKEN, spnegoAuthenticator.getResponseToken());
+                    return new CredentialValidationOutput(null, CredentialValidationOutput.Status.CONTINUE, state);
+                }
+            }
+        }
+
+        return CredentialValidationOutput.failed();
+    }
+
+    @Override
+    public void close() {
+    }
+
+    /**
+     * Called after successful kerberos authentication
+     *
+     * @param realm realm
+     * @param username username without realm prefix
+     * @return finded or newly created user
+     */
+    protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
+        UserModel user = session.userStorage().getUserByUsername(username, realm);
+        if (user != null) {
+            logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username);
+            if (!model.getId().equals(user.getFederationLink())) {
+                logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getDisplayName());
+                return null;
+            } else {
+                LDAPObject ldapObject = loadAndValidateUser(realm, user);
+                if (ldapObject != null) {
+                    return proxy(realm, user, ldapObject);
+                } else {
+                    logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s",
+                            username,  model.getDisplayName(), user.getFirstAttribute(LDAPConstants.LDAP_ID));
+                    logger.warn("Will re-create user");
+                    session.userStorage().removeUser(realm, user);
+                }
+            }
+        }
+
+        // Creating user to local storage
+        logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username);
+        return getUserByUsername(realm, username);
+    }
+
+    public LDAPObject loadLDAPUserByUsername(RealmModel realm, String username) {
+        LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
+        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
+
+        String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute();
+        Condition usernameCondition = conditionsBuilder.equal(new QueryParameter(usernameMappedAttribute), username);
+        ldapQuery.where(usernameCondition);
+
+        LDAPObject ldapUser = ldapQuery.getFirstResult();
+        if (ldapUser == null) {
+            return null;
+        }
+
+        // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
+        String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
+        if (!username.equals(ldapUsername)) {
+            logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, ldapUsername);
+            return null;
+        }
+
+        return ldapUser;
+    }
+
+    public LDAPFederationMapper getMapper(UserFederationMapperModel mapperModel) {
+        LDAPFederationMapper ldapMapper = (LDAPFederationMapper) getSession().getProvider(UserFederationMapper.class, mapperModel.getFederationMapperType());
+        if (ldapMapper == null) {
+            throw new ModelException("Can't find mapper type with ID: " + mapperModel.getFederationMapperType());
+        }
+
+        return ldapMapper;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
index a71b84d..3198255 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
@@ -1,362 +1,362 @@
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.federation.kerberos.CommonKerberosConfig;
-import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
-import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
-import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.QueryParameter;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakSessionTask;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationEventAwareProviderFactory;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserFederationSyncResult;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class LDAPFederationProviderFactory extends UserFederationEventAwareProviderFactory {
-    private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
-    public static final String PROVIDER_NAME = LDAPConstants.LDAP_PROVIDER;
-
-    private LDAPIdentityStoreRegistry ldapStoreRegistry;
-
-    @Override
-    public UserFederationProvider create(KeycloakSession session) {
-        throw new IllegalAccessError("Illegal to call this method");
-    }
-
-    @Override
-    public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
-        return new LDAPFederationProvider(this, session, model, ldapIdentityStore);
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
-    }
-
-    @Override
-    public void close() {
-        this.ldapStoreRegistry = null;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_NAME;
-    }
-
-    @Override
-    public Set<String> getConfigurationOptions() {
-        return Collections.emptySet();
-    }
-
-
-    // Best effort to create appropriate mappers according to our LDAP config
-    @Override
-    public void onProviderModelCreated(RealmModel realm, UserFederationProviderModel newProviderModel) {
-        LDAPConfig ldapConfig = new LDAPConfig(newProviderModel.getConfig());
-
-        boolean activeDirectory = ldapConfig.isActiveDirectory();
-        UserFederationProvider.EditMode editMode = ldapConfig.getEditMode();
-        String readOnly = String.valueOf(editMode == UserFederationProvider.EditMode.READ_ONLY || editMode == UserFederationProvider.EditMode.UNSYNCED);
-        String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
-
-        String alwaysReadValueFromLDAP = String.valueOf(editMode==UserFederationProvider.EditMode.READ_ONLY || editMode== UserFederationProvider.EditMode.WRITABLE);
-
-        UserFederationMapperModel mapperModel;
-        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
-                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, usernameLdapAttribute,
-                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
-                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-        realm.addUserFederationMapper(mapperModel);
-
-        // CN is typically used as RDN for Active Directory deployments
-        if (ldapConfig.getRdnLdapAttribute().equalsIgnoreCase(LDAPConstants.CN)) {
-
-            if (usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.CN)) {
-
-                // For AD deployments with "cn" as username, we will map "givenName" to first name
-                mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                        UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
-                        UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
-                        UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                        UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                        UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-                realm.addUserFederationMapper(mapperModel);
-
-            } else {
-                if (editMode == UserFederationProvider.EditMode.WRITABLE) {
-
-                    // For AD deployments with "sAMAccountName" as username and writable, we need to map "cn" as username as well (this is needed so we can register new users from KC into LDAP) and we will map "givenName" to first name.
-                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                            UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
-                            UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
-                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                            UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                            UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-                    realm.addUserFederationMapper(mapperModel);
-
-                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username-cn", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                            UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
-                            UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
-                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                            UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
-                            UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-                    realm.addUserFederationMapper(mapperModel);
-                } else {
-
-                    // For read-only LDAP, we map "cn" as full name
-                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("full name", newProviderModel.getId(), FullNameLDAPFederationMapperFactory.PROVIDER_ID,
-                            FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE, LDAPConstants.CN,
-                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
-                    realm.addUserFederationMapper(mapperModel);
-                }
-            }
-        } else {
-            mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                    UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
-                    UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
-                    UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                    UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                    UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-            realm.addUserFederationMapper(mapperModel);
-        }
-
-        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("last name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.LAST_NAME,
-                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.SN,
-                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
-        realm.addUserFederationMapper(mapperModel);
-
-        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("email", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.EMAIL,
-                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.EMAIL,
-                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
-                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
-                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
-        realm.addUserFederationMapper(mapperModel);
-
-        String createTimestampLdapAttrName = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP;
-        String modifyTimestampLdapAttrName = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP;
-
-        // map createTimeStamp as read-only
-        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("creation date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.CREATE_TIMESTAMP,
-                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, createTimestampLdapAttrName,
-                UserAttributeLDAPFederationMapper.READ_ONLY, "true",
-                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
-        realm.addUserFederationMapper(mapperModel);
-
-        // map modifyTimeStamp as read-only
-        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("modify date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
-                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.MODIFY_TIMESTAMP,
-                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, modifyTimestampLdapAttrName,
-                UserAttributeLDAPFederationMapper.READ_ONLY, "true",
-                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
-                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
-        realm.addUserFederationMapper(mapperModel);
-    }
-
-
-    @Override
-    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
-        logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s", realmId, model.getDisplayName());
-
-        LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
-        UserFederationSyncResult syncResult = syncImpl(sessionFactory, userQuery, realmId, model);
-
-        // TODO: Remove all existing keycloak users, which have federation links, but are not in LDAP. Perhaps don't check users, which were just added or updated during this sync?
-
-        logger.infof("Sync all users finished: %s", syncResult.getStatus());
-        return syncResult;
-    }
-
-    @Override
-    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
-        logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, last sync time: " + lastSync, realmId, model.getDisplayName());
-
-        // Sync newly created and updated users
-        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-        Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.CREATE_TIMESTAMP), lastSync);
-        Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.MODIFY_TIMESTAMP), lastSync);
-        Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition);
-
-        LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
-        userQuery.where(orCondition);
-        UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model);
-
-        logger.infof("Sync changed users finished: %s", result.getStatus());
-        return result;
-    }
-
-    protected UserFederationSyncResult syncImpl(KeycloakSessionFactory sessionFactory, LDAPQuery userQuery, final String realmId, final UserFederationProviderModel fedModel) {
-
-        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
-
-        boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION));
-        if (pagination) {
-
-            String pageSizeConfig = fedModel.getConfig().get(LDAPConstants.BATCH_SIZE_FOR_SYNC);
-            int pageSize = pageSizeConfig!=null ? Integer.parseInt(pageSizeConfig) : LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC;
-
-            boolean nextPage = true;
-            while (nextPage) {
-                userQuery.setLimit(pageSize);
-                final List<LDAPObject> users = userQuery.getResultList();
-                nextPage = userQuery.getPaginationContext() != null;
-                UserFederationSyncResult currentPageSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
-                syncResult.add(currentPageSync);
-            }
-        } else {
-            // LDAP pagination not available. Do everything in single transaction
-            final List<LDAPObject> users = userQuery.getResultList();
-            UserFederationSyncResult currentSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
-            syncResult.add(currentSync);
-        }
-
-        return syncResult;
-    }
-
-    private LDAPQuery createQuery(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
-        class QueryHolder {
-            LDAPQuery query;
-        }
-
-        final QueryHolder queryHolder = new QueryHolder();
-        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
-            @Override
-            public void run(KeycloakSession session) {
-                LDAPFederationProvider ldapFedProvider = getInstance(session, model);
-                RealmModel realm = session.realms().getRealm(realmId);
-                queryHolder.query = LDAPUtils.createQueryForUserSearch(ldapFedProvider, realm);
-            }
-
-        });
-        return queryHolder.query;
-    }
-
-    protected UserFederationSyncResult importLdapUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel fedModel, List<LDAPObject> ldapUsers) {
-        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
-
-        class BooleanHolder {
-            private boolean value = true;
-        }
-        final BooleanHolder exists = new BooleanHolder();
-
-        for (final LDAPObject ldapUser : ldapUsers) {
-
-            try {
-
-                // Process each user in it's own transaction to avoid global fail
-                KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
-                    @Override
-                    public void run(KeycloakSession session) {
-                        LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
-                        RealmModel currentRealm = session.realms().getRealm(realmId);
-
-                        String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
-                        UserModel currentUser = session.userStorage().getUserByUsername(username, currentRealm);
-
-                        if (currentUser == null) {
-
-                            // Add new user to Keycloak
-                            exists.value = false;
-                            ldapFedProvider.importUserFromLDAP(session, currentRealm, ldapUser);
-                            syncResult.increaseAdded();
-
-                        } else {
-                            if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getFirstAttribute(LDAPConstants.LDAP_ID)))) {
-
-                                // Update keycloak user
-                                Set<UserFederationMapperModel> federationMappers = currentRealm.getUserFederationMappersByFederationProvider(fedModel.getId());
-                                for (UserFederationMapperModel mapperModel : federationMappers) {
-                                    LDAPFederationMapper ldapMapper = ldapFedProvider.getMapper(mapperModel);
-                                    ldapMapper.onImportUserFromLDAP(mapperModel, ldapFedProvider, ldapUser, currentUser, currentRealm, false);
-                                }
-
-                                logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
-                                syncResult.increaseUpdated();
-                            } else {
-                                logger.warnf("User '%s' is not updated during sync as he already exists in Keycloak database but is not linked to federation provider '%s'", username, fedModel.getDisplayName());
-                                syncResult.increaseFailed();
-                            }
-                        }
-                    }
-
-                });
-            } catch (ModelException me) {
-                logger.error("Failed during import user from LDAP", me);
-                syncResult.increaseFailed();
-
-                // Remove user if we already added him during this transaction
-                if (!exists.value) {
-                    KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
-                        @Override
-                        public void run(KeycloakSession session) {
-                            LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
-                            RealmModel currentRealm = session.realms().getRealm(realmId);
-                            String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
-                            UserModel existing = session.userStorage().getUserByUsername(username, currentRealm);
-                            if (existing != null) {
-                                session.userStorage().removeUser(currentRealm, existing);
-                            }
-                        }
-
-                    });
-                }
-            }
-        }
-
-        return syncResult;
-    }
-
-    protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
-        KerberosServerSubjectAuthenticator kerberosAuth = createKerberosSubjectAuthenticator(kerberosConfig);
-        return new SPNEGOAuthenticator(kerberosConfig, kerberosAuth, spnegoToken);
-    }
-
-    protected KerberosServerSubjectAuthenticator createKerberosSubjectAuthenticator(CommonKerberosConfig kerberosConfig) {
-        return new KerberosServerSubjectAuthenticator(kerberosConfig);
-    }
-
-    protected KerberosUsernamePasswordAuthenticator createKerberosUsernamePasswordAuthenticator(CommonKerberosConfig kerberosConfig) {
-        return new KerberosUsernamePasswordAuthenticator(kerberosConfig);
-    }
-}
+package org.keycloak.federation.ldap;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.federation.kerberos.CommonKerberosConfig;
+import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
+import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
+import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
+import org.keycloak.federation.ldap.idm.model.LDAPObject;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
+import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
+import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
+import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
+import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
+import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
+import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakSessionTask;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationEventAwareProviderFactory;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserFederationSyncResult;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class LDAPFederationProviderFactory extends UserFederationEventAwareProviderFactory {
+    private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
+    public static final String PROVIDER_NAME = LDAPConstants.LDAP_PROVIDER;
+
+    private LDAPIdentityStoreRegistry ldapStoreRegistry;
+
+    @Override
+    public UserFederationProvider create(KeycloakSession session) {
+        throw new IllegalAccessError("Illegal to call this method");
+    }
+
+    @Override
+    public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
+        LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
+        return new LDAPFederationProvider(this, session, model, ldapIdentityStore);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
+    }
+
+    @Override
+    public void close() {
+        this.ldapStoreRegistry = null;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_NAME;
+    }
+
+    @Override
+    public Set<String> getConfigurationOptions() {
+        return Collections.emptySet();
+    }
+
+
+    // Best effort to create appropriate mappers according to our LDAP config
+    @Override
+    public void onProviderModelCreated(RealmModel realm, UserFederationProviderModel newProviderModel) {
+        LDAPConfig ldapConfig = new LDAPConfig(newProviderModel.getConfig());
+
+        boolean activeDirectory = ldapConfig.isActiveDirectory();
+        UserFederationProvider.EditMode editMode = ldapConfig.getEditMode();
+        String readOnly = String.valueOf(editMode == UserFederationProvider.EditMode.READ_ONLY || editMode == UserFederationProvider.EditMode.UNSYNCED);
+        String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
+
+        String alwaysReadValueFromLDAP = String.valueOf(editMode==UserFederationProvider.EditMode.READ_ONLY || editMode== UserFederationProvider.EditMode.WRITABLE);
+
+        UserFederationMapperModel mapperModel;
+        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
+                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, usernameLdapAttribute,
+                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
+                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+        realm.addUserFederationMapper(mapperModel);
+
+        // CN is typically used as RDN for Active Directory deployments
+        if (ldapConfig.getRdnLdapAttribute().equalsIgnoreCase(LDAPConstants.CN)) {
+
+            if (usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.CN)) {
+
+                // For AD deployments with "cn" as username, we will map "givenName" to first name
+                mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                        UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
+                        UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
+                        UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                        UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                        UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+                realm.addUserFederationMapper(mapperModel);
+
+            } else {
+                if (editMode == UserFederationProvider.EditMode.WRITABLE) {
+
+                    // For AD deployments with "sAMAccountName" as username and writable, we need to map "cn" as username as well (this is needed so we can register new users from KC into LDAP) and we will map "givenName" to first name.
+                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                            UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
+                            UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
+                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                            UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                            UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+                    realm.addUserFederationMapper(mapperModel);
+
+                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username-cn", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                            UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
+                            UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
+                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                            UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
+                            UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+                    realm.addUserFederationMapper(mapperModel);
+                } else {
+
+                    // For read-only LDAP, we map "cn" as full name
+                    mapperModel = KeycloakModelUtils.createUserFederationMapperModel("full name", newProviderModel.getId(), FullNameLDAPFederationMapperFactory.PROVIDER_ID,
+                            FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE, LDAPConstants.CN,
+                            UserAttributeLDAPFederationMapper.READ_ONLY, readOnly);
+                    realm.addUserFederationMapper(mapperModel);
+                }
+            }
+        } else {
+            mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                    UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
+                    UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
+                    UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                    UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                    UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+            realm.addUserFederationMapper(mapperModel);
+        }
+
+        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("last name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.LAST_NAME,
+                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.SN,
+                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
+        realm.addUserFederationMapper(mapperModel);
+
+        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("email", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.EMAIL,
+                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.EMAIL,
+                UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
+                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
+                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
+        realm.addUserFederationMapper(mapperModel);
+
+        String createTimestampLdapAttrName = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP;
+        String modifyTimestampLdapAttrName = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP;
+
+        // map createTimeStamp as read-only
+        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("creation date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.CREATE_TIMESTAMP,
+                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, createTimestampLdapAttrName,
+                UserAttributeLDAPFederationMapper.READ_ONLY, "true",
+                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
+        realm.addUserFederationMapper(mapperModel);
+
+        // map modifyTimeStamp as read-only
+        mapperModel = KeycloakModelUtils.createUserFederationMapperModel("modify date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
+                UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.MODIFY_TIMESTAMP,
+                UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, modifyTimestampLdapAttrName,
+                UserAttributeLDAPFederationMapper.READ_ONLY, "true",
+                UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
+                UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
+        realm.addUserFederationMapper(mapperModel);
+    }
+
+
+    @Override
+    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
+        logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s", realmId, model.getDisplayName());
+
+        LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
+        UserFederationSyncResult syncResult = syncImpl(sessionFactory, userQuery, realmId, model);
+
+        // TODO: Remove all existing keycloak users, which have federation links, but are not in LDAP. Perhaps don't check users, which were just added or updated during this sync?
+
+        logger.infof("Sync all users finished: %s", syncResult.getStatus());
+        return syncResult;
+    }
+
+    @Override
+    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
+        logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, last sync time: " + lastSync, realmId, model.getDisplayName());
+
+        // Sync newly created and updated users
+        LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
+        Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.CREATE_TIMESTAMP), lastSync);
+        Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.MODIFY_TIMESTAMP), lastSync);
+        Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition);
+
+        LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
+        userQuery.where(orCondition);
+        UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model);
+
+        logger.infof("Sync changed users finished: %s", result.getStatus());
+        return result;
+    }
+
+    protected UserFederationSyncResult syncImpl(KeycloakSessionFactory sessionFactory, LDAPQuery userQuery, final String realmId, final UserFederationProviderModel fedModel) {
+
+        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
+
+        boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION));
+        if (pagination) {
+
+            String pageSizeConfig = fedModel.getConfig().get(LDAPConstants.BATCH_SIZE_FOR_SYNC);
+            int pageSize = pageSizeConfig!=null ? Integer.parseInt(pageSizeConfig) : LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC;
+
+            boolean nextPage = true;
+            while (nextPage) {
+                userQuery.setLimit(pageSize);
+                final List<LDAPObject> users = userQuery.getResultList();
+                nextPage = userQuery.getPaginationContext() != null;
+                UserFederationSyncResult currentPageSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
+                syncResult.add(currentPageSync);
+            }
+        } else {
+            // LDAP pagination not available. Do everything in single transaction
+            final List<LDAPObject> users = userQuery.getResultList();
+            UserFederationSyncResult currentSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
+            syncResult.add(currentSync);
+        }
+
+        return syncResult;
+    }
+
+    private LDAPQuery createQuery(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
+        class QueryHolder {
+            LDAPQuery query;
+        }
+
+        final QueryHolder queryHolder = new QueryHolder();
+        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+
+            @Override
+            public void run(KeycloakSession session) {
+                LDAPFederationProvider ldapFedProvider = getInstance(session, model);
+                RealmModel realm = session.realms().getRealm(realmId);
+                queryHolder.query = LDAPUtils.createQueryForUserSearch(ldapFedProvider, realm);
+            }
+
+        });
+        return queryHolder.query;
+    }
+
+    protected UserFederationSyncResult importLdapUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel fedModel, List<LDAPObject> ldapUsers) {
+        final UserFederationSyncResult syncResult = new UserFederationSyncResult();
+
+        class BooleanHolder {
+            private boolean value = true;
+        }
+        final BooleanHolder exists = new BooleanHolder();
+
+        for (final LDAPObject ldapUser : ldapUsers) {
+
+            try {
+
+                // Process each user in it's own transaction to avoid global fail
+                KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+
+                    @Override
+                    public void run(KeycloakSession session) {
+                        LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
+                        RealmModel currentRealm = session.realms().getRealm(realmId);
+
+                        String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
+                        UserModel currentUser = session.userStorage().getUserByUsername(username, currentRealm);
+
+                        if (currentUser == null) {
+
+                            // Add new user to Keycloak
+                            exists.value = false;
+                            ldapFedProvider.importUserFromLDAP(session, currentRealm, ldapUser);
+                            syncResult.increaseAdded();
+
+                        } else {
+                            if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getFirstAttribute(LDAPConstants.LDAP_ID)))) {
+
+                                // Update keycloak user
+                                Set<UserFederationMapperModel> federationMappers = currentRealm.getUserFederationMappersByFederationProvider(fedModel.getId());
+                                for (UserFederationMapperModel mapperModel : federationMappers) {
+                                    LDAPFederationMapper ldapMapper = ldapFedProvider.getMapper(mapperModel);
+                                    ldapMapper.onImportUserFromLDAP(mapperModel, ldapFedProvider, ldapUser, currentUser, currentRealm, false);
+                                }
+
+                                logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
+                                syncResult.increaseUpdated();
+                            } else {
+                                logger.warnf("User '%s' is not updated during sync as he already exists in Keycloak database but is not linked to federation provider '%s'", username, fedModel.getDisplayName());
+                                syncResult.increaseFailed();
+                            }
+                        }
+                    }
+
+                });
+            } catch (ModelException me) {
+                logger.error("Failed during import user from LDAP", me);
+                syncResult.increaseFailed();
+
+                // Remove user if we already added him during this transaction
+                if (!exists.value) {
+                    KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+
+                        @Override
+                        public void run(KeycloakSession session) {
+                            LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
+                            RealmModel currentRealm = session.realms().getRealm(realmId);
+                            String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
+                            UserModel existing = session.userStorage().getUserByUsername(username, currentRealm);
+                            if (existing != null) {
+                                session.userStorage().removeUser(currentRealm, existing);
+                            }
+                        }
+
+                    });
+                }
+            }
+        }
+
+        return syncResult;
+    }
+
+    protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
+        KerberosServerSubjectAuthenticator kerberosAuth = createKerberosSubjectAuthenticator(kerberosConfig);
+        return new SPNEGOAuthenticator(kerberosConfig, kerberosAuth, spnegoToken);
+    }
+
+    protected KerberosServerSubjectAuthenticator createKerberosSubjectAuthenticator(CommonKerberosConfig kerberosConfig) {
+        return new KerberosServerSubjectAuthenticator(kerberosConfig);
+    }
+
+    protected KerberosUsernamePasswordAuthenticator createKerberosUsernamePasswordAuthenticator(CommonKerberosConfig kerberosConfig) {
+        return new KerberosUsernamePasswordAuthenticator(kerberosConfig);
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java
index 3151407..1a7fe6c 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java
@@ -1,49 +1,49 @@
-package org.keycloak.federation.ldap;
-
-import org.keycloak.models.ModelReadOnlyException;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ReadonlyLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
-
-    protected LDAPFederationProvider provider;
-
-    public ReadonlyLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
-        super(delegate);
-        this.provider = provider;
-    }
-
-    @Override
-    public void setUsername(String username) {
-        throw new ModelReadOnlyException("Federated storage is not writable");
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        throw new ModelReadOnlyException("Federated storage is not writable");
-    }
-
-    @Override
-    public void setFirstName(String first) {
-        throw new ModelReadOnlyException("Federated storage is not writable");
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        if (provider.getSupportedCredentialTypes(delegate).contains(cred.getType())) {
-            throw new ModelReadOnlyException("Federated storage is not writable");
-        }
-        delegate.updateCredential(cred);
-    }
-
-    @Override
-    public void setEmail(String email) {
-        throw new ModelReadOnlyException("Federated storage is not writable");
-    }
-
-}
+package org.keycloak.federation.ldap;
+
+import org.keycloak.models.ModelReadOnlyException;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.UserModelDelegate;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ReadonlyLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
+
+    protected LDAPFederationProvider provider;
+
+    public ReadonlyLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
+        super(delegate);
+        this.provider = provider;
+    }
+
+    @Override
+    public void setUsername(String username) {
+        throw new ModelReadOnlyException("Federated storage is not writable");
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        throw new ModelReadOnlyException("Federated storage is not writable");
+    }
+
+    @Override
+    public void setFirstName(String first) {
+        throw new ModelReadOnlyException("Federated storage is not writable");
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        if (provider.getSupportedCredentialTypes(delegate).contains(cred.getType())) {
+            throw new ModelReadOnlyException("Federated storage is not writable");
+        }
+        delegate.updateCredential(cred);
+    }
+
+    @Override
+    public void setEmail(String email) {
+        throw new ModelReadOnlyException("Federated storage is not writable");
+    }
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java
index 7c2cfb8..a0bb6f9 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java
@@ -1,20 +1,20 @@
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UnsyncedLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
-    private static final Logger logger = Logger.getLogger(UnsyncedLDAPUserModelDelegate.class);
-
-    protected LDAPFederationProvider provider;
-
-    public UnsyncedLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
-        super(delegate);
-        this.provider = provider;
-    }
-}
+package org.keycloak.federation.ldap;
+
+import org.jboss.logging.Logger;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.UserModelDelegate;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UnsyncedLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
+    private static final Logger logger = Logger.getLogger(UnsyncedLDAPUserModelDelegate.class);
+
+    protected LDAPFederationProvider provider;
+
+    public UnsyncedLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
+        super(delegate);
+        this.provider = provider;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
index 4e6ba40..f49c0fb 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
@@ -1,42 +1,42 @@
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class WritableLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
-    private static final Logger logger = Logger.getLogger(WritableLDAPUserModelDelegate.class);
-
-    protected LDAPFederationProvider provider;
-    protected LDAPObject ldapObject;
-
-    public WritableLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider, LDAPObject ldapObject) {
-        super(delegate);
-        this.provider = provider;
-        this.ldapObject = ldapObject;
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        if (!provider.getSupportedCredentialTypes(delegate).contains(cred.getType())) {
-            delegate.updateCredential(cred);
-            return;
-        }
-
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
-            String password = cred.getValue();
-            ldapIdentityStore.updatePassword(ldapObject, password);
-        } else {
-            logger.warnf("Don't know how to update credential of type [%s] for user [%s]", cred.getType(), delegate.getUsername());
-        }
-    }
-
-}
+package org.keycloak.federation.ldap;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.ldap.idm.model.LDAPObject;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.UserModelDelegate;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class WritableLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
+    private static final Logger logger = Logger.getLogger(WritableLDAPUserModelDelegate.class);
+
+    protected LDAPFederationProvider provider;
+    protected LDAPObject ldapObject;
+
+    public WritableLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider, LDAPObject ldapObject) {
+        super(delegate);
+        this.provider = provider;
+        this.ldapObject = ldapObject;
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        if (!provider.getSupportedCredentialTypes(delegate).contains(cred.getType())) {
+            delegate.updateCredential(cred);
+            return;
+        }
+
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+            String password = cred.getValue();
+            ldapIdentityStore.updatePassword(ldapObject, password);
+        } else {
+            logger.warnf("Don't know how to update credential of type [%s] for user [%s]", cred.getType(), delegate.getUsername());
+        }
+    }
+
+}
diff --git a/forms/account-api/pom.xml b/forms/account-api/pom.xml
index 2f8c6f0..7ec7cc2 100755
--- a/forms/account-api/pom.xml
+++ b/forms/account-api/pom.xml
@@ -1,57 +1,57 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-account-api</artifactId>
-	<name>Keycloak Account Management API</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-account-api</artifactId>
+	<name>Keycloak Account Management API</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/account-freemarker/pom.xml b/forms/account-freemarker/pom.xml
index 1b736ae..9bfcdd2 100755
--- a/forms/account-freemarker/pom.xml
+++ b/forms/account-freemarker/pom.xml
@@ -1,82 +1,82 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-account-freemarker</artifactId>
-	<name>Keycloak Account Management FreeMarker</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-account-api</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-			<groupId>org.freemarker</groupId>
-			<artifactId>freemarker</artifactId>
-            <scope>provided</scope>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-account-freemarker</artifactId>
+	<name>Keycloak Account Management FreeMarker</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-account-api</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+            <scope>provided</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/common-freemarker/pom.xml b/forms/common-freemarker/pom.xml
index 9650d36..af3fb16 100755
--- a/forms/common-freemarker/pom.xml
+++ b/forms/common-freemarker/pom.xml
@@ -1,62 +1,62 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-forms-common-freemarker</artifactId>
-	<name>Keycloak Forms Common FreeMarker</name>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-			<groupId>org.freemarker</groupId>
-			<artifactId>freemarker</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>    
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-forms-common-freemarker</artifactId>
+	<name>Keycloak Forms Common FreeMarker</name>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>    
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java
index da8fc5d..1fb954e 100755
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java
@@ -1,23 +1,23 @@
-package org.keycloak.freemarker;
-
-import org.keycloak.models.BrowserSecurityHeaders;
-import org.keycloak.models.RealmModel;
-
-import javax.ws.rs.core.Response;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class BrowserSecurityHeaderSetup {
-
-    public static Response.ResponseBuilder headers(Response.ResponseBuilder builder, RealmModel realm) {
-        for (Map.Entry<String, String> entry : realm.getBrowserSecurityHeaders().entrySet()) {
-            String headerName = BrowserSecurityHeaders.headerAttributeMap.get(entry.getKey());
-            if (headerName == null) continue;
-            builder.header(headerName, entry.getValue());
-        }
-        return builder;
-    }
-}
+package org.keycloak.freemarker;
+
+import org.keycloak.models.BrowserSecurityHeaders;
+import org.keycloak.models.RealmModel;
+
+import javax.ws.rs.core.Response;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class BrowserSecurityHeaderSetup {
+
+    public static Response.ResponseBuilder headers(Response.ResponseBuilder builder, RealmModel realm) {
+        for (Map.Entry<String, String> entry : realm.getBrowserSecurityHeaders().entrySet()) {
+            String headerName = BrowserSecurityHeaders.headerAttributeMap.get(entry.getKey());
+            if (headerName == null) continue;
+            builder.header(headerName, entry.getValue());
+        }
+        return builder;
+    }
+}
diff --git a/forms/common-themes/pom.xml b/forms/common-themes/pom.xml
index 3338128..9ed3178 100755
--- a/forms/common-themes/pom.xml
+++ b/forms/common-themes/pom.xml
@@ -1,67 +1,67 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-forms-common-themes</artifactId>
-	<name>Keycloak Login Default Theme</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-forms-common-themes</artifactId>
+	<name>Keycloak Login Default Theme</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
index 60edadf..1a87bce 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
@@ -1,73 +1,73 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Keycloak Admin Console</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <link rel="shortcut icon" href="${resourceUrl}/img/favicon.ico">
-    <#if properties.styles?has_content>
-    <#list properties.styles?split(' ') as style>
-    <link href="${resourceUrl}/${style}" rel="stylesheet" />
-    </#list>
-    </#if>
-
-    <script type="text/javascript">
-        var authUrl = '${authUrl}';
-        var resourceUrl = '${resourceUrl}';
-    </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/angular/angular.js"></script>
-    <script src="${resourceUrl}/lib/angular/angular-resource.js"></script>
-    <script src="${resourceUrl}/lib/angular/angular-route.js"></script>
-    <script src="${resourceUrl}/lib/angular/ui-bootstrap-tpls-0.11.0.js"></script>
-
-    <script src="${resourceUrl}/lib/angular/select2.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/lib/fileupload/angular-file-upload.min.js"></script>
-    <script src="${resourceUrl}/lib/filesaver/FileSaver.js"></script>
-
-    <script src="${authUrl}/js/${resourceVersion}/keycloak.js" type="text/javascript"></script>
-
-    <script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/controllers/clients.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/controllers/users.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/loaders.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/services.js" type="text/javascript"></script>
-</head>
-<body data-ng-controller="GlobalCtrl" data-ng-cloak data-ng-show="auth.user">
-
-<nav class="navbar navbar-default navbar-pf" role="navigation" data-ng-include data-src="resourceUrl + '/partials/menu.html'">
-</nav>
-
-<div class="container-fluid">
-<div class="row">
-    <div data-ng-view id="view"></div>
-</div>
-</div>
-
-<div class="feedback-aligner" data-ng-show="notification">
-    <div class="alert alert-{{notification.type}} alert-dismissable">
-        <button type="button" class="close">
-            <span class="pficon pficon-close" data-ng-click="notification = null"/>
-        </button>
-
-        <span class="pficon pficon-ok" ng-show="notification.type == 'success'"></span>
-        <span class="pficon pficon-info" ng-show="notification.type == 'info'"></span>
-        <span class="pficon-layered" ng-show="notification.type == 'danger'">
-            <span class="pficon pficon-error-octagon"></span>
-            <span class="pficon pficon-error-exclamation"></span>
-        </span>
-        <span class="pficon-layered" ng-show="notification.type == 'warning'">
-            <span class="pficon pficon-warning-triangle"></span>
-            <span class="pficon pficon-warning-exclamation"></span>
-        </span>
-        <strong>{{notification.header}}</strong> {{notification.message}}
-    </div>
-</div>
-
-<div id="loading" class="loading">Loading...</div>
-
-</body>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Keycloak Admin Console</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="shortcut icon" href="${resourceUrl}/img/favicon.ico">
+    <#if properties.styles?has_content>
+    <#list properties.styles?split(' ') as style>
+    <link href="${resourceUrl}/${style}" rel="stylesheet" />
+    </#list>
+    </#if>
+
+    <script type="text/javascript">
+        var authUrl = '${authUrl}';
+        var resourceUrl = '${resourceUrl}';
+    </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/angular/angular.js"></script>
+    <script src="${resourceUrl}/lib/angular/angular-resource.js"></script>
+    <script src="${resourceUrl}/lib/angular/angular-route.js"></script>
+    <script src="${resourceUrl}/lib/angular/ui-bootstrap-tpls-0.11.0.js"></script>
+
+    <script src="${resourceUrl}/lib/angular/select2.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/lib/fileupload/angular-file-upload.min.js"></script>
+    <script src="${resourceUrl}/lib/filesaver/FileSaver.js"></script>
+
+    <script src="${authUrl}/js/${resourceVersion}/keycloak.js" type="text/javascript"></script>
+
+    <script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/controllers/clients.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/controllers/users.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/loaders.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/services.js" type="text/javascript"></script>
+</head>
+<body data-ng-controller="GlobalCtrl" data-ng-cloak data-ng-show="auth.user">
+
+<nav class="navbar navbar-default navbar-pf" role="navigation" data-ng-include data-src="resourceUrl + '/partials/menu.html'">
+</nav>
+
+<div class="container-fluid">
+<div class="row">
+    <div data-ng-view id="view"></div>
+</div>
+</div>
+
+<div class="feedback-aligner" data-ng-show="notification">
+    <div class="alert alert-{{notification.type}} alert-dismissable">
+        <button type="button" class="close">
+            <span class="pficon pficon-close" data-ng-click="notification = null"/>
+        </button>
+
+        <span class="pficon pficon-ok" ng-show="notification.type == 'success'"></span>
+        <span class="pficon pficon-info" ng-show="notification.type == 'info'"></span>
+        <span class="pficon-layered" ng-show="notification.type == 'danger'">
+            <span class="pficon pficon-error-octagon"></span>
+            <span class="pficon pficon-error-exclamation"></span>
+        </span>
+        <span class="pficon-layered" ng-show="notification.type == 'warning'">
+            <span class="pficon pficon-warning-triangle"></span>
+            <span class="pficon pficon-warning-exclamation"></span>
+        </span>
+        <strong>{{notification.header}}</strong> {{notification.message}}
+    </div>
+</div>
+
+<div id="loading" class="loading">Loading...</div>
+
+</body>
 </html>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
index b20e794..3f8618b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -1,1815 +1,1815 @@
-'use strict';
-
-var consoleBaseUrl = window.location.href;
-consoleBaseUrl = consoleBaseUrl.substring(0, consoleBaseUrl.indexOf("/console"));
-consoleBaseUrl = consoleBaseUrl + "/console";
-var configUrl = consoleBaseUrl + "/config";
-
-var auth = {};
-
-var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders', 'ui.bootstrap', 'ui.select2', 'angularFileUpload' ]);
-var resourceRequests = 0;
-var loadingTimer = -1;
-
-angular.element(document).ready(function () {
-    var keycloakAuth = new Keycloak(configUrl);
-
-    keycloakAuth.onAuthLogout = function() {
-        location.reload();
-    }
-
-    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
-        auth.authz = keycloakAuth;
-        module.factory('Auth', function() {
-            return auth;
-        });
-        angular.bootstrap(document, ["keycloak"]);
-    }).error(function () {
-        window.location.reload();
-    });
-});
-
-module.factory('authInterceptor', function($q, Auth) {
-    return {
-        request: function (config) {
-            if (!config.url.match(/.html$/)) {
-                var deferred = $q.defer();
-                if (Auth.authz.token) {
-                    Auth.authz.updateToken(5).success(function () {
-                        config.headers = config.headers || {};
-                        config.headers.Authorization = 'Bearer ' + Auth.authz.token;
-
-                        deferred.resolve(config);
-                    }).error(function () {
-                        location.reload();
-                    });
-                }
-                return deferred.promise;
-            } else {
-                return config;
-            }
-        }
-    };
-});
-
-
-
-
-module.config([ '$routeProvider', function($routeProvider) {
-    $routeProvider
-        .when('/create/realm', {
-            templateUrl : resourceUrl + '/partials/realm-create.html',
-            resolve : {
-
-            },
-            controller : 'RealmCreateCtrl'
-        })
-        .when('/realms/:realm', {
-            templateUrl : resourceUrl + '/partials/realm-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmDetailCtrl'
-        })
-        .when('/realms/:realm/login-settings', {
-            templateUrl : resourceUrl + '/partials/realm-login-settings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmLoginSettingsCtrl'
-        })
-        .when('/realms/:realm/theme-settings', {
-            templateUrl : resourceUrl + '/partials/realm-theme-settings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmThemeCtrl'
-        })
-        .when('/realms/:realm/cache-settings', {
-            templateUrl : resourceUrl + '/partials/realm-cache-settings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmCacheCtrl'
-        })
-        .when('/realms', {
-            templateUrl : resourceUrl + '/partials/realm-list.html',
-            controller : 'RealmListCtrl'
-        })
-        .when('/realms/:realm/token-settings', {
-            templateUrl : resourceUrl + '/partials/realm-tokens.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmTokenDetailCtrl'
-        })
-        .when('/realms/:realm/keys-settings', {
-            templateUrl : resourceUrl + '/partials/realm-keys.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmKeysDetailCtrl'
-        })
-        .when('/realms/:realm/identity-provider-settings', {
-            templateUrl : resourceUrl + '/partials/realm-identity-provider.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                instance : function(IdentityProviderLoader) {
-                    return {};
-                },
-                providerFactory : function(IdentityProviderFactoryLoader) {
-                    return {};
-                }
-            },
-            controller : 'RealmIdentityProviderCtrl'
-        })
-        .when('/create/identity-provider/:realm/:provider_id', {
-            templateUrl : function(params){ return resourceUrl + '/partials/realm-identity-provider-' + params.provider_id + '.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                instance : function(IdentityProviderLoader) {
-                    return {};
-                },
-                providerFactory : function(IdentityProviderFactoryLoader) {
-                    return new IdentityProviderFactoryLoader();
-                }
-            },
-            controller : 'RealmIdentityProviderCtrl'
-        })
-        .when('/realms/:realm/identity-provider-settings/provider/:provider_id/:alias', {
-            templateUrl : function(params){ return resourceUrl + '/partials/realm-identity-provider-' + params.provider_id + '.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                instance : function(IdentityProviderLoader) {
-                    return IdentityProviderLoader();
-                },
-                providerFactory : function(IdentityProviderFactoryLoader) {
-                    return IdentityProviderFactoryLoader();
-                }
-            },
-            controller : 'RealmIdentityProviderCtrl'
-        })
-        .when('/realms/:realm/identity-provider-settings/provider/:provider_id/:alias/export', {
-            templateUrl : resourceUrl + '/partials/realm-identity-provider-export.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                identityProvider : function(IdentityProviderLoader) {
-                    return IdentityProviderLoader();
-                },
-                providerFactory : function(IdentityProviderFactoryLoader) {
-                    return IdentityProviderFactoryLoader();
-                }
-            },
-            controller : 'RealmIdentityProviderExportCtrl'
-        })
-        .when('/realms/:realm/identity-provider-mappers/:alias/mappers', {
-            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mappers.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                identityProvider : function(IdentityProviderLoader) {
-                    return IdentityProviderLoader();
-                },
-                mapperTypes : function(IdentityProviderMapperTypesLoader) {
-                    return IdentityProviderMapperTypesLoader();
-                },
-                mappers : function(IdentityProviderMappersLoader) {
-                    return IdentityProviderMappersLoader();
-                }
-            },
-            controller : 'IdentityProviderMapperListCtrl'
-        })
-        .when('/realms/:realm/identity-provider-mappers/:alias/mappers/:mapperId', {
-            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mapper-detail.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                identityProvider : function(IdentityProviderLoader) {
-                    return IdentityProviderLoader();
-                },
-                mapperTypes : function(IdentityProviderMapperTypesLoader) {
-                    return IdentityProviderMapperTypesLoader();
-                },
-                mapper : function(IdentityProviderMapperLoader) {
-                    return IdentityProviderMapperLoader();
-                }
-            },
-            controller : 'IdentityProviderMapperCtrl'
-        })
-        .when('/create/identity-provider-mappers/:realm/:alias', {
-            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mapper-detail.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                identityProvider : function(IdentityProviderLoader) {
-                    return IdentityProviderLoader();
-                },
-                mapperTypes : function(IdentityProviderMapperTypesLoader) {
-                    return IdentityProviderMapperTypesLoader();
-                }
-            },
-            controller : 'IdentityProviderMapperCreateCtrl'
-        })
-
-        .when('/realms/:realm/default-roles', {
-            templateUrl : resourceUrl + '/partials/realm-default-roles.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                }
-            },
-            controller : 'RealmDefaultRolesCtrl'
-        })
-        .when('/realms/:realm/smtp-settings', {
-            templateUrl : resourceUrl + '/partials/realm-smtp.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmSMTPSettingsCtrl'
-        })
-        .when('/realms/:realm/events', {
-            templateUrl : resourceUrl + '/partials/realm-events.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmEventsCtrl'
-        })
-        .when('/realms/:realm/admin-events', {
-            templateUrl : resourceUrl + '/partials/realm-events-admin.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmAdminEventsCtrl'
-        })
-        .when('/realms/:realm/events-settings', {
-            templateUrl : resourceUrl + '/partials/realm-events-config.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                eventsConfig : function(RealmEventsConfigLoader) {
-                    return RealmEventsConfigLoader();
-                }
-            },
-            controller : 'RealmEventsConfigCtrl'
-        })
-        .when('/create/user/:realm', {
-            templateUrl : resourceUrl + '/partials/user-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function() {
-                    return {};
-                }
-            },
-            controller : 'UserDetailCtrl'
-        })
-        .when('/realms/:realm/users/:user', {
-            templateUrl : resourceUrl + '/partials/user-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                }
-            },
-            controller : 'UserDetailCtrl'
-        })
-        .when('/realms/:realm/users/:user/user-credentials', {
-            templateUrl : resourceUrl + '/partials/user-credentials.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                }
-            },
-            controller : 'UserCredentialsCtrl'
-        })
-        .when('/realms/:realm/users/:user/role-mappings', {
-            templateUrl : resourceUrl + '/partials/role-mappings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'UserRoleMappingCtrl'
-        })
-        .when('/realms/:realm/users/:user/sessions', {
-            templateUrl : resourceUrl + '/partials/user-sessions.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                },
-                sessions : function(UserSessionsLoader) {
-                    return UserSessionsLoader();
-                }
-            },
-            controller : 'UserSessionsCtrl'
-        })
-        .when('/realms/:realm/users/:user/federated-identity', {
-            templateUrl : resourceUrl + '/partials/user-federated-identity-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                },
-                federatedIdentities : function(UserFederatedIdentityLoader) {
-                    return UserFederatedIdentityLoader();
-                }
-            },
-            controller : 'UserFederatedIdentityCtrl'
-        })
-        .when('/create/federated-identity/:realm/:user', {
-            templateUrl : resourceUrl + '/partials/user-federated-identity-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                },
-                federatedIdentities : function(UserFederatedIdentityLoader) {
-                    return UserFederatedIdentityLoader();
-                }
-            },
-            controller : 'UserFederatedIdentityAddCtrl'
-        })
-        .when('/realms/:realm/users/:user/consents', {
-            templateUrl : resourceUrl + '/partials/user-consents.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                user : function(UserLoader) {
-                    return UserLoader();
-                },
-                userConsents : function(UserConsentsLoader) {
-                    return UserConsentsLoader();
-                }
-            },
-            controller : 'UserConsentsCtrl'
-        })
-        .when('/realms/:realm/users', {
-            templateUrl : resourceUrl + '/partials/user-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'UserListCtrl'
-        })
-
-        .when('/create/role/:realm', {
-            templateUrl : resourceUrl + '/partials/role-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                role : function() {
-                    return {};
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'RoleDetailCtrl'
-        })
-        .when('/realms/:realm/roles/:role', {
-            templateUrl : resourceUrl + '/partials/role-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                role : function(RoleLoader) {
-                    return RoleLoader();
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'RoleDetailCtrl'
-        })
-        .when('/realms/:realm/roles', {
-            templateUrl : resourceUrl + '/partials/role-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                }
-            },
-            controller : 'RoleListCtrl'
-        })
-
-        .when('/create/role/:realm/clients/:client', {
-            templateUrl : resourceUrl + '/partials/client-role-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                role : function() {
-                    return {};
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'ClientRoleDetailCtrl'
-        })
-        .when('/realms/:realm/clients/:client/roles/:role', {
-            templateUrl : resourceUrl + '/partials/client-role-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                role : function(ClientRoleLoader) {
-                    return ClientRoleLoader();
-                },
-                roles : function(RoleListLoader) {
-                    return RoleListLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'ClientRoleDetailCtrl'
-        })
-        .when('/realms/:realm/clients/:client/mappers', {
-            templateUrl : resourceUrl + '/partials/client-mappers.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'ClientProtocolMapperListCtrl'
-        })
-        .when('/realms/:realm/clients/:client/add-mappers', {
-            templateUrl : resourceUrl + '/partials/client-mappers-add.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'AddBuiltinProtocolMapperCtrl'
-        })
-        .when('/realms/:realm/clients/:client/mappers/:id', {
-            templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                mapper : function(ClientProtocolMapperLoader) {
-                    return ClientProtocolMapperLoader();
-                }
-
-            },
-            controller : 'ClientProtocolMapperCtrl'
-        })
-        .when('/create/client/:realm/:client/mappers', {
-            templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientProtocolMapperCreateCtrl'
-        })
-        .when('/realms/:realm/clients/:client/sessions', {
-            templateUrl : resourceUrl + '/partials/client-sessions.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                sessionCount : function(ClientSessionCountLoader) {
-                    return ClientSessionCountLoader();
-                }
-            },
-            controller : 'ClientSessionsCtrl'
-        })
-        .when('/realms/:realm/clients/:client/credentials', {
-            templateUrl : resourceUrl + '/partials/client-credentials.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientCredentialsCtrl'
-        })
-        .when('/realms/:realm/clients/:client/identity-provider', {
-            templateUrl : resourceUrl + '/partials/client-identity-provider.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientIdentityProviderCtrl'
-        })
-        .when('/realms/:realm/clients/:client/clustering', {
-            templateUrl : resourceUrl + '/partials/client-clustering.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientClusteringCtrl'
-        })
-        .when('/register-node/realms/:realm/clients/:client/clustering', {
-            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientClusteringNodeCtrl'
-        })
-        .when('/realms/:realm/clients/:client/clustering/:node', {
-            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientClusteringNodeCtrl'
-        })
-        .when('/realms/:realm/clients/:client/saml/keys', {
-            templateUrl : resourceUrl + '/partials/client-saml-keys.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientSamlKeyCtrl'
-        })
-        .when('/realms/:realm/clients/:client/saml/:keyType/import/:attribute', {
-            templateUrl : resourceUrl + '/partials/client-saml-key-import.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientCertificateImportCtrl'
-        })
-        .when('/realms/:realm/clients/:client/saml/:keyType/export/:attribute', {
-            templateUrl : resourceUrl + '/partials/client-saml-key-export.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientCertificateExportCtrl'
-        })
-        .when('/realms/:realm/clients/:client/roles', {
-            templateUrl : resourceUrl + '/partials/client-role-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                roles : function(ClientRoleListLoader) {
-                    return ClientRoleListLoader();
-                }
-            },
-            controller : 'ClientRoleListCtrl'
-        })
-        .when('/realms/:realm/clients/:client/revocation', {
-            templateUrl : resourceUrl + '/partials/client-revocation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientRevocationCtrl'
-        })
-        .when('/realms/:realm/clients/:client/scope-mappings', {
-            templateUrl : resourceUrl + '/partials/client-scope-mappings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'ClientScopeMappingCtrl'
-        })
-        .when('/realms/:realm/clients/:client/installation', {
-            templateUrl : resourceUrl + '/partials/client-installation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                }
-            },
-            controller : 'ClientInstallationCtrl'
-        })
-        .when('/create/client/:realm', {
-            templateUrl : resourceUrl + '/partials/client-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                },
-                client : function() {
-                    return {};
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'ClientDetailCtrl'
-        })
-        .when('/realms/:realm/clients/:client', {
-            templateUrl : resourceUrl + '/partials/client-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                },
-                client : function(ClientLoader) {
-                    return ClientLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'ClientDetailCtrl'
-        })
-        .when('/realms/:realm/clients', {
-            templateUrl : resourceUrl + '/partials/client-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-
-            },
-            controller : 'ClientListCtrl'
-        })
-        .when('/import/client/:realm', {
-            templateUrl : resourceUrl + '/partials/client-import.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'ClientImportCtrl'
-        })
-        .when('/', {
-            templateUrl : resourceUrl + '/partials/home.html',
-            controller : 'HomeCtrl'
-        })
-        .when('/mocks/:realm', {
-            templateUrl : resourceUrl + '/partials/realm-detail_mock.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-            },
-            controller : 'RealmDetailCtrl'
-        })
-        .when('/realms/:realm/sessions/revocation', {
-            templateUrl : resourceUrl + '/partials/session-revocation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmRevocationCtrl'
-        })
-         .when('/realms/:realm/sessions/realm', {
-            templateUrl : resourceUrl + '/partials/session-realm.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                stats : function(RealmClientSessionStatsLoader) {
-                    return RealmClientSessionStatsLoader();
-                }
-            },
-            controller : 'RealmSessionStatsCtrl'
-        })
-        .when('/realms/:realm/user-federation', {
-            templateUrl : resourceUrl + '/partials/user-federation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'UserFederationCtrl'
-        })
-        .when('/realms/:realm/user-federation/providers/ldap/:instance', {
-            templateUrl : resourceUrl + '/partials/federated-ldap.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                }
-            },
-            controller : 'LDAPCtrl'
-        })
-        .when('/create/user-federation/:realm/providers/ldap', {
-            templateUrl : resourceUrl + '/partials/federated-ldap.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function() {
-                    return {};
-                }
-            },
-            controller : 'LDAPCtrl'
-        })
-        .when('/realms/:realm/user-federation/providers/kerberos/:instance', {
-            templateUrl : resourceUrl + '/partials/federated-kerberos.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                },
-                providerFactory : function() {
-                    return { id: "kerberos" };
-                }
-            },
-            controller : 'GenericUserFederationCtrl'
-        })
-        .when('/create/user-federation/:realm/providers/kerberos', {
-            templateUrl : resourceUrl + '/partials/federated-kerberos.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function() {
-                    return {};
-                },
-                providerFactory : function() {
-                    return { id: "kerberos" };
-                }
-            },
-            controller : 'GenericUserFederationCtrl'
-        })
-        .when('/create/user-federation/:realm/providers/:provider', {
-            templateUrl : resourceUrl + '/partials/federated-generic.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function() {
-                    return {
-
-                    };
-                },
-                providerFactory : function(UserFederationFactoryLoader) {
-                    return UserFederationFactoryLoader();
-                }
-            },
-            controller : 'GenericUserFederationCtrl'
-        })
-        .when('/realms/:realm/user-federation/providers/:provider/:instance', {
-            templateUrl : resourceUrl + '/partials/federated-generic.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                instance : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                },
-                providerFactory : function(UserFederationFactoryLoader) {
-                    return UserFederationFactoryLoader();
-                }
-            },
-            controller : 'GenericUserFederationCtrl'
-        })
-        .when('/realms/:realm/user-federation/providers/:provider/:instance/mappers', {
-            templateUrl : function(params){ return resourceUrl + '/partials/federated-mappers.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                provider : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                },
-                mapperTypes : function(UserFederationMapperTypesLoader) {
-                    return UserFederationMapperTypesLoader();
-                },
-                mappers : function(UserFederationMappersLoader) {
-                    return UserFederationMappersLoader();
-                }
-            },
-            controller : 'UserFederationMapperListCtrl'
-        })
-        .when('/realms/:realm/user-federation/providers/:provider/:instance/mappers/:mapperId', {
-            templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                provider : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                },
-                mapperTypes : function(UserFederationMapperTypesLoader) {
-                    return UserFederationMapperTypesLoader();
-                },
-                mapper : function(UserFederationMapperLoader) {
-                    return UserFederationMapperLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'UserFederationMapperCtrl'
-        })
-        .when('/create/user-federation-mappers/:realm/:provider/:instance', {
-            templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                provider : function(UserFederationInstanceLoader) {
-                    return UserFederationInstanceLoader();
-                },
-                mapperTypes : function(UserFederationMapperTypesLoader) {
-                    return UserFederationMapperTypesLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'UserFederationMapperCreateCtrl'
-        })
-
-        .when('/realms/:realm/defense/headers', {
-            templateUrl : resourceUrl + '/partials/defense-headers.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-
-            },
-            controller : 'DefenseHeadersCtrl'
-        })
-        .when('/realms/:realm/defense/brute-force', {
-            templateUrl : resourceUrl + '/partials/brute-force.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmBruteForceCtrl'
-        })
-        .when('/realms/:realm/protocols', {
-            templateUrl : resourceUrl + '/partials/protocol-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                serverInfo : function(ServerInfoLoader) {
-                    return ServerInfoLoader();
-                }
-
-            },
-            controller : 'ProtocolListCtrl'
-        })
-        .when('/realms/:realm/authentication/flows', {
-            templateUrl : resourceUrl + '/partials/authentication-flows.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                flows : function(AuthenticationFlowsLoader) {
-                    return AuthenticationFlowsLoader();
-                }
-            },
-            controller : 'AuthenticationFlowsCtrl'
-        })
-        .when('/realms/:realm/authentication/required-actions', {
-            templateUrl : resourceUrl + '/partials/required-actions.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RequiredActionsCtrl'
-        })
-        .when('/realms/:realm/authentication/password-policy', {
-            templateUrl : resourceUrl + '/partials/password-policy.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                }
-            },
-            controller : 'RealmPasswordPolicyCtrl'
-        })
-        .when('/realms/:realm/authentication/config/:provider/:config', {
-            templateUrl : resourceUrl + '/partials/authenticator-config.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                configType : function(AuthenticationConfigDescriptionLoader) {
-                    return AuthenticationConfigDescriptionLoader();
-                },
-                config : function(AuthenticationConfigLoader) {
-                    return AuthenticationConfigLoader();
-                }
-            },
-            controller : 'AuthenticationConfigCtrl'
-        })
-        .when('/create/authentication/:realm/execution/:executionId/provider/:provider', {
-            templateUrl : resourceUrl + '/partials/authenticator-config.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                configType : function(AuthenticationConfigDescriptionLoader) {
-                    return AuthenticationConfigDescriptionLoader();
-                },
-                execution : function(ExecutionIdLoader) {
-                    return ExecutionIdLoader();
-                }
-            },
-            controller : 'AuthenticationConfigCreateCtrl'
-        })
-        .when('/server-info', {
-            templateUrl : resourceUrl + '/partials/server-info.html'
-        })
-        .when('/logout', {
-            templateUrl : resourceUrl + '/partials/home.html',
-            controller : 'LogoutCtrl'
-        })
-        .when('/notfound', {
-            templateUrl : resourceUrl + '/partials/notfound.html'
-        })
-        .when('/forbidden', {
-            templateUrl : resourceUrl + '/partials/forbidden.html'
-        })
-        .otherwise({
-            templateUrl : resourceUrl + '/partials/pagenotfound.html'
-        });
-} ]);
-
-module.config(function($httpProvider) {
-    $httpProvider.responseInterceptors.push('errorInterceptor');
-
-    var spinnerFunction = function(data, headersGetter) {
-        if (resourceRequests == 0) {
-            loadingTimer = window.setTimeout(function() {
-                $('#loading').show();
-                loadingTimer = -1;
-            }, 500);
-        }
-        resourceRequests++;
-        return data;
-    };
-    $httpProvider.defaults.transformRequest.push(spinnerFunction);
-
-    $httpProvider.responseInterceptors.push('spinnerInterceptor');
-    $httpProvider.interceptors.push('authInterceptor');
-
-});
-
-module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
-    return function(promise) {
-        return promise.then(function(response) {
-            resourceRequests--;
-            if (resourceRequests == 0) {
-                if(loadingTimer != -1) {
-                    window.clearTimeout(loadingTimer);
-                    loadingTimer = -1;
-                }
-                $('#loading').hide();
-            }
-            return response;
-        }, function(response) {
-            resourceRequests--;
-            if (resourceRequests == 0) {
-                if(loadingTimer != -1) {
-                    window.clearTimeout(loadingTimer);
-                    loadingTimer = -1;
-                }
-                $('#loading').hide();
-            }
-
-            return $q.reject(response);
-        });
-    };
-});
-
-module.factory('errorInterceptor', function($q, $window, $rootScope, $location, Notifications, Auth) {
-    return function(promise) {
-        return promise.then(function(response) {
-            return response;
-        }, function(response) {
-            if (response.status == 401) {
-                Auth.authz.logout();
-            } else if (response.status == 403) {
-                $location.path('/forbidden');
-            } else if (response.status == 404) {
-                $location.path('/notfound');
-            } else if (response.status) {
-                if (response.data && response.data.errorMessage) {
-                    Notifications.error(response.data.errorMessage);
-                } else {
-                    Notifications.error("An unexpected server error has occurred");
-                }
-            }
-            return $q.reject(response);
-        });
-    };
-});
-
-// collapsable form fieldsets
-module.directive('collapsable', function() {
-    return function(scope, element, attrs) {
-        element.click(function() {
-            $(this).toggleClass('collapsed');
-            $(this).find('.toggle-icons').toggleClass('kc-icon-collapse').toggleClass('kc-icon-expand');
-            $(this).find('.toggle-icons').text($(this).text() == "Icon: expand" ? "Icon: collapse" : "Icon: expand");
-            $(this).parent().find('.form-group').toggleClass('hidden');
-        });
-    }
-});
-
-// collapsable form fieldsets
-module.directive('uncollapsed', function() {
-    return function(scope, element, attrs) {
-        element.prepend('<i class="toggle-class fa fa-angle-down"></i> ');
-        element.click(function() {
-            $(this).find('.toggle-class').toggleClass('fa-angle-down').toggleClass('fa-angle-right');
-            $(this).parent().find('.form-group').toggleClass('hidden');
-        });
-    }
-});
-
-// collapsable form fieldsets
-module.directive('collapsed', function() {
-    return function(scope, element, attrs) {
-        element.prepend('<i class="toggle-class fa fa-angle-right"></i> ');
-        element.parent().find('.form-group').toggleClass('hidden');
-        element.click(function() {
-            $(this).find('.toggle-class').toggleClass('fa-angle-down').toggleClass('fa-angle-right');
-            $(this).parent().find('.form-group').toggleClass('hidden');
-        });
-    }
-});
-
-/**
- * Directive for presenting an ON-OFF switch for checkbox.
- * Usage: <input ng-model="mmm" name="nnn" id="iii" onoffswitch [on-text="ooo" off-text="fff"] />
- */
-module.directive('onoffswitch', function() {
-    return {
-        restrict: "EA",
-        replace: true,
-        scope: {
-            name: '@',
-            id: '@',
-            ngModel: '=',
-            ngDisabled: '=',
-            kcOnText: '@onText',
-            kcOffText: '@offText'
-        },
-        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
-        //templateUrl: "templates/kc-switch.html",
-        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='{{name}}' id='{{id}}'><label for='{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
-        compile: function(element, attrs) {
-            /*
-            We don't want to propagate basic attributes to the root element of directive. Id should be passed to the
-            input element only to achieve proper label binding (and validity).
-            */
-            element.removeAttr('name');
-            element.removeAttr('id');
-
-            if (!attrs.onText) { attrs.onText = "ON"; }
-            if (!attrs.offText) { attrs.offText = "OFF"; }
-
-            element.bind('keydown', function(e){
-                var code = e.keyCode || e.which;
-                if (code === 32 || code === 13) {
-                    e.stopImmediatePropagation();
-                    e.preventDefault();
-                    $(e.target).find('input').click();
-                }
-            });
-        }
-    }
-});
-
-/**
- * Directive for presenting an ON-OFF switch for checkbox.
- * This directive provides some additional capabilities to the default onoffswitch such as:
- *
- * - Dynamic values for id and name attributes. Useful if you need to use this directive inside a ng-repeat
- * - Specific scope to specify the value. Instead of just true or false.
- *
- * Usage: <input ng-model="mmm" name="nnn" id="iii" kc-onoffswitch-model [on-text="ooo" off-text="fff"] />
- */
-module.directive('onoffswitchmodel', function() {
-    return {
-        restrict: "EA",
-        replace: true,
-        scope: {
-            name: '=',
-            id: '=',
-            value: '=',
-            ngModel: '=',
-            ngDisabled: '=',
-            kcOnText: '@onText',
-            kcOffText: '@offText'
-        },
-        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
-        //templateUrl: "templates/kc-switch.html",
-        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-true-value='{{value}}' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='kc{{name}}' id='kc{{id}}'><label for='kc{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
-        compile: function(element, attrs) {
-
-            if (!attrs.onText) { attrs.onText = "ON"; }
-            if (!attrs.offText) { attrs.offText = "OFF"; }
-
-            element.bind('keydown click', function(e){
-                var code = e.keyCode || e.which;
-                if (code === 32 || code === 13) {
-                    e.stopImmediatePropagation();
-                    e.preventDefault();
-                    $(e.target).find('input').click();
-                }
-            });
-        }
-    }
-});
-
-/**
- * Directive for presenting an ON-OFF switch for checkbox.
- * This directive provides some additional capabilities to the default onoffswitch such as:
- *
- * - Specific scope to specify the value. Instead of just true or false.
- *
- * Usage: <input ng-model="mmm" name="nnn" id="iii" onoffswitchvalue [on-text="ooo" off-text="fff"] />
- */
-module.directive('onoffswitchvalue', function() {
-    return {
-        restrict: "EA",
-        replace: true,
-        scope: {
-            name: '@',
-            id: '@',
-            value: '=',
-            ngModel: '=',
-            ngDisabled: '=',
-            kcOnText: '@onText',
-            kcOffText: '@offText'
-        },
-        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
-        //templateUrl: "templates/kc-switch.html",
-        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-true-value='{{value}}' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='{{name}}' id='{{id}}'><label for='{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
-        compile: function(element, attrs) {
-            /*
-             We don't want to propagate basic attributes to the root element of directive. Id should be passed to the
-             input element only to achieve proper label binding (and validity).
-             */
-            element.removeAttr('name');
-            element.removeAttr('id');
-
-            if (!attrs.onText) { attrs.onText = "ON"; }
-            if (!attrs.offText) { attrs.offText = "OFF"; }
-
-            element.bind('keydown', function(e){
-                var code = e.keyCode || e.which;
-                if (code === 32 || code === 13) {
-                    e.stopImmediatePropagation();
-                    e.preventDefault();
-                    $(e.target).find('input').click();
-                }
-            });
-        }
-    }
-});
-
-module.directive('kcInput', function() {
-    var d = {
-        scope : true,
-        replace : false,
-        link : function(scope, element, attrs) {
-            var form = element.children('form');
-            var label = element.children('label');
-            var input = element.children('input');
-
-            var id = form.attr('name') + '.' + input.attr('name');
-
-            element.attr('class', 'control-group');
-
-            label.attr('class', 'control-label');
-            label.attr('for', id);
-
-            input.wrap('<div class="controls"/>');
-            input.attr('id', id);
-
-            if (!input.attr('placeHolder')) {
-                input.attr('placeHolder', label.text());
-            }
-
-            if (input.attr('required')) {
-                label.append(' <span class="required">*</span>');
-            }
-        }
-    };
-    return d;
-});
-
-module.directive('kcEnter', function() {
-    return function(scope, element, attrs) {
-        element.bind("keydown keypress", function(event) {
-            if (event.which === 13) {
-                scope.$apply(function() {
-                    scope.$eval(attrs.kcEnter);
-                });
-
-                event.preventDefault();
-            }
-        });
-    };
-});
-
-module.directive('kcSave', function ($compile, Notifications) {
-    return {
-        restrict: 'A',
-        link: function ($scope, elem, attr, ctrl) {
-            elem.addClass("btn btn-primary");
-            elem.attr("type","submit");
-            elem.bind('click', function() {
-                $scope.$apply(function() {
-                    var form = elem.closest('form');
-                    if (form && form.attr('name')) {
-                        var ngValid = form.find('.ng-valid');
-                        if ($scope[form.attr('name')].$valid) {
-                            //ngValid.removeClass('error');
-                            ngValid.parent().removeClass('has-error');
-                            $scope['save']();
-                        } else {
-                            Notifications.error("Missing or invalid field(s). Please verify the fields in red.")
-                            //ngValid.removeClass('error');
-                            ngValid.parent().removeClass('has-error');
-
-                            var ngInvalid = form.find('.ng-invalid');
-                            //ngInvalid.addClass('error');
-                            ngInvalid.parent().addClass('has-error');
-                        }
-                    }
-                });
-            })
-        }
-    }
-});
-
-module.directive('kcReset', function ($compile, Notifications) {
-    return {
-        restrict: 'A',
-        link: function ($scope, elem, attr, ctrl) {
-            elem.addClass("btn btn-default");
-            elem.attr("type","submit");
-            elem.bind('click', function() {
-                $scope.$apply(function() {
-                    var form = elem.closest('form');
-                    if (form && form.attr('name')) {
-                        form.find('.ng-valid').removeClass('error');
-                        form.find('.ng-invalid').removeClass('error');
-                        $scope['reset']();
-                    }
-                })
-            })
-        }
-    }
-});
-
-module.directive('kcCancel', function ($compile, Notifications) {
-    return {
-        restrict: 'A',
-        link: function ($scope, elem, attr, ctrl) {
-            elem.addClass("btn btn-default");
-            elem.attr("type","submit");
-        }
-    }
-});
-
-module.directive('kcDelete', function ($compile, Notifications) {
-    return {
-        restrict: 'A',
-        link: function ($scope, elem, attr, ctrl) {
-            elem.addClass("btn btn-danger");
-            elem.attr("type","submit");
-        }
-    }
-});
-
-
-module.directive('kcDropdown', function ($compile, Notifications) {
-    return {
-        scope: {
-            kcOptions: '=',
-            kcModel: '=',
-            id: "=",
-            kcPlaceholder: '@'
-        },
-        restrict: 'EA',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-select.html',
-        link: function(scope, element, attr) {
-            scope.updateModel = function(item) {
-                scope.kcModel = item;
-            };
-        }
-    }
-});
-
-module.directive('kcReadOnly', function() {
-    var disabled = {};
-
-    var d = {
-        replace : false,
-        link : function(scope, element, attrs) {
-            var disable = function(i, e) {
-                if (!e.disabled) {
-                    disabled[e.tagName + i] = true;
-                    e.disabled = true;
-                }
-            }
-
-            var enable = function(i, e) {
-                if (disabled[e.tagName + i]) {
-                    e.disabled = false;
-                    delete disabled[i];
-                }
-            }
-
-            scope.$watch(attrs.kcReadOnly, function(readOnly) {
-                if (readOnly) {
-                    element.find('input').each(disable);
-                    element.find('button').each(disable);
-                    element.find('select').each(disable);
-                    element.find('textarea').each(disable);
-                } else {
-                    element.find('input').each(enable);
-                    element.find('input').each(enable);
-                    element.find('button').each(enable);
-                    element.find('select').each(enable);
-                    element.find('textarea').each(enable);
-                }
-            });
-        }
-    };
-    return d;
-});
-
-module.directive('kcMenu', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-menu.html'
-    }
-});
-
-module.directive('kcTabsRealm', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-tabs-realm.html'
-    }
-});
-
-module.directive('kcTabsAuthentication', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-tabs-authentication.html'
-    }
-});
-
-module.directive('kcTabsUser', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-tabs-user.html'
-    }
-});
-
-module.directive('kcTabsClient', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-tabs-client.html'
-    }
-});
-
-module.directive('kcNavigationUser', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-navigation-user.html'
-    }
-});
-
-module.controller('RoleSelectorModalCtrl', function($scope, realm, config, configName, RealmRoles, Client, ClientRole, $modalInstance) {
-    console.log('realm: ' + realm.realm);
-    $scope.selectedRealmRole = {
-        role: undefined
-    };
-    $scope.selectedClientRole = {
-        role: undefined
-    };
-    $scope.client = {
-        selected: undefined
-    };
-
-    $scope.selectRealmRole = function() {
-        config[configName] = $scope.selectedRealmRole.role.name;
-        $modalInstance.close();
-    }
-
-    $scope.selectClientRole = function() {
-        config[configName] = $scope.client.selected.clientId + "." + $scope.selectedClientRole.role.name;
-        $modalInstance.close();
-    }
-
-    $scope.cancel = function() {
-        $modalInstance.dismiss();
-    }
-
-    $scope.changeClient = function() {
-        if ($scope.client.selected) {
-            ClientRole.query({realm: realm.realm, client: $scope.client.selected.id}, function (data) {
-                $scope.clientRoles = data;
-             });
-        } else {
-            console.log('selected client was null');
-            $scope.clientRoles = null;
-        }
-
-    }
-    RealmRoles.query({realm: realm.realm}, function(data) {
-        $scope.realmRoles = data;
-    })
-    Client.query({realm: realm.realm}, function(data) {
-        $scope.clients = data;
-        if (data.length > 0) {
-            $scope.client.selected = data[0];
-            $scope.changeClient();
-        }
-    })
-});
-
-
-module.directive('kcProviderConfig', function ($modal) {
-    return {
-        scope: {
-            config: '=',
-            properties: '=',
-            realm: '=',
-            clients: '='
-        },
-        restrict: 'E',
-        replace: true,
-        link: function(scope, element, attrs) {
-            scope.openRoleSelector = function(configName) {
-                $modal.open({
-                    templateUrl: resourceUrl + '/partials/modal/role-selector.html',
-                    controller: 'RoleSelectorModalCtrl',
-                    resolve: {
-                        realm: function () {
-                            return scope.realm;
-                        },
-                        config: function() {
-                            return scope.config;
-                        },
-                        configName: function() {
-
-                            return configName;
-                        }
-                    }
-                })
-
-            };
-
-        },
-        templateUrl: resourceUrl + '/templates/kc-provider-config.html'
-    }
-});
-
-/*
-*  Used to select the element (invoke $(elem).select()) on specified action list.
-*  Usages kc-select-action="click mouseover"
-*  When used in the textarea element, this will select/highlight the textarea content on specified action (i.e. click).
-*/
-module.directive('kcSelectAction', function ($compile, Notifications) {
-    return {
-        restrict: 'A',
-        compile: function (elem, attrs) {
-
-            var events = attrs.kcSelectAction.split(" ");
-
-            for(var i=0; i < events.length; i++){
-
-                elem.bind(events[i], function(){
-                    elem.select();
-                });
-            }
-        }
-    }
-});
-
-module.filter('remove', function() {
-    return function(input, remove, attribute) {
-        if (!input || !remove) {
-            return input;
-        }
-
-        var out = [];
-        for ( var i = 0; i < input.length; i++) {
-            var e = input[i];
-
-            if (Array.isArray(remove)) {
-                for (var j = 0; j < remove.length; j++) {
-                    if (attribute) {
-                        if (remove[j][attribute] == e[attribute]) {
-                            e = null;
-                            break;
-                        }
-                    } else {
-                        if (remove[j] == e) {
-                            e = null;
-                            break;
-                        }
-                    }
-                }
-            } else {
-                if (attribute) {
-                    if (remove[attribute] == e[attribute]) {
-                        e = null;
-                    }
-                } else {
-                    if (remove == e) {
-                        e = null;
-                    }
-                }
-            }
-
-            if (e != null) {
-                out.push(e);
-            }
-        }
-
-        return out;
-    };
-});
-
-module.filter('capitalize', function() {
-    return function(input) {
-        if (!input) {
-            return;
-        }
-        var result = input.substring(0, 1).toUpperCase();
-        var s = input.substring(1);
-        for (var i=0; i<s.length ; i++) {
-            var c = s[i];
-            if (c.match(/[A-Z]/)) {
-                result = result.concat(" ")
-            };
-            result = result.concat(c);
-        };
-        return result;
-    };
-});
-
-module.directive('kcSidebarResize', function ($window) {
-    return function (scope, element) {
-        function resize() {
-            var navBar = angular.element(document.getElementsByClassName('navbar-pf')).height();
-            var container = angular.element(document.getElementById("view").getElementsByTagName("div")[0]).height();
-            var height = Math.max(container, window.innerHeight - navBar - 3);
-
-            element[0].style['min-height'] = height + 'px';
-        }
-
-        resize();
-
-        var w = angular.element($window);
-        scope.$watch(function () {
-            return {
-                'h': window.innerHeight,
-                'w': window.innerWidth
-            };
-        }, function () {
-            resize();
-        }, true);
-        w.bind('resize', function () {
-            scope.$apply();
-        });
-    }
-});
-
-
-
-module.directive('kcTooltip', function($compile) {
-        return {
-            restrict: 'E',
-            replace: false,
-            terminal: true,
-            priority: 1000,
-            link: function link(scope,element, attrs) {
-                var angularElement = angular.element(element[0]);
-                var tooltip = angularElement.text();
-                angularElement.text('');
-                element.addClass('hidden');
-
-                var label = angular.element(element.parent().children()[0]);
-                label.append(' <i class="fa fa-question-circle text-muted" tooltip="' + tooltip + '" tooltip-placement="right"></i>');
-
-                $compile(label)(scope);
-            }
-        };
+'use strict';
+
+var consoleBaseUrl = window.location.href;
+consoleBaseUrl = consoleBaseUrl.substring(0, consoleBaseUrl.indexOf("/console"));
+consoleBaseUrl = consoleBaseUrl + "/console";
+var configUrl = consoleBaseUrl + "/config";
+
+var auth = {};
+
+var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders', 'ui.bootstrap', 'ui.select2', 'angularFileUpload' ]);
+var resourceRequests = 0;
+var loadingTimer = -1;
+
+angular.element(document).ready(function () {
+    var keycloakAuth = new Keycloak(configUrl);
+
+    keycloakAuth.onAuthLogout = function() {
+        location.reload();
+    }
+
+    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
+        auth.authz = keycloakAuth;
+        module.factory('Auth', function() {
+            return auth;
+        });
+        angular.bootstrap(document, ["keycloak"]);
+    }).error(function () {
+        window.location.reload();
+    });
+});
+
+module.factory('authInterceptor', function($q, Auth) {
+    return {
+        request: function (config) {
+            if (!config.url.match(/.html$/)) {
+                var deferred = $q.defer();
+                if (Auth.authz.token) {
+                    Auth.authz.updateToken(5).success(function () {
+                        config.headers = config.headers || {};
+                        config.headers.Authorization = 'Bearer ' + Auth.authz.token;
+
+                        deferred.resolve(config);
+                    }).error(function () {
+                        location.reload();
+                    });
+                }
+                return deferred.promise;
+            } else {
+                return config;
+            }
+        }
+    };
+});
+
+
+
+
+module.config([ '$routeProvider', function($routeProvider) {
+    $routeProvider
+        .when('/create/realm', {
+            templateUrl : resourceUrl + '/partials/realm-create.html',
+            resolve : {
+
+            },
+            controller : 'RealmCreateCtrl'
+        })
+        .when('/realms/:realm', {
+            templateUrl : resourceUrl + '/partials/realm-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmDetailCtrl'
+        })
+        .when('/realms/:realm/login-settings', {
+            templateUrl : resourceUrl + '/partials/realm-login-settings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmLoginSettingsCtrl'
+        })
+        .when('/realms/:realm/theme-settings', {
+            templateUrl : resourceUrl + '/partials/realm-theme-settings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmThemeCtrl'
+        })
+        .when('/realms/:realm/cache-settings', {
+            templateUrl : resourceUrl + '/partials/realm-cache-settings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmCacheCtrl'
+        })
+        .when('/realms', {
+            templateUrl : resourceUrl + '/partials/realm-list.html',
+            controller : 'RealmListCtrl'
+        })
+        .when('/realms/:realm/token-settings', {
+            templateUrl : resourceUrl + '/partials/realm-tokens.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmTokenDetailCtrl'
+        })
+        .when('/realms/:realm/keys-settings', {
+            templateUrl : resourceUrl + '/partials/realm-keys.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmKeysDetailCtrl'
+        })
+        .when('/realms/:realm/identity-provider-settings', {
+            templateUrl : resourceUrl + '/partials/realm-identity-provider.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                instance : function(IdentityProviderLoader) {
+                    return {};
+                },
+                providerFactory : function(IdentityProviderFactoryLoader) {
+                    return {};
+                }
+            },
+            controller : 'RealmIdentityProviderCtrl'
+        })
+        .when('/create/identity-provider/:realm/:provider_id', {
+            templateUrl : function(params){ return resourceUrl + '/partials/realm-identity-provider-' + params.provider_id + '.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                instance : function(IdentityProviderLoader) {
+                    return {};
+                },
+                providerFactory : function(IdentityProviderFactoryLoader) {
+                    return new IdentityProviderFactoryLoader();
+                }
+            },
+            controller : 'RealmIdentityProviderCtrl'
+        })
+        .when('/realms/:realm/identity-provider-settings/provider/:provider_id/:alias', {
+            templateUrl : function(params){ return resourceUrl + '/partials/realm-identity-provider-' + params.provider_id + '.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                instance : function(IdentityProviderLoader) {
+                    return IdentityProviderLoader();
+                },
+                providerFactory : function(IdentityProviderFactoryLoader) {
+                    return IdentityProviderFactoryLoader();
+                }
+            },
+            controller : 'RealmIdentityProviderCtrl'
+        })
+        .when('/realms/:realm/identity-provider-settings/provider/:provider_id/:alias/export', {
+            templateUrl : resourceUrl + '/partials/realm-identity-provider-export.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                identityProvider : function(IdentityProviderLoader) {
+                    return IdentityProviderLoader();
+                },
+                providerFactory : function(IdentityProviderFactoryLoader) {
+                    return IdentityProviderFactoryLoader();
+                }
+            },
+            controller : 'RealmIdentityProviderExportCtrl'
+        })
+        .when('/realms/:realm/identity-provider-mappers/:alias/mappers', {
+            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mappers.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                identityProvider : function(IdentityProviderLoader) {
+                    return IdentityProviderLoader();
+                },
+                mapperTypes : function(IdentityProviderMapperTypesLoader) {
+                    return IdentityProviderMapperTypesLoader();
+                },
+                mappers : function(IdentityProviderMappersLoader) {
+                    return IdentityProviderMappersLoader();
+                }
+            },
+            controller : 'IdentityProviderMapperListCtrl'
+        })
+        .when('/realms/:realm/identity-provider-mappers/:alias/mappers/:mapperId', {
+            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mapper-detail.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                identityProvider : function(IdentityProviderLoader) {
+                    return IdentityProviderLoader();
+                },
+                mapperTypes : function(IdentityProviderMapperTypesLoader) {
+                    return IdentityProviderMapperTypesLoader();
+                },
+                mapper : function(IdentityProviderMapperLoader) {
+                    return IdentityProviderMapperLoader();
+                }
+            },
+            controller : 'IdentityProviderMapperCtrl'
+        })
+        .when('/create/identity-provider-mappers/:realm/:alias', {
+            templateUrl : function(params){ return resourceUrl + '/partials/identity-provider-mapper-detail.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                identityProvider : function(IdentityProviderLoader) {
+                    return IdentityProviderLoader();
+                },
+                mapperTypes : function(IdentityProviderMapperTypesLoader) {
+                    return IdentityProviderMapperTypesLoader();
+                }
+            },
+            controller : 'IdentityProviderMapperCreateCtrl'
+        })
+
+        .when('/realms/:realm/default-roles', {
+            templateUrl : resourceUrl + '/partials/realm-default-roles.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                }
+            },
+            controller : 'RealmDefaultRolesCtrl'
+        })
+        .when('/realms/:realm/smtp-settings', {
+            templateUrl : resourceUrl + '/partials/realm-smtp.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmSMTPSettingsCtrl'
+        })
+        .when('/realms/:realm/events', {
+            templateUrl : resourceUrl + '/partials/realm-events.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmEventsCtrl'
+        })
+        .when('/realms/:realm/admin-events', {
+            templateUrl : resourceUrl + '/partials/realm-events-admin.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmAdminEventsCtrl'
+        })
+        .when('/realms/:realm/events-settings', {
+            templateUrl : resourceUrl + '/partials/realm-events-config.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                eventsConfig : function(RealmEventsConfigLoader) {
+                    return RealmEventsConfigLoader();
+                }
+            },
+            controller : 'RealmEventsConfigCtrl'
+        })
+        .when('/create/user/:realm', {
+            templateUrl : resourceUrl + '/partials/user-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function() {
+                    return {};
+                }
+            },
+            controller : 'UserDetailCtrl'
+        })
+        .when('/realms/:realm/users/:user', {
+            templateUrl : resourceUrl + '/partials/user-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                }
+            },
+            controller : 'UserDetailCtrl'
+        })
+        .when('/realms/:realm/users/:user/user-credentials', {
+            templateUrl : resourceUrl + '/partials/user-credentials.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                }
+            },
+            controller : 'UserCredentialsCtrl'
+        })
+        .when('/realms/:realm/users/:user/role-mappings', {
+            templateUrl : resourceUrl + '/partials/role-mappings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'UserRoleMappingCtrl'
+        })
+        .when('/realms/:realm/users/:user/sessions', {
+            templateUrl : resourceUrl + '/partials/user-sessions.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                },
+                sessions : function(UserSessionsLoader) {
+                    return UserSessionsLoader();
+                }
+            },
+            controller : 'UserSessionsCtrl'
+        })
+        .when('/realms/:realm/users/:user/federated-identity', {
+            templateUrl : resourceUrl + '/partials/user-federated-identity-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                },
+                federatedIdentities : function(UserFederatedIdentityLoader) {
+                    return UserFederatedIdentityLoader();
+                }
+            },
+            controller : 'UserFederatedIdentityCtrl'
+        })
+        .when('/create/federated-identity/:realm/:user', {
+            templateUrl : resourceUrl + '/partials/user-federated-identity-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                },
+                federatedIdentities : function(UserFederatedIdentityLoader) {
+                    return UserFederatedIdentityLoader();
+                }
+            },
+            controller : 'UserFederatedIdentityAddCtrl'
+        })
+        .when('/realms/:realm/users/:user/consents', {
+            templateUrl : resourceUrl + '/partials/user-consents.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                user : function(UserLoader) {
+                    return UserLoader();
+                },
+                userConsents : function(UserConsentsLoader) {
+                    return UserConsentsLoader();
+                }
+            },
+            controller : 'UserConsentsCtrl'
+        })
+        .when('/realms/:realm/users', {
+            templateUrl : resourceUrl + '/partials/user-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'UserListCtrl'
+        })
+
+        .when('/create/role/:realm', {
+            templateUrl : resourceUrl + '/partials/role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                role : function() {
+                    return {};
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'RoleDetailCtrl'
+        })
+        .when('/realms/:realm/roles/:role', {
+            templateUrl : resourceUrl + '/partials/role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                role : function(RoleLoader) {
+                    return RoleLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'RoleDetailCtrl'
+        })
+        .when('/realms/:realm/roles', {
+            templateUrl : resourceUrl + '/partials/role-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                }
+            },
+            controller : 'RoleListCtrl'
+        })
+
+        .when('/create/role/:realm/clients/:client', {
+            templateUrl : resourceUrl + '/partials/client-role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                role : function() {
+                    return {};
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'ClientRoleDetailCtrl'
+        })
+        .when('/realms/:realm/clients/:client/roles/:role', {
+            templateUrl : resourceUrl + '/partials/client-role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                role : function(ClientRoleLoader) {
+                    return ClientRoleLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'ClientRoleDetailCtrl'
+        })
+        .when('/realms/:realm/clients/:client/mappers', {
+            templateUrl : resourceUrl + '/partials/client-mappers.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'ClientProtocolMapperListCtrl'
+        })
+        .when('/realms/:realm/clients/:client/add-mappers', {
+            templateUrl : resourceUrl + '/partials/client-mappers-add.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'AddBuiltinProtocolMapperCtrl'
+        })
+        .when('/realms/:realm/clients/:client/mappers/:id', {
+            templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                mapper : function(ClientProtocolMapperLoader) {
+                    return ClientProtocolMapperLoader();
+                }
+
+            },
+            controller : 'ClientProtocolMapperCtrl'
+        })
+        .when('/create/client/:realm/:client/mappers', {
+            templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientProtocolMapperCreateCtrl'
+        })
+        .when('/realms/:realm/clients/:client/sessions', {
+            templateUrl : resourceUrl + '/partials/client-sessions.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                sessionCount : function(ClientSessionCountLoader) {
+                    return ClientSessionCountLoader();
+                }
+            },
+            controller : 'ClientSessionsCtrl'
+        })
+        .when('/realms/:realm/clients/:client/credentials', {
+            templateUrl : resourceUrl + '/partials/client-credentials.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientCredentialsCtrl'
+        })
+        .when('/realms/:realm/clients/:client/identity-provider', {
+            templateUrl : resourceUrl + '/partials/client-identity-provider.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientIdentityProviderCtrl'
+        })
+        .when('/realms/:realm/clients/:client/clustering', {
+            templateUrl : resourceUrl + '/partials/client-clustering.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientClusteringCtrl'
+        })
+        .when('/register-node/realms/:realm/clients/:client/clustering', {
+            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientClusteringNodeCtrl'
+        })
+        .when('/realms/:realm/clients/:client/clustering/:node', {
+            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientClusteringNodeCtrl'
+        })
+        .when('/realms/:realm/clients/:client/saml/keys', {
+            templateUrl : resourceUrl + '/partials/client-saml-keys.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientSamlKeyCtrl'
+        })
+        .when('/realms/:realm/clients/:client/saml/:keyType/import/:attribute', {
+            templateUrl : resourceUrl + '/partials/client-saml-key-import.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientCertificateImportCtrl'
+        })
+        .when('/realms/:realm/clients/:client/saml/:keyType/export/:attribute', {
+            templateUrl : resourceUrl + '/partials/client-saml-key-export.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientCertificateExportCtrl'
+        })
+        .when('/realms/:realm/clients/:client/roles', {
+            templateUrl : resourceUrl + '/partials/client-role-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                roles : function(ClientRoleListLoader) {
+                    return ClientRoleListLoader();
+                }
+            },
+            controller : 'ClientRoleListCtrl'
+        })
+        .when('/realms/:realm/clients/:client/revocation', {
+            templateUrl : resourceUrl + '/partials/client-revocation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientRevocationCtrl'
+        })
+        .when('/realms/:realm/clients/:client/scope-mappings', {
+            templateUrl : resourceUrl + '/partials/client-scope-mappings.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'ClientScopeMappingCtrl'
+        })
+        .when('/realms/:realm/clients/:client/installation', {
+            templateUrl : resourceUrl + '/partials/client-installation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientInstallationCtrl'
+        })
+        .when('/create/client/:realm', {
+            templateUrl : resourceUrl + '/partials/client-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                },
+                client : function() {
+                    return {};
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'ClientDetailCtrl'
+        })
+        .when('/realms/:realm/clients/:client', {
+            templateUrl : resourceUrl + '/partials/client-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'ClientDetailCtrl'
+        })
+        .when('/realms/:realm/clients', {
+            templateUrl : resourceUrl + '/partials/client-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+
+            },
+            controller : 'ClientListCtrl'
+        })
+        .when('/import/client/:realm', {
+            templateUrl : resourceUrl + '/partials/client-import.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'ClientImportCtrl'
+        })
+        .when('/', {
+            templateUrl : resourceUrl + '/partials/home.html',
+            controller : 'HomeCtrl'
+        })
+        .when('/mocks/:realm', {
+            templateUrl : resourceUrl + '/partials/realm-detail_mock.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+            },
+            controller : 'RealmDetailCtrl'
+        })
+        .when('/realms/:realm/sessions/revocation', {
+            templateUrl : resourceUrl + '/partials/session-revocation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmRevocationCtrl'
+        })
+         .when('/realms/:realm/sessions/realm', {
+            templateUrl : resourceUrl + '/partials/session-realm.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                stats : function(RealmClientSessionStatsLoader) {
+                    return RealmClientSessionStatsLoader();
+                }
+            },
+            controller : 'RealmSessionStatsCtrl'
+        })
+        .when('/realms/:realm/user-federation', {
+            templateUrl : resourceUrl + '/partials/user-federation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'UserFederationCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/ldap/:instance', {
+            templateUrl : resourceUrl + '/partials/federated-ldap.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                }
+            },
+            controller : 'LDAPCtrl'
+        })
+        .when('/create/user-federation/:realm/providers/ldap', {
+            templateUrl : resourceUrl + '/partials/federated-ldap.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function() {
+                    return {};
+                }
+            },
+            controller : 'LDAPCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/kerberos/:instance', {
+            templateUrl : resourceUrl + '/partials/federated-kerberos.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                },
+                providerFactory : function() {
+                    return { id: "kerberos" };
+                }
+            },
+            controller : 'GenericUserFederationCtrl'
+        })
+        .when('/create/user-federation/:realm/providers/kerberos', {
+            templateUrl : resourceUrl + '/partials/federated-kerberos.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function() {
+                    return {};
+                },
+                providerFactory : function() {
+                    return { id: "kerberos" };
+                }
+            },
+            controller : 'GenericUserFederationCtrl'
+        })
+        .when('/create/user-federation/:realm/providers/:provider', {
+            templateUrl : resourceUrl + '/partials/federated-generic.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function() {
+                    return {
+
+                    };
+                },
+                providerFactory : function(UserFederationFactoryLoader) {
+                    return UserFederationFactoryLoader();
+                }
+            },
+            controller : 'GenericUserFederationCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/:provider/:instance', {
+            templateUrl : resourceUrl + '/partials/federated-generic.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                instance : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                },
+                providerFactory : function(UserFederationFactoryLoader) {
+                    return UserFederationFactoryLoader();
+                }
+            },
+            controller : 'GenericUserFederationCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/:provider/:instance/mappers', {
+            templateUrl : function(params){ return resourceUrl + '/partials/federated-mappers.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                },
+                mapperTypes : function(UserFederationMapperTypesLoader) {
+                    return UserFederationMapperTypesLoader();
+                },
+                mappers : function(UserFederationMappersLoader) {
+                    return UserFederationMappersLoader();
+                }
+            },
+            controller : 'UserFederationMapperListCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/:provider/:instance/mappers/:mapperId', {
+            templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                },
+                mapperTypes : function(UserFederationMapperTypesLoader) {
+                    return UserFederationMapperTypesLoader();
+                },
+                mapper : function(UserFederationMapperLoader) {
+                    return UserFederationMapperLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'UserFederationMapperCtrl'
+        })
+        .when('/create/user-federation-mappers/:realm/:provider/:instance', {
+            templateUrl : function(params){ return resourceUrl + '/partials/federated-mapper-detail.html'; },
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                },
+                mapperTypes : function(UserFederationMapperTypesLoader) {
+                    return UserFederationMapperTypesLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
+                }
+            },
+            controller : 'UserFederationMapperCreateCtrl'
+        })
+
+        .when('/realms/:realm/defense/headers', {
+            templateUrl : resourceUrl + '/partials/defense-headers.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+
+            },
+            controller : 'DefenseHeadersCtrl'
+        })
+        .when('/realms/:realm/defense/brute-force', {
+            templateUrl : resourceUrl + '/partials/brute-force.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmBruteForceCtrl'
+        })
+        .when('/realms/:realm/protocols', {
+            templateUrl : resourceUrl + '/partials/protocol-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                serverInfo : function(ServerInfoLoader) {
+                    return ServerInfoLoader();
+                }
+
+            },
+            controller : 'ProtocolListCtrl'
+        })
+        .when('/realms/:realm/authentication/flows', {
+            templateUrl : resourceUrl + '/partials/authentication-flows.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                flows : function(AuthenticationFlowsLoader) {
+                    return AuthenticationFlowsLoader();
+                }
+            },
+            controller : 'AuthenticationFlowsCtrl'
+        })
+        .when('/realms/:realm/authentication/required-actions', {
+            templateUrl : resourceUrl + '/partials/required-actions.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RequiredActionsCtrl'
+        })
+        .when('/realms/:realm/authentication/password-policy', {
+            templateUrl : resourceUrl + '/partials/password-policy.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'RealmPasswordPolicyCtrl'
+        })
+        .when('/realms/:realm/authentication/config/:provider/:config', {
+            templateUrl : resourceUrl + '/partials/authenticator-config.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                configType : function(AuthenticationConfigDescriptionLoader) {
+                    return AuthenticationConfigDescriptionLoader();
+                },
+                config : function(AuthenticationConfigLoader) {
+                    return AuthenticationConfigLoader();
+                }
+            },
+            controller : 'AuthenticationConfigCtrl'
+        })
+        .when('/create/authentication/:realm/execution/:executionId/provider/:provider', {
+            templateUrl : resourceUrl + '/partials/authenticator-config.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                configType : function(AuthenticationConfigDescriptionLoader) {
+                    return AuthenticationConfigDescriptionLoader();
+                },
+                execution : function(ExecutionIdLoader) {
+                    return ExecutionIdLoader();
+                }
+            },
+            controller : 'AuthenticationConfigCreateCtrl'
+        })
+        .when('/server-info', {
+            templateUrl : resourceUrl + '/partials/server-info.html'
+        })
+        .when('/logout', {
+            templateUrl : resourceUrl + '/partials/home.html',
+            controller : 'LogoutCtrl'
+        })
+        .when('/notfound', {
+            templateUrl : resourceUrl + '/partials/notfound.html'
+        })
+        .when('/forbidden', {
+            templateUrl : resourceUrl + '/partials/forbidden.html'
+        })
+        .otherwise({
+            templateUrl : resourceUrl + '/partials/pagenotfound.html'
+        });
+} ]);
+
+module.config(function($httpProvider) {
+    $httpProvider.responseInterceptors.push('errorInterceptor');
+
+    var spinnerFunction = function(data, headersGetter) {
+        if (resourceRequests == 0) {
+            loadingTimer = window.setTimeout(function() {
+                $('#loading').show();
+                loadingTimer = -1;
+            }, 500);
+        }
+        resourceRequests++;
+        return data;
+    };
+    $httpProvider.defaults.transformRequest.push(spinnerFunction);
+
+    $httpProvider.responseInterceptors.push('spinnerInterceptor');
+    $httpProvider.interceptors.push('authInterceptor');
+
+});
+
+module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
+    return function(promise) {
+        return promise.then(function(response) {
+            resourceRequests--;
+            if (resourceRequests == 0) {
+                if(loadingTimer != -1) {
+                    window.clearTimeout(loadingTimer);
+                    loadingTimer = -1;
+                }
+                $('#loading').hide();
+            }
+            return response;
+        }, function(response) {
+            resourceRequests--;
+            if (resourceRequests == 0) {
+                if(loadingTimer != -1) {
+                    window.clearTimeout(loadingTimer);
+                    loadingTimer = -1;
+                }
+                $('#loading').hide();
+            }
+
+            return $q.reject(response);
+        });
+    };
+});
+
+module.factory('errorInterceptor', function($q, $window, $rootScope, $location, Notifications, Auth) {
+    return function(promise) {
+        return promise.then(function(response) {
+            return response;
+        }, function(response) {
+            if (response.status == 401) {
+                Auth.authz.logout();
+            } else if (response.status == 403) {
+                $location.path('/forbidden');
+            } else if (response.status == 404) {
+                $location.path('/notfound');
+            } else if (response.status) {
+                if (response.data && response.data.errorMessage) {
+                    Notifications.error(response.data.errorMessage);
+                } else {
+                    Notifications.error("An unexpected server error has occurred");
+                }
+            }
+            return $q.reject(response);
+        });
+    };
+});
+
+// collapsable form fieldsets
+module.directive('collapsable', function() {
+    return function(scope, element, attrs) {
+        element.click(function() {
+            $(this).toggleClass('collapsed');
+            $(this).find('.toggle-icons').toggleClass('kc-icon-collapse').toggleClass('kc-icon-expand');
+            $(this).find('.toggle-icons').text($(this).text() == "Icon: expand" ? "Icon: collapse" : "Icon: expand");
+            $(this).parent().find('.form-group').toggleClass('hidden');
+        });
+    }
+});
+
+// collapsable form fieldsets
+module.directive('uncollapsed', function() {
+    return function(scope, element, attrs) {
+        element.prepend('<i class="toggle-class fa fa-angle-down"></i> ');
+        element.click(function() {
+            $(this).find('.toggle-class').toggleClass('fa-angle-down').toggleClass('fa-angle-right');
+            $(this).parent().find('.form-group').toggleClass('hidden');
+        });
+    }
+});
+
+// collapsable form fieldsets
+module.directive('collapsed', function() {
+    return function(scope, element, attrs) {
+        element.prepend('<i class="toggle-class fa fa-angle-right"></i> ');
+        element.parent().find('.form-group').toggleClass('hidden');
+        element.click(function() {
+            $(this).find('.toggle-class').toggleClass('fa-angle-down').toggleClass('fa-angle-right');
+            $(this).parent().find('.form-group').toggleClass('hidden');
+        });
+    }
+});
+
+/**
+ * Directive for presenting an ON-OFF switch for checkbox.
+ * Usage: <input ng-model="mmm" name="nnn" id="iii" onoffswitch [on-text="ooo" off-text="fff"] />
+ */
+module.directive('onoffswitch', function() {
+    return {
+        restrict: "EA",
+        replace: true,
+        scope: {
+            name: '@',
+            id: '@',
+            ngModel: '=',
+            ngDisabled: '=',
+            kcOnText: '@onText',
+            kcOffText: '@offText'
+        },
+        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
+        //templateUrl: "templates/kc-switch.html",
+        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='{{name}}' id='{{id}}'><label for='{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
+        compile: function(element, attrs) {
+            /*
+            We don't want to propagate basic attributes to the root element of directive. Id should be passed to the
+            input element only to achieve proper label binding (and validity).
+            */
+            element.removeAttr('name');
+            element.removeAttr('id');
+
+            if (!attrs.onText) { attrs.onText = "ON"; }
+            if (!attrs.offText) { attrs.offText = "OFF"; }
+
+            element.bind('keydown', function(e){
+                var code = e.keyCode || e.which;
+                if (code === 32 || code === 13) {
+                    e.stopImmediatePropagation();
+                    e.preventDefault();
+                    $(e.target).find('input').click();
+                }
+            });
+        }
+    }
+});
+
+/**
+ * Directive for presenting an ON-OFF switch for checkbox.
+ * This directive provides some additional capabilities to the default onoffswitch such as:
+ *
+ * - Dynamic values for id and name attributes. Useful if you need to use this directive inside a ng-repeat
+ * - Specific scope to specify the value. Instead of just true or false.
+ *
+ * Usage: <input ng-model="mmm" name="nnn" id="iii" kc-onoffswitch-model [on-text="ooo" off-text="fff"] />
+ */
+module.directive('onoffswitchmodel', function() {
+    return {
+        restrict: "EA",
+        replace: true,
+        scope: {
+            name: '=',
+            id: '=',
+            value: '=',
+            ngModel: '=',
+            ngDisabled: '=',
+            kcOnText: '@onText',
+            kcOffText: '@offText'
+        },
+        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
+        //templateUrl: "templates/kc-switch.html",
+        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-true-value='{{value}}' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='kc{{name}}' id='kc{{id}}'><label for='kc{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
+        compile: function(element, attrs) {
+
+            if (!attrs.onText) { attrs.onText = "ON"; }
+            if (!attrs.offText) { attrs.offText = "OFF"; }
+
+            element.bind('keydown click', function(e){
+                var code = e.keyCode || e.which;
+                if (code === 32 || code === 13) {
+                    e.stopImmediatePropagation();
+                    e.preventDefault();
+                    $(e.target).find('input').click();
+                }
+            });
+        }
+    }
+});
+
+/**
+ * Directive for presenting an ON-OFF switch for checkbox.
+ * This directive provides some additional capabilities to the default onoffswitch such as:
+ *
+ * - Specific scope to specify the value. Instead of just true or false.
+ *
+ * Usage: <input ng-model="mmm" name="nnn" id="iii" onoffswitchvalue [on-text="ooo" off-text="fff"] />
+ */
+module.directive('onoffswitchvalue', function() {
+    return {
+        restrict: "EA",
+        replace: true,
+        scope: {
+            name: '@',
+            id: '@',
+            value: '=',
+            ngModel: '=',
+            ngDisabled: '=',
+            kcOnText: '@onText',
+            kcOffText: '@offText'
+        },
+        // TODO - The same code acts differently when put into the templateURL. Find why and move the code there.
+        //templateUrl: "templates/kc-switch.html",
+        template: "<span><div class='onoffswitch' tabindex='0'><input type='checkbox' ng-true-value='{{value}}' ng-model='ngModel' ng-disabled='ngDisabled' class='onoffswitch-checkbox' name='{{name}}' id='{{id}}'><label for='{{id}}' class='onoffswitch-label'><span class='onoffswitch-inner'><span class='onoffswitch-active'>{{kcOnText}}</span><span class='onoffswitch-inactive'>{{kcOffText}}</span></span><span class='onoffswitch-switch'></span></label></div></span>",
+        compile: function(element, attrs) {
+            /*
+             We don't want to propagate basic attributes to the root element of directive. Id should be passed to the
+             input element only to achieve proper label binding (and validity).
+             */
+            element.removeAttr('name');
+            element.removeAttr('id');
+
+            if (!attrs.onText) { attrs.onText = "ON"; }
+            if (!attrs.offText) { attrs.offText = "OFF"; }
+
+            element.bind('keydown', function(e){
+                var code = e.keyCode || e.which;
+                if (code === 32 || code === 13) {
+                    e.stopImmediatePropagation();
+                    e.preventDefault();
+                    $(e.target).find('input').click();
+                }
+            });
+        }
+    }
+});
+
+module.directive('kcInput', function() {
+    var d = {
+        scope : true,
+        replace : false,
+        link : function(scope, element, attrs) {
+            var form = element.children('form');
+            var label = element.children('label');
+            var input = element.children('input');
+
+            var id = form.attr('name') + '.' + input.attr('name');
+
+            element.attr('class', 'control-group');
+
+            label.attr('class', 'control-label');
+            label.attr('for', id);
+
+            input.wrap('<div class="controls"/>');
+            input.attr('id', id);
+
+            if (!input.attr('placeHolder')) {
+                input.attr('placeHolder', label.text());
+            }
+
+            if (input.attr('required')) {
+                label.append(' <span class="required">*</span>');
+            }
+        }
+    };
+    return d;
+});
+
+module.directive('kcEnter', function() {
+    return function(scope, element, attrs) {
+        element.bind("keydown keypress", function(event) {
+            if (event.which === 13) {
+                scope.$apply(function() {
+                    scope.$eval(attrs.kcEnter);
+                });
+
+                event.preventDefault();
+            }
+        });
+    };
+});
+
+module.directive('kcSave', function ($compile, Notifications) {
+    return {
+        restrict: 'A',
+        link: function ($scope, elem, attr, ctrl) {
+            elem.addClass("btn btn-primary");
+            elem.attr("type","submit");
+            elem.bind('click', function() {
+                $scope.$apply(function() {
+                    var form = elem.closest('form');
+                    if (form && form.attr('name')) {
+                        var ngValid = form.find('.ng-valid');
+                        if ($scope[form.attr('name')].$valid) {
+                            //ngValid.removeClass('error');
+                            ngValid.parent().removeClass('has-error');
+                            $scope['save']();
+                        } else {
+                            Notifications.error("Missing or invalid field(s). Please verify the fields in red.")
+                            //ngValid.removeClass('error');
+                            ngValid.parent().removeClass('has-error');
+
+                            var ngInvalid = form.find('.ng-invalid');
+                            //ngInvalid.addClass('error');
+                            ngInvalid.parent().addClass('has-error');
+                        }
+                    }
+                });
+            })
+        }
+    }
+});
+
+module.directive('kcReset', function ($compile, Notifications) {
+    return {
+        restrict: 'A',
+        link: function ($scope, elem, attr, ctrl) {
+            elem.addClass("btn btn-default");
+            elem.attr("type","submit");
+            elem.bind('click', function() {
+                $scope.$apply(function() {
+                    var form = elem.closest('form');
+                    if (form && form.attr('name')) {
+                        form.find('.ng-valid').removeClass('error');
+                        form.find('.ng-invalid').removeClass('error');
+                        $scope['reset']();
+                    }
+                })
+            })
+        }
+    }
+});
+
+module.directive('kcCancel', function ($compile, Notifications) {
+    return {
+        restrict: 'A',
+        link: function ($scope, elem, attr, ctrl) {
+            elem.addClass("btn btn-default");
+            elem.attr("type","submit");
+        }
+    }
+});
+
+module.directive('kcDelete', function ($compile, Notifications) {
+    return {
+        restrict: 'A',
+        link: function ($scope, elem, attr, ctrl) {
+            elem.addClass("btn btn-danger");
+            elem.attr("type","submit");
+        }
+    }
+});
+
+
+module.directive('kcDropdown', function ($compile, Notifications) {
+    return {
+        scope: {
+            kcOptions: '=',
+            kcModel: '=',
+            id: "=",
+            kcPlaceholder: '@'
+        },
+        restrict: 'EA',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-select.html',
+        link: function(scope, element, attr) {
+            scope.updateModel = function(item) {
+                scope.kcModel = item;
+            };
+        }
+    }
+});
+
+module.directive('kcReadOnly', function() {
+    var disabled = {};
+
+    var d = {
+        replace : false,
+        link : function(scope, element, attrs) {
+            var disable = function(i, e) {
+                if (!e.disabled) {
+                    disabled[e.tagName + i] = true;
+                    e.disabled = true;
+                }
+            }
+
+            var enable = function(i, e) {
+                if (disabled[e.tagName + i]) {
+                    e.disabled = false;
+                    delete disabled[i];
+                }
+            }
+
+            scope.$watch(attrs.kcReadOnly, function(readOnly) {
+                if (readOnly) {
+                    element.find('input').each(disable);
+                    element.find('button').each(disable);
+                    element.find('select').each(disable);
+                    element.find('textarea').each(disable);
+                } else {
+                    element.find('input').each(enable);
+                    element.find('input').each(enable);
+                    element.find('button').each(enable);
+                    element.find('select').each(enable);
+                    element.find('textarea').each(enable);
+                }
+            });
+        }
+    };
+    return d;
+});
+
+module.directive('kcMenu', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-menu.html'
+    }
+});
+
+module.directive('kcTabsRealm', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-tabs-realm.html'
+    }
+});
+
+module.directive('kcTabsAuthentication', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-tabs-authentication.html'
+    }
+});
+
+module.directive('kcTabsUser', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-tabs-user.html'
+    }
+});
+
+module.directive('kcTabsClient', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-tabs-client.html'
+    }
+});
+
+module.directive('kcNavigationUser', function () {
+    return {
+        scope: true,
+        restrict: 'E',
+        replace: true,
+        templateUrl: resourceUrl + '/templates/kc-navigation-user.html'
+    }
+});
+
+module.controller('RoleSelectorModalCtrl', function($scope, realm, config, configName, RealmRoles, Client, ClientRole, $modalInstance) {
+    console.log('realm: ' + realm.realm);
+    $scope.selectedRealmRole = {
+        role: undefined
+    };
+    $scope.selectedClientRole = {
+        role: undefined
+    };
+    $scope.client = {
+        selected: undefined
+    };
+
+    $scope.selectRealmRole = function() {
+        config[configName] = $scope.selectedRealmRole.role.name;
+        $modalInstance.close();
+    }
+
+    $scope.selectClientRole = function() {
+        config[configName] = $scope.client.selected.clientId + "." + $scope.selectedClientRole.role.name;
+        $modalInstance.close();
+    }
+
+    $scope.cancel = function() {
+        $modalInstance.dismiss();
+    }
+
+    $scope.changeClient = function() {
+        if ($scope.client.selected) {
+            ClientRole.query({realm: realm.realm, client: $scope.client.selected.id}, function (data) {
+                $scope.clientRoles = data;
+             });
+        } else {
+            console.log('selected client was null');
+            $scope.clientRoles = null;
+        }
+
+    }
+    RealmRoles.query({realm: realm.realm}, function(data) {
+        $scope.realmRoles = data;
+    })
+    Client.query({realm: realm.realm}, function(data) {
+        $scope.clients = data;
+        if (data.length > 0) {
+            $scope.client.selected = data[0];
+            $scope.changeClient();
+        }
+    })
+});
+
+
+module.directive('kcProviderConfig', function ($modal) {
+    return {
+        scope: {
+            config: '=',
+            properties: '=',
+            realm: '=',
+            clients: '='
+        },
+        restrict: 'E',
+        replace: true,
+        link: function(scope, element, attrs) {
+            scope.openRoleSelector = function(configName) {
+                $modal.open({
+                    templateUrl: resourceUrl + '/partials/modal/role-selector.html',
+                    controller: 'RoleSelectorModalCtrl',
+                    resolve: {
+                        realm: function () {
+                            return scope.realm;
+                        },
+                        config: function() {
+                            return scope.config;
+                        },
+                        configName: function() {
+
+                            return configName;
+                        }
+                    }
+                })
+
+            };
+
+        },
+        templateUrl: resourceUrl + '/templates/kc-provider-config.html'
+    }
+});
+
+/*
+*  Used to select the element (invoke $(elem).select()) on specified action list.
+*  Usages kc-select-action="click mouseover"
+*  When used in the textarea element, this will select/highlight the textarea content on specified action (i.e. click).
+*/
+module.directive('kcSelectAction', function ($compile, Notifications) {
+    return {
+        restrict: 'A',
+        compile: function (elem, attrs) {
+
+            var events = attrs.kcSelectAction.split(" ");
+
+            for(var i=0; i < events.length; i++){
+
+                elem.bind(events[i], function(){
+                    elem.select();
+                });
+            }
+        }
+    }
+});
+
+module.filter('remove', function() {
+    return function(input, remove, attribute) {
+        if (!input || !remove) {
+            return input;
+        }
+
+        var out = [];
+        for ( var i = 0; i < input.length; i++) {
+            var e = input[i];
+
+            if (Array.isArray(remove)) {
+                for (var j = 0; j < remove.length; j++) {
+                    if (attribute) {
+                        if (remove[j][attribute] == e[attribute]) {
+                            e = null;
+                            break;
+                        }
+                    } else {
+                        if (remove[j] == e) {
+                            e = null;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                if (attribute) {
+                    if (remove[attribute] == e[attribute]) {
+                        e = null;
+                    }
+                } else {
+                    if (remove == e) {
+                        e = null;
+                    }
+                }
+            }
+
+            if (e != null) {
+                out.push(e);
+            }
+        }
+
+        return out;
+    };
+});
+
+module.filter('capitalize', function() {
+    return function(input) {
+        if (!input) {
+            return;
+        }
+        var result = input.substring(0, 1).toUpperCase();
+        var s = input.substring(1);
+        for (var i=0; i<s.length ; i++) {
+            var c = s[i];
+            if (c.match(/[A-Z]/)) {
+                result = result.concat(" ")
+            };
+            result = result.concat(c);
+        };
+        return result;
+    };
+});
+
+module.directive('kcSidebarResize', function ($window) {
+    return function (scope, element) {
+        function resize() {
+            var navBar = angular.element(document.getElementsByClassName('navbar-pf')).height();
+            var container = angular.element(document.getElementById("view").getElementsByTagName("div")[0]).height();
+            var height = Math.max(container, window.innerHeight - navBar - 3);
+
+            element[0].style['min-height'] = height + 'px';
+        }
+
+        resize();
+
+        var w = angular.element($window);
+        scope.$watch(function () {
+            return {
+                'h': window.innerHeight,
+                'w': window.innerWidth
+            };
+        }, function () {
+            resize();
+        }, true);
+        w.bind('resize', function () {
+            scope.$apply();
+        });
+    }
+});
+
+
+
+module.directive('kcTooltip', function($compile) {
+        return {
+            restrict: 'E',
+            replace: false,
+            terminal: true,
+            priority: 1000,
+            link: function link(scope,element, attrs) {
+                var angularElement = angular.element(element[0]);
+                var tooltip = angularElement.text();
+                angularElement.text('');
+                element.addClass('hidden');
+
+                var label = angular.element(element.parent().children()[0]);
+                label.append(' <i class="fa fa-question-circle text-muted" tooltip="' + tooltip + '" tooltip-placement="right"></i>');
+
+                $compile(label)(scope);
+            }
+        };
 });
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 2699138..5b3ddde 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -1,1303 +1,1303 @@
-Array.prototype.remove = function(from, to) {
-    var rest = this.slice((to || from) + 1 || this.length);
-    this.length = from < 0 ? this.length + from : from;
-    return this.push.apply(this, rest);
-};
-
-module.controller('ClientRoleListCtrl', function($scope, $location, realm, client, roles) {
-    $scope.realm = realm;
-    $scope.roles = roles;
-    $scope.client = client;
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientCredentialsCtrl', function($scope, $location, realm, client, ClientCredentials, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-    var secret = ClientCredentials.get({ realm : realm.realm, client : client.id },
-        function() {
-            $scope.secret = secret.value;
-        }
-    );
-
-    $scope.changePassword = function() {
-        var secret = ClientCredentials.update({ realm : realm.realm, client : client.id },
-            function() {
-                Notifications.success('The secret has been changed.');
-                $scope.secret = secret.value;
-            },
-            function() {
-                Notifications.error("The secret was not changed due to a problem.");
-                $scope.secret = "error";
-            }
-        );
-    };
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientIdentityProviderCtrl', function($scope, $location, $route, realm, client, Client, $location, Notifications) {
-    $scope.realm = realm;
-    $scope.client = angular.copy(client);
-    var length = 0;
-
-    if ($scope.client.identityProviders) {
-        length = $scope.client.identityProviders.length;
-
-        for (i = 0; i < $scope.client.identityProviders.length; i++) {
-            var clientProvider = $scope.client.identityProviders[i];
-            if (clientProvider.retrieveToken) {
-                clientProvider.retrieveToken = clientProvider.retrieveToken.toString();
-            }
-        }
-
-    } else {
-        $scope.client.identityProviders = [];
-    }
-
-    $scope.identityProviders = [];
-    var providersMissingInClient = [];
-
-    for (j = 0; j < realm.identityProviders.length; j++) {
-        var identityProvider = realm.identityProviders[j];
-        var clientProvider = null;
-
-        for (i = 0; i < $scope.client.identityProviders.length; i++) {
-            clientProvider = $scope.client.identityProviders[i];
-
-            if (clientProvider) {
-
-                if (clientProvider.id == identityProvider.id) {
-                    $scope.identityProviders[i] = {};
-                    $scope.identityProviders[i].identityProvider = identityProvider;
-                    $scope.identityProviders[i].retrieveToken = clientProvider.retrieveToken;
-                    break;
-                }
-
-                clientProvider = null;
-            }
-        }
-
-        if (clientProvider == null) {
-            providersMissingInClient.push(identityProvider);
-        }
-    }
-
-    for (j = 0; j < providersMissingInClient.length; j++) {
-        var identityProvider = providersMissingInClient[j];
-
-        var currentProvider = {};
-        currentProvider.identityProvider = identityProvider;
-        currentProvider.retrieveToken = "false";
-        $scope.identityProviders.push(currentProvider);
-
-        var currentClientProvider = {};
-        currentClientProvider.id = identityProvider.id;
-        currentClientProvider.retrieveToken = "false";
-        $scope.client.identityProviders.push(currentClientProvider);
-    }
-
-    var oldCopy = angular.copy($scope.client);
-
-    $scope.save = function() {
-
-        Client.update({
-            realm : realm.realm,
-            client : client.id
-        }, $scope.client, function() {
-            $scope.changed = false;
-            $route.reload();
-            Notifications.success("Your changes have been saved to the client.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.client = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-
-    $scope.$watch('client', function() {
-        if (!angular.equals($scope.client, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-});
-
-module.controller('ClientSamlKeyCtrl', function($scope, $location, $http, $upload, realm, client,
-                                                         ClientCertificate, ClientCertificateGenerate,
-                                                         ClientCertificateDownload, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-
-    var signingKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.signing' },
-        function() {
-            $scope.signingKeyInfo = signingKeyInfo;
-        }
-    );
-
-    $scope.generateSigningKey = function() {
-        var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.signing' },
-            function() {
-                Notifications.success('Signing key has been regenerated.');
-                $scope.signingKeyInfo = keyInfo;
-            },
-            function() {
-                Notifications.error("Signing key was not regenerated.");
-            }
-        );
-    };
-
-    $scope.importSigningKey = function() {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/import/saml.signing");
-    };
-
-    $scope.exportSigningKey = function() {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/export/saml.signing");
-    };
-
-    var encryptionKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' },
-        function() {
-            $scope.encryptionKeyInfo = encryptionKeyInfo;
-        }
-    );
-
-    $scope.generateEncryptionKey = function() {
-        var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' },
-            function() {
-                Notifications.success('Encryption key has been regenerated.');
-                $scope.encryptionKeyInfo = keyInfo;
-            },
-            function() {
-                Notifications.error("Encryption key was not regenerated.");
-            }
-        );
-    };
-
-    $scope.importEncryptionKey = function() {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/import/saml.encryption");
-    };
-
-    $scope.exportEncryptionKey = function() {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/export/saml.encryption");
-    };
-
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientCertificateImportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams,
-                                                         ClientCertificate, ClientCertificateGenerate,
-                                                         ClientCertificateDownload, Notifications) {
-
-    var keyType = $routeParams.keyType;
-    var attribute = $routeParams.attribute;
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.keyType = keyType;
-
-    $scope.files = [];
-
-    $scope.onFileSelect = function($files) {
-        $scope.files = $files;
-    };
-
-    $scope.clearFileSelect = function() {
-        $scope.files = null;
-    }
-
-    $scope.keyFormats = [
-        "JKS",
-        "PKCS12"
-    ];
-
-    $scope.uploadKeyFormat = $scope.keyFormats[0];
-
-    $scope.uploadFile = function() {
-        //$files: an array of files selected, each file has name, size, and type.
-        for (var i = 0; i < $scope.files.length; i++) {
-            var $file = $scope.files[i];
-            $scope.upload = $upload.upload({
-                url: authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/certificates/' + attribute + '/upload',
-                // method: POST or PUT,
-                // headers: {'headerKey': 'headerValue'}, withCredential: true,
-                data: {keystoreFormat: $scope.uploadKeyFormat,
-                    keyAlias: $scope.uploadKeyAlias,
-                    keyPassword: $scope.uploadKeyPassword,
-                    storePassword: $scope.uploadStorePassword
-                },
-                file: $file
-                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
-                //fileFormDataName: myFile,
-                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
-                //formDataAppender: function(formData, key, val){}
-            }).success(function(data, status, headers) {
-                Notifications.success("Keystore uploaded successfully.");
-                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/keys");
-            })
-                .error(function() {
-                    Notifications.error("The key store can not be uploaded. Please verify the file.");
-
-                });
-            //.then(success, error, progress);
-        }
-    };
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientCertificateExportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams,
-                                                         ClientCertificate, ClientCertificateGenerate,
-                                                         ClientCertificateDownload, Notifications) {
-    var keyType = $routeParams.keyType;
-    var attribute = $routeParams.attribute;
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.keyType = keyType;
-    var jks = {
-        keyAlias: client.clientId,
-        realmAlias: realm.realm
-    };
-
-    $scope.keyFormats = [
-        "JKS",
-        "PKCS12"
-    ];
-
-    var keyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: attribute },
-        function() {
-            $scope.keyInfo = keyInfo;
-        }
-    );
-    $scope.jks = jks;
-    $scope.jks.format = $scope.keyFormats[0];
-
-    $scope.download = function() {
-        $http({
-            url: authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/certificates/' + attribute + '/download',
-            method: 'POST',
-            responseType: 'arraybuffer',
-            data: $scope.jks,
-            headers: {
-                'Content-Type': 'application/json',
-                'Accept': 'client/octet-stream'
-            }
-        }).success(function(data){
-            var blob = new Blob([data], {
-                type: 'client/octet-stream'
-            });
-            var ext = ".jks";
-            if ($scope.jks.format == 'PKCS12') ext = ".p12";
-            saveAs(blob, 'keystore' + ext);
-        }).error(function(){
-            Notifications.error("Error downloading.");
-        });
-    }
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientSessionsCtrl', function($scope, realm, sessionCount, client,
-                                                      ClientUserSessions) {
-    $scope.realm = realm;
-    $scope.count = sessionCount.count;
-    $scope.sessions = [];
-    $scope.client = client;
-
-    $scope.page = 0;
-
-    $scope.query = {
-        realm : realm.realm,
-        client: $scope.client.id,
-        max : 5,
-        first : 0
-    }
-
-    $scope.firstPage = function() {
-        $scope.query.first = 0;
-        if ($scope.query.first < 0) {
-            $scope.query.first = 0;
-        }
-        $scope.loadUsers();
-    }
-
-    $scope.previousPage = function() {
-        $scope.query.first -= parseInt($scope.query.max);
-        if ($scope.query.first < 0) {
-            $scope.query.first = 0;
-        }
-        $scope.loadUsers();
-    }
-
-    $scope.nextPage = function() {
-        $scope.query.first += parseInt($scope.query.max);
-        $scope.loadUsers();
-    }
-
-    $scope.toDate = function(val) {
-        return new Date(val);
-    };
-
-    $scope.loadUsers = function() {
-        ClientUserSessions.query($scope.query, function(updated) {
-            $scope.sessions = updated;
-        })
-    };
-});
-
-module.controller('ClientRoleDetailCtrl', function($scope, realm, client, role, roles, clients,
-                                                        Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
-                                                        $http, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.role = angular.copy(role);
-    $scope.create = !role.name;
-
-    $scope.changed = $scope.create;
-
-    $scope.save = function() {
-        if ($scope.create) {
-            ClientRole.save({
-                realm: realm.realm,
-                client : client.id
-            }, $scope.role, function (data, headers) {
-                $scope.changed = false;
-                role = angular.copy($scope.role);
-
-                ClientRole.get({ realm: realm.realm, client : client.id, role: role.name }, function(role) {
-                    var id = role.id;
-                    $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles/" + id);
-                    Notifications.success("The role has been created.");
-                });
-            });
-        } else {
-            $scope.update();
-        }
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.role.name, 'role', function() {
-            $scope.role.$remove({
-                realm : realm.realm,
-                client : client.id,
-                role : $scope.role.id
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles");
-                Notifications.success("The role has been deleted.");
-            });
-        });
-    };
-
-    $scope.cancel = function () {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles");
-    };
-
-
-    roleControl($scope, realm, role, roles, clients,
-        ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
-        $http, $location, Notifications, Dialog);
-
-});
-
-module.controller('ClientImportCtrl', function($scope, $location, $upload, realm, serverInfo, Notifications) {
-
-    $scope.realm = realm;
-    $scope.configFormats = serverInfo.clientImporters;
-    $scope.configFormat = null;
-
-    $scope.files = [];
-
-    $scope.onFileSelect = function($files) {
-        $scope.files = $files;
-    };
-
-    $scope.clearFileSelect = function() {
-        $scope.files = null;
-    }
-
-    $scope.uploadFile = function() {
-        //$files: an array of files selected, each file has name, size, and type.
-        for (var i = 0; i < $scope.files.length; i++) {
-            var $file = $scope.files[i];
-            $scope.upload = $upload.upload({
-                url: authUrl + '/admin/realms/' + realm.realm + '/client-importers/' + $scope.configFormat.id + '/upload',
-                // method: POST or PUT,
-                // headers: {'headerKey': 'headerValue'}, withCredential: true,
-                data: {myObj: ""},
-                file: $file
-                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
-                //fileFormDataName: myFile,
-                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
-                //formDataAppender: function(formData, key, val){}
-            }).success(function(data, status, headers) {
-                Notifications.success("Uploaded successfully.");
-                $location.url("/realms/" + realm.realm + "/clients");
-            })
-                .error(function() {
-                    Notifications.error("The file can not be uploaded. Please verify the file.");
-
-                });
-            //.then(success, error, progress);
-        }
-    };
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-
-module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $location) {
-    $scope.realm = realm;
-    $scope.clients = clients;
-    $scope.importButton = serverInfo.clientImporters.length > 0;
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('ClientInstallationCtrl', function($scope, realm, client, ClientInstallation,ClientInstallationJBoss, $http, $routeParams) {
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.installation = null;
-    $scope.download = null;
-    $scope.configFormat = null;
-    $scope.filename = null;
-
-    $scope.configFormats = [
-        "Keycloak JSON",
-        "Wildfly/EAP Subsystem XML"
-    ];
-
-    $scope.changeFormat = function() {
-        if ($scope.configFormat == "Keycloak JSON") {
-            $scope.filename = 'keycloak.json';
-
-            var url = ClientInstallation.url({ realm: $routeParams.realm, client: $routeParams.client });
-            $http.get(url).success(function(data) {
-                var tmp = angular.fromJson(data);
-                $scope.installation = angular.toJson(tmp, true);
-                $scope.type = 'application/json';
-            })
-        } else if ($scope.configFormat == "Wildfly/EAP Subsystem XML") {
-            $scope.filename = 'keycloak.xml';
-
-            var url = ClientInstallationJBoss.url({ realm: $routeParams.realm, client: $routeParams.client });
-            $http.get(url).success(function(data) {
-                $scope.installation = data;
-                $scope.type = 'text/xml';
-            })
-        }
-
-        console.debug($scope.filename);
-    };
-
-    $scope.download = function() {
-        saveAs(new Blob([$scope.installation], { type: $scope.type }), $scope.filename);
-    }
-});
-
-module.controller('ClientDetailCtrl', function($scope, realm, client, $route, serverInfo, Client, $location, Dialog, Notifications) {
-    $scope.accessTypes = [
-        "confidential",
-        "public",
-        "bearer-only"
-    ];
-
-    $scope.protocols = serverInfo.protocols;
-
-    $scope.signatureAlgorithms = [
-        "RSA_SHA1",
-        "RSA_SHA256",
-        "RSA_SHA512",
-        "DSA_SHA1"
-    ];
-    $scope.nameIdFormats = [
-        "username",
-        "email",
-        "transient",
-        "persistent"
-    ];
-
-    $scope.realm = realm;
-    $scope.create = !client.clientId;
-    $scope.samlAuthnStatement = false;
-    $scope.samlMultiValuedRoles = false;
-    $scope.samlServerSignature = false;
-    $scope.samlAssertionSignature = false;
-    $scope.samlClientSignature = false;
-    $scope.samlEncrypt = false;
-    $scope.samlForcePostBinding = false;
-    $scope.samlForceNameIdFormat = false;
-    if (!$scope.create) {
-        if (!client.attributes) {
-            client.attributes = {};
-        }
-        $scope.client= angular.copy(client);
-        $scope.accessType = $scope.accessTypes[0];
-        if (client.bearerOnly) {
-            $scope.accessType = $scope.accessTypes[2];
-        } else if (client.publicClient) {
-            $scope.accessType = $scope.accessTypes[1];
-        }
-        if (client.protocol) {
-            $scope.protocol = $scope.protocols[$scope.protocols.indexOf(client.protocol)];
-        } else {
-            $scope.protocol = $scope.protocols[0];
-        }
-        if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA1') {
-            $scope.signatureAlgorithm = $scope.signatureAlgorithms[0];
-        } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA256') {
-            $scope.signatureAlgorithm = $scope.signatureAlgorithms[1];
-        } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA512') {
-            $scope.signatureAlgorithm = $scope.signatureAlgorithms[2];
-        } else if (client.attributes['saml.signature.algorithm'] == 'DSA_SHA1') {
-            $scope.signatureAlgorithm = $scope.signatureAlgorithms[3];
-        }
-        if (client.attributes['saml_name_id_format'] == 'unspecified') {
-            $scope.nameIdFormat = $scope.nameIdFormats[0];
-        } else if (client.attributes['saml_name_id_format'] == 'email') {
-            $scope.nameIdFormat = $scope.nameIdFormats[1];
-        } else if (client.attributes['saml_name_id_format'] == 'transient') {
-            $scope.nameIdFormat = $scope.nameIdFormats[2];
-        } else if (client.attributes['saml_name_id_format'] == 'persistent') {
-            $scope.nameIdFormat = $scope.nameIdFormats[3];
-        }
-
-    } else {
-        $scope.client = { enabled: true, attributes: {}};
-        $scope.client.redirectUris = [];
-        $scope.accessType = $scope.accessTypes[0];
-        $scope.protocol = $scope.protocols[0];
-        $scope.signatureAlgorithm = $scope.signatureAlgorithms[1];
-        $scope.nameIdFormat = $scope.nameIdFormats[0];
-        $scope.samlAuthnStatement = true;
-        $scope.samlForceNameIdFormat = false;
-    }
-
-    if ($scope.client.attributes["saml.server.signature"]) {
-        if ($scope.client.attributes["saml.server.signature"] == "true") {
-            $scope.samlServerSignature = true;
-        } else {
-            $scope.samlServerSignature = false;
-
-        }
-    }
-    if ($scope.client.attributes["saml.assertion.signature"]) {
-        if ($scope.client.attributes["saml.assertion.signature"] == "true") {
-            $scope.samlAssertionSignature = true;
-        } else {
-            $scope.samlAssertionSignature = false;
-        }
-    }
-    if ($scope.client.attributes["saml.client.signature"]) {
-        if ($scope.client.attributes["saml.client.signature"] == "true") {
-            $scope.samlClientSignature = true;
-        } else {
-            $scope.samlClientSignature = false;
-        }
-    }
-    if ($scope.client.attributes["saml.encrypt"]) {
-        if ($scope.client.attributes["saml.encrypt"] == "true") {
-            $scope.samlEncrypt = true;
-        } else {
-            $scope.samlEncrypt = false;
-        }
-    }
-    if ($scope.client.attributes["saml.authnstatement"]) {
-        if ($scope.client.attributes["saml.authnstatement"] == "true") {
-            $scope.samlAuthnStatement = true;
-        } else {
-            $scope.samlAuthnStatement = false;
-        }
-    }
-    if ($scope.client.attributes["saml_force_name_id_format"]) {
-        if ($scope.client.attributes["saml_force_name_id_format"] == "true") {
-            $scope.samlForceNameIdFormat = true;
-        } else {
-            $scope.samlForceNameIdFormat = false;
-        }
-    }
-    if ($scope.client.attributes["saml.multivalued.roles"]) {
-        if ($scope.client.attributes["saml.multivalued.roles"] == "true") {
-            $scope.samlMultiValuedRoles = true;
-        } else {
-            $scope.samlMultiValuedRoles = false;
-        }
-    }
-    if ($scope.client.attributes["saml.force.post.binding"]) {
-        if ($scope.client.attributes["saml.force.post.binding"] == "true") {
-            $scope.samlForcePostBinding = true;
-        } else {
-            $scope.samlForcePostBinding = false;
-        }
-    }
-
-    $scope.switchChange = function() {
-        $scope.changed = true;
-    }
-
-    $scope.changeAccessType = function() {
-        if ($scope.accessType == "confidential") {
-            $scope.client.bearerOnly = false;
-            $scope.client.publicClient = false;
-        } else if ($scope.accessType == "public") {
-            $scope.client.bearerOnly = false;
-            $scope.client.publicClient = true;
-        } else if ($scope.accessType == "bearer-only") {
-            $scope.client.bearerOnly = true;
-            $scope.client.publicClient = false;
-        }
-    };
-
-    $scope.changeProtocol = function() {
-        if ($scope.protocol == "openid-connect") {
-            $scope.client.protocol = "openid-connect";
-        } else if ($scope.protocol == "saml") {
-            $scope.client.protocol = "saml";
-        }
-    };
-
-    $scope.changeAlgorithm = function() {
-        $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm;
-    };
-
-    $scope.changeNameIdFormat = function() {
-        $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat;
-    };
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    function isChanged() {
-        if (!angular.equals($scope.client, client)) {
-            return true;
-        }
-        if ($scope.newRedirectUri && $scope.newRedirectUri.length > 0) {
-            return true;
-        }
-        if ($scope.newWebOrigin && $scope.newWebOrigin.length > 0) {
-            return true;
-        }
-        return false;
-    }
-
-    $scope.$watch('client', function() {
-        $scope.changed = isChanged();
-    }, true);
-
-    $scope.$watch('newRedirectUri', function() {
-        $scope.changed = isChanged();
-    }, true);
-
-
-    $scope.$watch('newWebOrigin', function() {
-        $scope.changed = isChanged();
-    }, true);
-
-    $scope.deleteWebOrigin = function(index) {
-        $scope.client.webOrigins.splice(index, 1);
-    }
-    $scope.addWebOrigin = function() {
-        $scope.client.webOrigins.push($scope.newWebOrigin);
-        $scope.newWebOrigin = "";
-    }
-    $scope.deleteRedirectUri = function(index) {
-        $scope.client.redirectUris.splice(index, 1);
-    }
-
-    $scope.addRedirectUri = function() {
-        $scope.client.redirectUris.push($scope.newRedirectUri);
-        $scope.newRedirectUri = "";
-    }
-
-    $scope.save = function() {
-        if ($scope.newRedirectUri && $scope.newRedirectUri.length > 0) {
-            $scope.addRedirectUri();
-        }
-
-        if ($scope.newWebOrigin && $scope.newWebOrigin.length > 0) {
-            $scope.addWebOrigin();
-        }
-
-        if ($scope.samlServerSignature == true) {
-            $scope.client.attributes["saml.server.signature"] = "true";
-        } else {
-            $scope.client.attributes["saml.server.signature"] = "false";
-
-        }
-        if ($scope.samlAssertionSignature == true) {
-            $scope.client.attributes["saml.assertion.signature"] = "true";
-        } else {
-            $scope.client.attributes["saml.assertion.signature"] = "false";
-        }
-        if ($scope.samlClientSignature == true) {
-            $scope.client.attributes["saml.client.signature"] = "true";
-        } else {
-            $scope.client.attributes["saml.client.signature"] = "false";
-
-        }
-        if ($scope.samlEncrypt == true) {
-            $scope.client.attributes["saml.encrypt"] = "true";
-        } else {
-            $scope.client.attributes["saml.encrypt"] = "false";
-
-        }
-        if ($scope.samlAuthnStatement == true) {
-            $scope.client.attributes["saml.authnstatement"] = "true";
-        } else {
-            $scope.client.attributes["saml.authnstatement"] = "false";
-
-        }
-        if ($scope.samlForceNameIdFormat == true) {
-            $scope.client.attributes["saml_force_name_id_format"] = "true";
-        } else {
-            $scope.client.attributes["saml_force_name_id_format"] = "false";
-
-        }
-        if ($scope.samlMultiValuedRoles == true) {
-            $scope.client.attributes["saml.multivalued.roles"] = "true";
-        } else {
-            $scope.client.attributes["saml.multivalued.roles"] = "false";
-
-        }
-        if ($scope.samlForcePostBinding == true) {
-            $scope.client.attributes["saml.force.post.binding"] = "true";
-        } else {
-            $scope.client.attributes["saml.force.post.binding"] = "false";
-
-        }
-
-        $scope.client.protocol = $scope.protocol;
-        $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm;
-        $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat;
-
-        if ($scope.client.protocol != 'saml' && !$scope.client.bearerOnly && !$scope.client.directGrantsOnly && (!$scope.client.redirectUris || $scope.client.redirectUris.length == 0)) {
-            Notifications.error("You must specify at least one redirect uri");
-        } else {
-            if ($scope.create) {
-                Client.save({
-                    realm: realm.realm,
-                    client: ''
-                }, $scope.client, function (data, headers) {
-                    $scope.changed = false;
-                    var l = headers().location;
-                    var id = l.substring(l.lastIndexOf("/") + 1);
-                    $location.url("/realms/" + realm.realm + "/clients/" + id);
-                    Notifications.success("The client has been created.");
-                });
-            } else {
-                Client.update({
-                    realm : realm.realm,
-                    client : client.id
-                }, $scope.client, function() {
-                    $scope.changed = false;
-                    client = angular.copy($scope.client);
-                    $location.url("/realms/" + realm.realm + "/clients/" + client.id);
-                    Notifications.success("Your changes have been saved to the client.");
-                });
-            }
-        }
-    };
-
-    $scope.reset = function() {
-        $route.reload();
-    };
-
-    $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/clients");
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.client.clientId, 'client', function() {
-            $scope.client.$remove({
-                realm : realm.realm,
-                client : $scope.client.id
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/clients");
-                Notifications.success("The client has been deleted.");
-            });
-        });
-    };
-
-
-});
-
-module.controller('ClientScopeMappingCtrl', function($scope, $http, realm, client, clients, Notifications,
-                                                          Client,
-                                                          ClientRealmScopeMapping, ClientClientScopeMapping, ClientRole,
-                                                          ClientAvailableRealmScopeMapping, ClientAvailableClientScopeMapping,
-                                                          ClientCompositeRealmScopeMapping, ClientCompositeClientScopeMapping) {
-    $scope.realm = realm;
-    $scope.client = angular.copy(client);
-    $scope.selectedRealmRoles = [];
-    $scope.selectedRealmMappings = [];
-    $scope.realmMappings = [];
-    $scope.clients = clients;
-    $scope.clientRoles = [];
-    $scope.clientComposite = [];
-    $scope.selectedClientRoles = [];
-    $scope.selectedClientMappings = [];
-    $scope.clientMappings = [];
-    $scope.dummymodel = [];
-
-
-    $scope.changeFullScopeAllowed = function() {
-        Client.update({
-            realm : realm.realm,
-            client : client.id
-        }, $scope.client, function() {
-            $scope.changed = false;
-            client = angular.copy($scope.client);
-            updateRealmRoles();
-            Notifications.success("Scope mappings updated.");
-        });
-    }
-
-
-
-    function updateRealmRoles() {
-        $scope.realmRoles = ClientAvailableRealmScopeMapping.query({realm : realm.realm, client : client.id});
-        $scope.realmMappings = ClientRealmScopeMapping.query({realm : realm.realm, client : client.id});
-        $scope.realmComposite = ClientCompositeRealmScopeMapping.query({realm : realm.realm, client : client.id});
-    }
-
-    function updateClientRoles() {
-        if ($scope.targetClient) {
-            $scope.clientRoles = ClientAvailableClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
-            $scope.clientMappings = ClientClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
-            $scope.clientComposite = ClientCompositeClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
-        } else {
-            $scope.clientRoles = null;
-            $scope.clientMappings = null;
-            $scope.clientComposite = null;
-        }
-    }
-
-    $scope.changeClient = function() {
-        updateClientRoles();
-    };
-
-    $scope.addRealmRole = function() {
-        var roles = $scope.selectedRealmRoles;
-        $scope.selectedRealmRoles = [];
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/scope-mappings/realm',
-            roles).success(function() {
-                updateRealmRoles();
-                Notifications.success("Scope mappings updated.");
-            });
-    };
-
-    $scope.deleteRealmRole = function() {
-        var roles = $scope.selectedRealmMappings;
-        $scope.selectedRealmMappings = [];
-        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/realm',
-            {data : roles, headers : {"content-type" : "application/json"}}).success(function () {
-                updateRealmRoles();
-                Notifications.success("Scope mappings updated.");
-            });
-    };
-
-    $scope.addClientRole = function() {
-        var roles = $scope.selectedClientRoles;
-        $scope.selectedClientRoles = [];
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/clients/' + $scope.targetClient.id,
-                roles).success(function () {
-                updateClientRoles();
-                Notifications.success("Scope mappings updated.");
-            });
-    };
-
-    $scope.deleteClientRole = function() {
-        var roles = $scope.selectedClientMappings;
-        $scope.selectedClientMappings = [];
-        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/clients/' + $scope.targetClient.id,
-            {data : roles, headers : {"content-type" : "application/json"}}).success(function () {
-                updateClientRoles();
-                Notifications.success("Scope mappings updated.");
-            });
-    };
-
-    updateRealmRoles();
-});
-
-module.controller('ClientRevocationCtrl', function($scope, realm, client, Client, ClientPushRevocation, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-
-    var setNotBefore = function() {
-        if ($scope.client.notBefore == 0) {
-            $scope.notBefore = "None";
-        } else {
-            $scope.notBefore = new Date($scope.client.notBefore * 1000);
-        }
-    };
-
-    setNotBefore();
-
-    var refresh = function() {
-        Client.get({ realm : realm.realm, client: $scope.client.id }, function(updated) {
-            $scope.client = updated;
-            setNotBefore();
-        })
-
-    };
-
-    $scope.clear = function() {
-        $scope.client.notBefore = 0;
-        Client.update({ realm : realm.realm, client: client.id}, $scope.client, function () {
-            $scope.notBefore = "None";
-            Notifications.success('Not Before cleared for client.');
-            refresh();
-        });
-    }
-    $scope.setNotBeforeNow = function() {
-        $scope.client.notBefore = new Date().getTime()/1000;
-        Client.update({ realm : realm.realm, client: $scope.client.id}, $scope.client, function () {
-            Notifications.success('Not Before set for client.');
-            refresh();
-        });
-    }
-    $scope.pushRevocation = function() {
-        ClientPushRevocation.save({realm : realm.realm, client: $scope.client.id}, function (globalReqResult) {
-            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
-            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
-
-            if (successCount==0 && failedCount==0) {
-                Notifications.warn('No push sent. No admin URI configured or no registered cluster nodes available');
-            } else if (failedCount > 0) {
-                var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
-                Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
-            } else {
-                Notifications.success('Successfully push notBefore to: ' + globalReqResult.successRequests);
-            }
-        });
-    }
-
-});
-
-module.controller('ClientClusteringCtrl', function($scope, client, Client, ClientTestNodesAvailable, realm, $location, $route, Notifications, TimeUnit) {
-    $scope.client = client;
-    $scope.realm = realm;
-
-    var oldCopy = angular.copy($scope.client);
-    $scope.changed = false;
-
-    $scope.$watch('client', function() {
-        if (!angular.equals($scope.client, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.client.nodeReRegistrationTimeoutUnit = TimeUnit.autoUnit(client.nodeReRegistrationTimeout);
-    $scope.client.nodeReRegistrationTimeout = TimeUnit.toUnit(client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit);
-    $scope.$watch('client.nodeReRegistrationTimeoutUnit', function(to, from) {
-        $scope.client.nodeReRegistrationTimeout = TimeUnit.convert($scope.client.nodeReRegistrationTimeout, from, to);
-    });
-
-    $scope.save = function() {
-        var clientCopy = angular.copy($scope.client);
-        delete clientCopy['nodeReRegistrationTimeoutUnit'];
-        clientCopy.nodeReRegistrationTimeout = TimeUnit.toSeconds($scope.client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit)
-        Client.update({ realm : realm.realm, client : client.id }, clientCopy, function () {
-            $route.reload();
-            Notifications.success('Your changes have been saved to the client.');
-        });
-    };
-
-    $scope.reset = function() {
-        $route.reload();
-    };
-
-    $scope.testNodesAvailable = function() {
-        ClientTestNodesAvailable.get({ realm : realm.realm, client : client.id }, function(globalReqResult) {
-            $route.reload();
-
-            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
-            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
-
-            if (successCount==0 && failedCount==0) {
-                Notifications.warn('No requests sent. No admin URI configured or no registered cluster nodes available');
-            } else if (failedCount > 0) {
-                var msgStart = successCount>0 ? 'Successfully verify availability for ' + globalReqResult.successRequests + ' . ' : '';
-                Notifications.error(msgStart + 'Failed to verify availability for: ' + globalReqResult.failedRequests + '. Fix or unregister failed cluster nodes and try again');
-            } else {
-                Notifications.success('Successfully sent requests to: ' + globalReqResult.successRequests);
-            }
-        });
-    };
-
-    if (client.registeredNodes) {
-        var nodeRegistrations = [];
-        for (node in client.registeredNodes) {
-            reg = {
-                host: node,
-                lastRegistration: new Date(client.registeredNodes[node] * 1000)
-            }
-            nodeRegistrations.push(reg);
-        }
-
-        $scope.nodeRegistrations = nodeRegistrations;
-    };
-});
-
-module.controller('ClientClusteringNodeCtrl', function($scope, client, Client, ClientClusterNode, realm, $location, $routeParams, Notifications) {
-    $scope.client = client;
-    $scope.realm = realm;
-    $scope.create = !$routeParams.node;
-
-    $scope.save = function() {
-        ClientClusterNode.save({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() {
-            Notifications.success('Node ' + $scope.node.host + ' registered successfully.');
-            $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/clustering');
-        });
-    }
-
-    $scope.unregisterNode = function() {
-        ClientClusterNode.remove({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() {
-            Notifications.success('Node ' + $scope.node.host + ' unregistered successfully.');
-            $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/clustering');
-        });
-    }
-
-    if ($scope.create) {
-        $scope.node = {}
-        $scope.registered = false;
-    } else {
-        var lastRegTime = client.registeredNodes[$routeParams.node];
-
-        if (lastRegTime) {
-            $scope.registered = true;
-            $scope.node = {
-                host: $routeParams.node,
-                lastRegistration: new Date(lastRegTime * 1000)
-            }
-
-        } else {
-            $scope.registered = false;
-            $scope.node = {
-                host: $routeParams.node
-            }
-        }
-    }
-});
-
-module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, client, serverInfo,
-                                                            ClientProtocolMappersByProtocol,
-                                                            $http, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-    if (client.protocol == null) {
-        client.protocol = 'openid-connect';
-    }
-
-    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
-    var mapperTypes = {};
-    for (var i = 0; i < protocolMappers.length; i++) {
-        mapperTypes[protocolMappers[i].id] = protocolMappers[i];
-    }
-    $scope.mapperTypes = mapperTypes;
-
-
-
-
-    var updateMappers = function() {
-        var clientMappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol}, function() {
-            var builtinMappers = serverInfo.builtinProtocolMappers[client.protocol];
-            for (var i = 0; i < clientMappers.length; i++) {
-                for (var j = 0; j < builtinMappers.length; j++) {
-                    if (builtinMappers[j].name == clientMappers[i].name
-                        && builtinMappers[j].protocolMapper == clientMappers[i].protocolMapper) {
-                        builtinMappers.splice(j, 1);
-                        break;
-                    }
-                }
-            }
-            $scope.mappers = builtinMappers;
-            for (var i = 0; i < $scope.mappers.length; i++) {
-                $scope.mappers[i].isChecked = false;
-            }
-
-
-        });
-    };
-
-    updateMappers();
-
-    $scope.add = function() {
-        var toAdd = [];
-        for (var i = 0; i < $scope.mappers.length; i++) {
-            if ($scope.mappers[i].isChecked) {
-                delete $scope.mappers[i].isChecked;
-                toAdd.push($scope.mappers[i]);
-            }
-        }
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/protocol-mappers/add-models',
-                   toAdd).success(function() {
-                Notifications.success("Mappers added");
-                $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/mappers');
-            }).error(function() {
-                Notifications.error("Error adding mappers");
-                $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/mappers');
-            });
-    };
-
-});
-
-module.controller('ClientProtocolMapperListCtrl', function($scope, realm, client, serverInfo,
-                                                           ClientProtocolMappersByProtocol,
-                                                           $http, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.client = client;
-    if (client.protocol == null) {
-        client.protocol = 'openid-connect';
-    }
-
-    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
-    var mapperTypes = {};
-    for (var i = 0; i < protocolMappers.length; i++) {
-        mapperTypes[protocolMappers[i].id] = protocolMappers[i];
-    }
-    $scope.mapperTypes = mapperTypes;
-
-
-    var updateMappers = function() {
-        $scope.mappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol});
-    };
-
-    updateMappers();
-});
-
-module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.create = false;
-    if (client.protocol == null) {
-        client.protocol = 'openid-connect';
-    }
-    $scope.protocol = client.protocol;
-    $scope.mapper = angular.copy(mapper);
-    $scope.changed = false;
-    $scope.boolval = true;
-    $scope.boolvalId = 'boolval';
-
-    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
-    for (var i = 0; i < protocolMappers.length; i++) {
-        if (protocolMappers[i].id == mapper.protocolMapper) {
-            $scope.mapperType = protocolMappers[i];
-        }
-    }
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.$watch('mapper', function() {
-        if (!angular.equals($scope.mapper, mapper)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        ClientProtocolMapper.update({
-            realm : realm.realm,
-            client: client.id,
-            id : mapper.id
-        }, $scope.mapper, function() {
-            $scope.changed = false;
-            mapper = angular.copy($scope.mapper);
-            $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + mapper.id);
-            Notifications.success("Your changes have been saved.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.mapper = angular.copy(mapper);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
-            ClientProtocolMapper.remove({ realm: realm.realm, client: client.id, id : $scope.mapper.id }, function() {
-                Notifications.success("The mapper has been deleted.");
-                $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers");
-            });
-        });
-    };
-
-});
-
-module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, ClientProtocolMapper, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.client = client;
-    $scope.create = true;
-    if (client.protocol == null) {
-        client.protocol = 'openid-connect';
-    }
-    var protocol = client.protocol;
-    $scope.protocol = protocol;
-    $scope.mapper = { protocol :  client.protocol, config: {}};
-    $scope.mapperTypes = serverInfo.protocolMapperTypes[protocol];
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.save = function() {
-        $scope.mapper.protocolMapper = $scope.mapperType.id;
-        ClientProtocolMapper.save({
-            realm : realm.realm, client: client.id
-        }, $scope.mapper, function(data, headers) {
-            var l = headers().location;
-            var id = l.substring(l.lastIndexOf("/") + 1);
-            $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + id);
-            Notifications.success("Mapper has been created.");
-        });
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-
-});
-
-
-
-
+Array.prototype.remove = function(from, to) {
+    var rest = this.slice((to || from) + 1 || this.length);
+    this.length = from < 0 ? this.length + from : from;
+    return this.push.apply(this, rest);
+};
+
+module.controller('ClientRoleListCtrl', function($scope, $location, realm, client, roles) {
+    $scope.realm = realm;
+    $scope.roles = roles;
+    $scope.client = client;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientCredentialsCtrl', function($scope, $location, realm, client, ClientCredentials, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+    var secret = ClientCredentials.get({ realm : realm.realm, client : client.id },
+        function() {
+            $scope.secret = secret.value;
+        }
+    );
+
+    $scope.changePassword = function() {
+        var secret = ClientCredentials.update({ realm : realm.realm, client : client.id },
+            function() {
+                Notifications.success('The secret has been changed.');
+                $scope.secret = secret.value;
+            },
+            function() {
+                Notifications.error("The secret was not changed due to a problem.");
+                $scope.secret = "error";
+            }
+        );
+    };
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientIdentityProviderCtrl', function($scope, $location, $route, realm, client, Client, $location, Notifications) {
+    $scope.realm = realm;
+    $scope.client = angular.copy(client);
+    var length = 0;
+
+    if ($scope.client.identityProviders) {
+        length = $scope.client.identityProviders.length;
+
+        for (i = 0; i < $scope.client.identityProviders.length; i++) {
+            var clientProvider = $scope.client.identityProviders[i];
+            if (clientProvider.retrieveToken) {
+                clientProvider.retrieveToken = clientProvider.retrieveToken.toString();
+            }
+        }
+
+    } else {
+        $scope.client.identityProviders = [];
+    }
+
+    $scope.identityProviders = [];
+    var providersMissingInClient = [];
+
+    for (j = 0; j < realm.identityProviders.length; j++) {
+        var identityProvider = realm.identityProviders[j];
+        var clientProvider = null;
+
+        for (i = 0; i < $scope.client.identityProviders.length; i++) {
+            clientProvider = $scope.client.identityProviders[i];
+
+            if (clientProvider) {
+
+                if (clientProvider.id == identityProvider.id) {
+                    $scope.identityProviders[i] = {};
+                    $scope.identityProviders[i].identityProvider = identityProvider;
+                    $scope.identityProviders[i].retrieveToken = clientProvider.retrieveToken;
+                    break;
+                }
+
+                clientProvider = null;
+            }
+        }
+
+        if (clientProvider == null) {
+            providersMissingInClient.push(identityProvider);
+        }
+    }
+
+    for (j = 0; j < providersMissingInClient.length; j++) {
+        var identityProvider = providersMissingInClient[j];
+
+        var currentProvider = {};
+        currentProvider.identityProvider = identityProvider;
+        currentProvider.retrieveToken = "false";
+        $scope.identityProviders.push(currentProvider);
+
+        var currentClientProvider = {};
+        currentClientProvider.id = identityProvider.id;
+        currentClientProvider.retrieveToken = "false";
+        $scope.client.identityProviders.push(currentClientProvider);
+    }
+
+    var oldCopy = angular.copy($scope.client);
+
+    $scope.save = function() {
+
+        Client.update({
+            realm : realm.realm,
+            client : client.id
+        }, $scope.client, function() {
+            $scope.changed = false;
+            $route.reload();
+            Notifications.success("Your changes have been saved to the client.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.client = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+
+    $scope.$watch('client', function() {
+        if (!angular.equals($scope.client, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+});
+
+module.controller('ClientSamlKeyCtrl', function($scope, $location, $http, $upload, realm, client,
+                                                         ClientCertificate, ClientCertificateGenerate,
+                                                         ClientCertificateDownload, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+
+    var signingKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.signing' },
+        function() {
+            $scope.signingKeyInfo = signingKeyInfo;
+        }
+    );
+
+    $scope.generateSigningKey = function() {
+        var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.signing' },
+            function() {
+                Notifications.success('Signing key has been regenerated.');
+                $scope.signingKeyInfo = keyInfo;
+            },
+            function() {
+                Notifications.error("Signing key was not regenerated.");
+            }
+        );
+    };
+
+    $scope.importSigningKey = function() {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/import/saml.signing");
+    };
+
+    $scope.exportSigningKey = function() {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Signing/export/saml.signing");
+    };
+
+    var encryptionKeyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' },
+        function() {
+            $scope.encryptionKeyInfo = encryptionKeyInfo;
+        }
+    );
+
+    $scope.generateEncryptionKey = function() {
+        var keyInfo = ClientCertificateGenerate.generate({ realm : realm.realm, client : client.id, attribute: 'saml.encryption' },
+            function() {
+                Notifications.success('Encryption key has been regenerated.');
+                $scope.encryptionKeyInfo = keyInfo;
+            },
+            function() {
+                Notifications.error("Encryption key was not regenerated.");
+            }
+        );
+    };
+
+    $scope.importEncryptionKey = function() {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/import/saml.encryption");
+    };
+
+    $scope.exportEncryptionKey = function() {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/Encryption/export/saml.encryption");
+    };
+
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientCertificateImportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams,
+                                                         ClientCertificate, ClientCertificateGenerate,
+                                                         ClientCertificateDownload, Notifications) {
+
+    var keyType = $routeParams.keyType;
+    var attribute = $routeParams.attribute;
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.keyType = keyType;
+
+    $scope.files = [];
+
+    $scope.onFileSelect = function($files) {
+        $scope.files = $files;
+    };
+
+    $scope.clearFileSelect = function() {
+        $scope.files = null;
+    }
+
+    $scope.keyFormats = [
+        "JKS",
+        "PKCS12"
+    ];
+
+    $scope.uploadKeyFormat = $scope.keyFormats[0];
+
+    $scope.uploadFile = function() {
+        //$files: an array of files selected, each file has name, size, and type.
+        for (var i = 0; i < $scope.files.length; i++) {
+            var $file = $scope.files[i];
+            $scope.upload = $upload.upload({
+                url: authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/certificates/' + attribute + '/upload',
+                // method: POST or PUT,
+                // headers: {'headerKey': 'headerValue'}, withCredential: true,
+                data: {keystoreFormat: $scope.uploadKeyFormat,
+                    keyAlias: $scope.uploadKeyAlias,
+                    keyPassword: $scope.uploadKeyPassword,
+                    storePassword: $scope.uploadStorePassword
+                },
+                file: $file
+                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
+                //fileFormDataName: myFile,
+                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
+                //formDataAppender: function(formData, key, val){}
+            }).success(function(data, status, headers) {
+                Notifications.success("Keystore uploaded successfully.");
+                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/saml/keys");
+            })
+                .error(function() {
+                    Notifications.error("The key store can not be uploaded. Please verify the file.");
+
+                });
+            //.then(success, error, progress);
+        }
+    };
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientCertificateExportCtrl', function($scope, $location, $http, $upload, realm, client, $routeParams,
+                                                         ClientCertificate, ClientCertificateGenerate,
+                                                         ClientCertificateDownload, Notifications) {
+    var keyType = $routeParams.keyType;
+    var attribute = $routeParams.attribute;
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.keyType = keyType;
+    var jks = {
+        keyAlias: client.clientId,
+        realmAlias: realm.realm
+    };
+
+    $scope.keyFormats = [
+        "JKS",
+        "PKCS12"
+    ];
+
+    var keyInfo = ClientCertificate.get({ realm : realm.realm, client : client.id, attribute: attribute },
+        function() {
+            $scope.keyInfo = keyInfo;
+        }
+    );
+    $scope.jks = jks;
+    $scope.jks.format = $scope.keyFormats[0];
+
+    $scope.download = function() {
+        $http({
+            url: authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/certificates/' + attribute + '/download',
+            method: 'POST',
+            responseType: 'arraybuffer',
+            data: $scope.jks,
+            headers: {
+                'Content-Type': 'application/json',
+                'Accept': 'client/octet-stream'
+            }
+        }).success(function(data){
+            var blob = new Blob([data], {
+                type: 'client/octet-stream'
+            });
+            var ext = ".jks";
+            if ($scope.jks.format == 'PKCS12') ext = ".p12";
+            saveAs(blob, 'keystore' + ext);
+        }).error(function(){
+            Notifications.error("Error downloading.");
+        });
+    }
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientSessionsCtrl', function($scope, realm, sessionCount, client,
+                                                      ClientUserSessions) {
+    $scope.realm = realm;
+    $scope.count = sessionCount.count;
+    $scope.sessions = [];
+    $scope.client = client;
+
+    $scope.page = 0;
+
+    $scope.query = {
+        realm : realm.realm,
+        client: $scope.client.id,
+        max : 5,
+        first : 0
+    }
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.loadUsers();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.loadUsers();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.loadUsers();
+    }
+
+    $scope.toDate = function(val) {
+        return new Date(val);
+    };
+
+    $scope.loadUsers = function() {
+        ClientUserSessions.query($scope.query, function(updated) {
+            $scope.sessions = updated;
+        })
+    };
+});
+
+module.controller('ClientRoleDetailCtrl', function($scope, realm, client, role, roles, clients,
+                                                        Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
+                                                        $http, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.role = angular.copy(role);
+    $scope.create = !role.name;
+
+    $scope.changed = $scope.create;
+
+    $scope.save = function() {
+        if ($scope.create) {
+            ClientRole.save({
+                realm: realm.realm,
+                client : client.id
+            }, $scope.role, function (data, headers) {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+
+                ClientRole.get({ realm: realm.realm, client : client.id, role: role.name }, function(role) {
+                    var id = role.id;
+                    $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles/" + id);
+                    Notifications.success("The role has been created.");
+                });
+            });
+        } else {
+            $scope.update();
+        }
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.role.name, 'role', function() {
+            $scope.role.$remove({
+                realm : realm.realm,
+                client : client.id,
+                role : $scope.role.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles");
+                Notifications.success("The role has been deleted.");
+            });
+        });
+    };
+
+    $scope.cancel = function () {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/roles");
+    };
+
+
+    roleControl($scope, realm, role, roles, clients,
+        ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
+        $http, $location, Notifications, Dialog);
+
+});
+
+module.controller('ClientImportCtrl', function($scope, $location, $upload, realm, serverInfo, Notifications) {
+
+    $scope.realm = realm;
+    $scope.configFormats = serverInfo.clientImporters;
+    $scope.configFormat = null;
+
+    $scope.files = [];
+
+    $scope.onFileSelect = function($files) {
+        $scope.files = $files;
+    };
+
+    $scope.clearFileSelect = function() {
+        $scope.files = null;
+    }
+
+    $scope.uploadFile = function() {
+        //$files: an array of files selected, each file has name, size, and type.
+        for (var i = 0; i < $scope.files.length; i++) {
+            var $file = $scope.files[i];
+            $scope.upload = $upload.upload({
+                url: authUrl + '/admin/realms/' + realm.realm + '/client-importers/' + $scope.configFormat.id + '/upload',
+                // method: POST or PUT,
+                // headers: {'headerKey': 'headerValue'}, withCredential: true,
+                data: {myObj: ""},
+                file: $file
+                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
+                //fileFormDataName: myFile,
+                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
+                //formDataAppender: function(formData, key, val){}
+            }).success(function(data, status, headers) {
+                Notifications.success("Uploaded successfully.");
+                $location.url("/realms/" + realm.realm + "/clients");
+            })
+                .error(function() {
+                    Notifications.error("The file can not be uploaded. Please verify the file.");
+
+                });
+            //.then(success, error, progress);
+        }
+    };
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+
+module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $location) {
+    $scope.realm = realm;
+    $scope.clients = clients;
+    $scope.importButton = serverInfo.clientImporters.length > 0;
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('ClientInstallationCtrl', function($scope, realm, client, ClientInstallation,ClientInstallationJBoss, $http, $routeParams) {
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.installation = null;
+    $scope.download = null;
+    $scope.configFormat = null;
+    $scope.filename = null;
+
+    $scope.configFormats = [
+        "Keycloak JSON",
+        "Wildfly/EAP Subsystem XML"
+    ];
+
+    $scope.changeFormat = function() {
+        if ($scope.configFormat == "Keycloak JSON") {
+            $scope.filename = 'keycloak.json';
+
+            var url = ClientInstallation.url({ realm: $routeParams.realm, client: $routeParams.client });
+            $http.get(url).success(function(data) {
+                var tmp = angular.fromJson(data);
+                $scope.installation = angular.toJson(tmp, true);
+                $scope.type = 'application/json';
+            })
+        } else if ($scope.configFormat == "Wildfly/EAP Subsystem XML") {
+            $scope.filename = 'keycloak.xml';
+
+            var url = ClientInstallationJBoss.url({ realm: $routeParams.realm, client: $routeParams.client });
+            $http.get(url).success(function(data) {
+                $scope.installation = data;
+                $scope.type = 'text/xml';
+            })
+        }
+
+        console.debug($scope.filename);
+    };
+
+    $scope.download = function() {
+        saveAs(new Blob([$scope.installation], { type: $scope.type }), $scope.filename);
+    }
+});
+
+module.controller('ClientDetailCtrl', function($scope, realm, client, $route, serverInfo, Client, $location, Dialog, Notifications) {
+    $scope.accessTypes = [
+        "confidential",
+        "public",
+        "bearer-only"
+    ];
+
+    $scope.protocols = serverInfo.protocols;
+
+    $scope.signatureAlgorithms = [
+        "RSA_SHA1",
+        "RSA_SHA256",
+        "RSA_SHA512",
+        "DSA_SHA1"
+    ];
+    $scope.nameIdFormats = [
+        "username",
+        "email",
+        "transient",
+        "persistent"
+    ];
+
+    $scope.realm = realm;
+    $scope.create = !client.clientId;
+    $scope.samlAuthnStatement = false;
+    $scope.samlMultiValuedRoles = false;
+    $scope.samlServerSignature = false;
+    $scope.samlAssertionSignature = false;
+    $scope.samlClientSignature = false;
+    $scope.samlEncrypt = false;
+    $scope.samlForcePostBinding = false;
+    $scope.samlForceNameIdFormat = false;
+    if (!$scope.create) {
+        if (!client.attributes) {
+            client.attributes = {};
+        }
+        $scope.client= angular.copy(client);
+        $scope.accessType = $scope.accessTypes[0];
+        if (client.bearerOnly) {
+            $scope.accessType = $scope.accessTypes[2];
+        } else if (client.publicClient) {
+            $scope.accessType = $scope.accessTypes[1];
+        }
+        if (client.protocol) {
+            $scope.protocol = $scope.protocols[$scope.protocols.indexOf(client.protocol)];
+        } else {
+            $scope.protocol = $scope.protocols[0];
+        }
+        if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA1') {
+            $scope.signatureAlgorithm = $scope.signatureAlgorithms[0];
+        } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA256') {
+            $scope.signatureAlgorithm = $scope.signatureAlgorithms[1];
+        } else if (client.attributes['saml.signature.algorithm'] == 'RSA_SHA512') {
+            $scope.signatureAlgorithm = $scope.signatureAlgorithms[2];
+        } else if (client.attributes['saml.signature.algorithm'] == 'DSA_SHA1') {
+            $scope.signatureAlgorithm = $scope.signatureAlgorithms[3];
+        }
+        if (client.attributes['saml_name_id_format'] == 'unspecified') {
+            $scope.nameIdFormat = $scope.nameIdFormats[0];
+        } else if (client.attributes['saml_name_id_format'] == 'email') {
+            $scope.nameIdFormat = $scope.nameIdFormats[1];
+        } else if (client.attributes['saml_name_id_format'] == 'transient') {
+            $scope.nameIdFormat = $scope.nameIdFormats[2];
+        } else if (client.attributes['saml_name_id_format'] == 'persistent') {
+            $scope.nameIdFormat = $scope.nameIdFormats[3];
+        }
+
+    } else {
+        $scope.client = { enabled: true, attributes: {}};
+        $scope.client.redirectUris = [];
+        $scope.accessType = $scope.accessTypes[0];
+        $scope.protocol = $scope.protocols[0];
+        $scope.signatureAlgorithm = $scope.signatureAlgorithms[1];
+        $scope.nameIdFormat = $scope.nameIdFormats[0];
+        $scope.samlAuthnStatement = true;
+        $scope.samlForceNameIdFormat = false;
+    }
+
+    if ($scope.client.attributes["saml.server.signature"]) {
+        if ($scope.client.attributes["saml.server.signature"] == "true") {
+            $scope.samlServerSignature = true;
+        } else {
+            $scope.samlServerSignature = false;
+
+        }
+    }
+    if ($scope.client.attributes["saml.assertion.signature"]) {
+        if ($scope.client.attributes["saml.assertion.signature"] == "true") {
+            $scope.samlAssertionSignature = true;
+        } else {
+            $scope.samlAssertionSignature = false;
+        }
+    }
+    if ($scope.client.attributes["saml.client.signature"]) {
+        if ($scope.client.attributes["saml.client.signature"] == "true") {
+            $scope.samlClientSignature = true;
+        } else {
+            $scope.samlClientSignature = false;
+        }
+    }
+    if ($scope.client.attributes["saml.encrypt"]) {
+        if ($scope.client.attributes["saml.encrypt"] == "true") {
+            $scope.samlEncrypt = true;
+        } else {
+            $scope.samlEncrypt = false;
+        }
+    }
+    if ($scope.client.attributes["saml.authnstatement"]) {
+        if ($scope.client.attributes["saml.authnstatement"] == "true") {
+            $scope.samlAuthnStatement = true;
+        } else {
+            $scope.samlAuthnStatement = false;
+        }
+    }
+    if ($scope.client.attributes["saml_force_name_id_format"]) {
+        if ($scope.client.attributes["saml_force_name_id_format"] == "true") {
+            $scope.samlForceNameIdFormat = true;
+        } else {
+            $scope.samlForceNameIdFormat = false;
+        }
+    }
+    if ($scope.client.attributes["saml.multivalued.roles"]) {
+        if ($scope.client.attributes["saml.multivalued.roles"] == "true") {
+            $scope.samlMultiValuedRoles = true;
+        } else {
+            $scope.samlMultiValuedRoles = false;
+        }
+    }
+    if ($scope.client.attributes["saml.force.post.binding"]) {
+        if ($scope.client.attributes["saml.force.post.binding"] == "true") {
+            $scope.samlForcePostBinding = true;
+        } else {
+            $scope.samlForcePostBinding = false;
+        }
+    }
+
+    $scope.switchChange = function() {
+        $scope.changed = true;
+    }
+
+    $scope.changeAccessType = function() {
+        if ($scope.accessType == "confidential") {
+            $scope.client.bearerOnly = false;
+            $scope.client.publicClient = false;
+        } else if ($scope.accessType == "public") {
+            $scope.client.bearerOnly = false;
+            $scope.client.publicClient = true;
+        } else if ($scope.accessType == "bearer-only") {
+            $scope.client.bearerOnly = true;
+            $scope.client.publicClient = false;
+        }
+    };
+
+    $scope.changeProtocol = function() {
+        if ($scope.protocol == "openid-connect") {
+            $scope.client.protocol = "openid-connect";
+        } else if ($scope.protocol == "saml") {
+            $scope.client.protocol = "saml";
+        }
+    };
+
+    $scope.changeAlgorithm = function() {
+        $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm;
+    };
+
+    $scope.changeNameIdFormat = function() {
+        $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat;
+    };
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    function isChanged() {
+        if (!angular.equals($scope.client, client)) {
+            return true;
+        }
+        if ($scope.newRedirectUri && $scope.newRedirectUri.length > 0) {
+            return true;
+        }
+        if ($scope.newWebOrigin && $scope.newWebOrigin.length > 0) {
+            return true;
+        }
+        return false;
+    }
+
+    $scope.$watch('client', function() {
+        $scope.changed = isChanged();
+    }, true);
+
+    $scope.$watch('newRedirectUri', function() {
+        $scope.changed = isChanged();
+    }, true);
+
+
+    $scope.$watch('newWebOrigin', function() {
+        $scope.changed = isChanged();
+    }, true);
+
+    $scope.deleteWebOrigin = function(index) {
+        $scope.client.webOrigins.splice(index, 1);
+    }
+    $scope.addWebOrigin = function() {
+        $scope.client.webOrigins.push($scope.newWebOrigin);
+        $scope.newWebOrigin = "";
+    }
+    $scope.deleteRedirectUri = function(index) {
+        $scope.client.redirectUris.splice(index, 1);
+    }
+
+    $scope.addRedirectUri = function() {
+        $scope.client.redirectUris.push($scope.newRedirectUri);
+        $scope.newRedirectUri = "";
+    }
+
+    $scope.save = function() {
+        if ($scope.newRedirectUri && $scope.newRedirectUri.length > 0) {
+            $scope.addRedirectUri();
+        }
+
+        if ($scope.newWebOrigin && $scope.newWebOrigin.length > 0) {
+            $scope.addWebOrigin();
+        }
+
+        if ($scope.samlServerSignature == true) {
+            $scope.client.attributes["saml.server.signature"] = "true";
+        } else {
+            $scope.client.attributes["saml.server.signature"] = "false";
+
+        }
+        if ($scope.samlAssertionSignature == true) {
+            $scope.client.attributes["saml.assertion.signature"] = "true";
+        } else {
+            $scope.client.attributes["saml.assertion.signature"] = "false";
+        }
+        if ($scope.samlClientSignature == true) {
+            $scope.client.attributes["saml.client.signature"] = "true";
+        } else {
+            $scope.client.attributes["saml.client.signature"] = "false";
+
+        }
+        if ($scope.samlEncrypt == true) {
+            $scope.client.attributes["saml.encrypt"] = "true";
+        } else {
+            $scope.client.attributes["saml.encrypt"] = "false";
+
+        }
+        if ($scope.samlAuthnStatement == true) {
+            $scope.client.attributes["saml.authnstatement"] = "true";
+        } else {
+            $scope.client.attributes["saml.authnstatement"] = "false";
+
+        }
+        if ($scope.samlForceNameIdFormat == true) {
+            $scope.client.attributes["saml_force_name_id_format"] = "true";
+        } else {
+            $scope.client.attributes["saml_force_name_id_format"] = "false";
+
+        }
+        if ($scope.samlMultiValuedRoles == true) {
+            $scope.client.attributes["saml.multivalued.roles"] = "true";
+        } else {
+            $scope.client.attributes["saml.multivalued.roles"] = "false";
+
+        }
+        if ($scope.samlForcePostBinding == true) {
+            $scope.client.attributes["saml.force.post.binding"] = "true";
+        } else {
+            $scope.client.attributes["saml.force.post.binding"] = "false";
+
+        }
+
+        $scope.client.protocol = $scope.protocol;
+        $scope.client.attributes['saml.signature.algorithm'] = $scope.signatureAlgorithm;
+        $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat;
+
+        if ($scope.client.protocol != 'saml' && !$scope.client.bearerOnly && !$scope.client.directGrantsOnly && (!$scope.client.redirectUris || $scope.client.redirectUris.length == 0)) {
+            Notifications.error("You must specify at least one redirect uri");
+        } else {
+            if ($scope.create) {
+                Client.save({
+                    realm: realm.realm,
+                    client: ''
+                }, $scope.client, function (data, headers) {
+                    $scope.changed = false;
+                    var l = headers().location;
+                    var id = l.substring(l.lastIndexOf("/") + 1);
+                    $location.url("/realms/" + realm.realm + "/clients/" + id);
+                    Notifications.success("The client has been created.");
+                });
+            } else {
+                Client.update({
+                    realm : realm.realm,
+                    client : client.id
+                }, $scope.client, function() {
+                    $scope.changed = false;
+                    client = angular.copy($scope.client);
+                    $location.url("/realms/" + realm.realm + "/clients/" + client.id);
+                    Notifications.success("Your changes have been saved to the client.");
+                });
+            }
+        }
+    };
+
+    $scope.reset = function() {
+        $route.reload();
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.realm + "/clients");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.client.clientId, 'client', function() {
+            $scope.client.$remove({
+                realm : realm.realm,
+                client : $scope.client.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/clients");
+                Notifications.success("The client has been deleted.");
+            });
+        });
+    };
+
+
+});
+
+module.controller('ClientScopeMappingCtrl', function($scope, $http, realm, client, clients, Notifications,
+                                                          Client,
+                                                          ClientRealmScopeMapping, ClientClientScopeMapping, ClientRole,
+                                                          ClientAvailableRealmScopeMapping, ClientAvailableClientScopeMapping,
+                                                          ClientCompositeRealmScopeMapping, ClientCompositeClientScopeMapping) {
+    $scope.realm = realm;
+    $scope.client = angular.copy(client);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.clients = clients;
+    $scope.clientRoles = [];
+    $scope.clientComposite = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientMappings = [];
+    $scope.clientMappings = [];
+    $scope.dummymodel = [];
+
+
+    $scope.changeFullScopeAllowed = function() {
+        Client.update({
+            realm : realm.realm,
+            client : client.id
+        }, $scope.client, function() {
+            $scope.changed = false;
+            client = angular.copy($scope.client);
+            updateRealmRoles();
+            Notifications.success("Scope mappings updated.");
+        });
+    }
+
+
+
+    function updateRealmRoles() {
+        $scope.realmRoles = ClientAvailableRealmScopeMapping.query({realm : realm.realm, client : client.id});
+        $scope.realmMappings = ClientRealmScopeMapping.query({realm : realm.realm, client : client.id});
+        $scope.realmComposite = ClientCompositeRealmScopeMapping.query({realm : realm.realm, client : client.id});
+    }
+
+    function updateClientRoles() {
+        if ($scope.targetClient) {
+            $scope.clientRoles = ClientAvailableClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
+            $scope.clientMappings = ClientClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
+            $scope.clientComposite = ClientCompositeClientScopeMapping.query({realm : realm.realm, client : client.id, targetClient : $scope.targetClient.id});
+        } else {
+            $scope.clientRoles = null;
+            $scope.clientMappings = null;
+            $scope.clientComposite = null;
+        }
+    }
+
+    $scope.changeClient = function() {
+        updateClientRoles();
+    };
+
+    $scope.addRealmRole = function() {
+        var roles = $scope.selectedRealmRoles;
+        $scope.selectedRealmRoles = [];
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/scope-mappings/realm',
+            roles).success(function() {
+                updateRealmRoles();
+                Notifications.success("Scope mappings updated.");
+            });
+    };
+
+    $scope.deleteRealmRole = function() {
+        var roles = $scope.selectedRealmMappings;
+        $scope.selectedRealmMappings = [];
+        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/realm',
+            {data : roles, headers : {"content-type" : "application/json"}}).success(function () {
+                updateRealmRoles();
+                Notifications.success("Scope mappings updated.");
+            });
+    };
+
+    $scope.addClientRole = function() {
+        var roles = $scope.selectedClientRoles;
+        $scope.selectedClientRoles = [];
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/clients/' + $scope.targetClient.id,
+                roles).success(function () {
+                updateClientRoles();
+                Notifications.success("Scope mappings updated.");
+            });
+    };
+
+    $scope.deleteClientRole = function() {
+        var roles = $scope.selectedClientMappings;
+        $scope.selectedClientMappings = [];
+        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id +  '/scope-mappings/clients/' + $scope.targetClient.id,
+            {data : roles, headers : {"content-type" : "application/json"}}).success(function () {
+                updateClientRoles();
+                Notifications.success("Scope mappings updated.");
+            });
+    };
+
+    updateRealmRoles();
+});
+
+module.controller('ClientRevocationCtrl', function($scope, realm, client, Client, ClientPushRevocation, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+
+    var setNotBefore = function() {
+        if ($scope.client.notBefore == 0) {
+            $scope.notBefore = "None";
+        } else {
+            $scope.notBefore = new Date($scope.client.notBefore * 1000);
+        }
+    };
+
+    setNotBefore();
+
+    var refresh = function() {
+        Client.get({ realm : realm.realm, client: $scope.client.id }, function(updated) {
+            $scope.client = updated;
+            setNotBefore();
+        })
+
+    };
+
+    $scope.clear = function() {
+        $scope.client.notBefore = 0;
+        Client.update({ realm : realm.realm, client: client.id}, $scope.client, function () {
+            $scope.notBefore = "None";
+            Notifications.success('Not Before cleared for client.');
+            refresh();
+        });
+    }
+    $scope.setNotBeforeNow = function() {
+        $scope.client.notBefore = new Date().getTime()/1000;
+        Client.update({ realm : realm.realm, client: $scope.client.id}, $scope.client, function () {
+            Notifications.success('Not Before set for client.');
+            refresh();
+        });
+    }
+    $scope.pushRevocation = function() {
+        ClientPushRevocation.save({realm : realm.realm, client: $scope.client.id}, function (globalReqResult) {
+            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
+            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
+
+            if (successCount==0 && failedCount==0) {
+                Notifications.warn('No push sent. No admin URI configured or no registered cluster nodes available');
+            } else if (failedCount > 0) {
+                var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
+                Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
+            } else {
+                Notifications.success('Successfully push notBefore to: ' + globalReqResult.successRequests);
+            }
+        });
+    }
+
+});
+
+module.controller('ClientClusteringCtrl', function($scope, client, Client, ClientTestNodesAvailable, realm, $location, $route, Notifications, TimeUnit) {
+    $scope.client = client;
+    $scope.realm = realm;
+
+    var oldCopy = angular.copy($scope.client);
+    $scope.changed = false;
+
+    $scope.$watch('client', function() {
+        if (!angular.equals($scope.client, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.client.nodeReRegistrationTimeoutUnit = TimeUnit.autoUnit(client.nodeReRegistrationTimeout);
+    $scope.client.nodeReRegistrationTimeout = TimeUnit.toUnit(client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit);
+    $scope.$watch('client.nodeReRegistrationTimeoutUnit', function(to, from) {
+        $scope.client.nodeReRegistrationTimeout = TimeUnit.convert($scope.client.nodeReRegistrationTimeout, from, to);
+    });
+
+    $scope.save = function() {
+        var clientCopy = angular.copy($scope.client);
+        delete clientCopy['nodeReRegistrationTimeoutUnit'];
+        clientCopy.nodeReRegistrationTimeout = TimeUnit.toSeconds($scope.client.nodeReRegistrationTimeout, $scope.client.nodeReRegistrationTimeoutUnit)
+        Client.update({ realm : realm.realm, client : client.id }, clientCopy, function () {
+            $route.reload();
+            Notifications.success('Your changes have been saved to the client.');
+        });
+    };
+
+    $scope.reset = function() {
+        $route.reload();
+    };
+
+    $scope.testNodesAvailable = function() {
+        ClientTestNodesAvailable.get({ realm : realm.realm, client : client.id }, function(globalReqResult) {
+            $route.reload();
+
+            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
+            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
+
+            if (successCount==0 && failedCount==0) {
+                Notifications.warn('No requests sent. No admin URI configured or no registered cluster nodes available');
+            } else if (failedCount > 0) {
+                var msgStart = successCount>0 ? 'Successfully verify availability for ' + globalReqResult.successRequests + ' . ' : '';
+                Notifications.error(msgStart + 'Failed to verify availability for: ' + globalReqResult.failedRequests + '. Fix or unregister failed cluster nodes and try again');
+            } else {
+                Notifications.success('Successfully sent requests to: ' + globalReqResult.successRequests);
+            }
+        });
+    };
+
+    if (client.registeredNodes) {
+        var nodeRegistrations = [];
+        for (node in client.registeredNodes) {
+            reg = {
+                host: node,
+                lastRegistration: new Date(client.registeredNodes[node] * 1000)
+            }
+            nodeRegistrations.push(reg);
+        }
+
+        $scope.nodeRegistrations = nodeRegistrations;
+    };
+});
+
+module.controller('ClientClusteringNodeCtrl', function($scope, client, Client, ClientClusterNode, realm, $location, $routeParams, Notifications) {
+    $scope.client = client;
+    $scope.realm = realm;
+    $scope.create = !$routeParams.node;
+
+    $scope.save = function() {
+        ClientClusterNode.save({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() {
+            Notifications.success('Node ' + $scope.node.host + ' registered successfully.');
+            $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/clustering');
+        });
+    }
+
+    $scope.unregisterNode = function() {
+        ClientClusterNode.remove({ realm : realm.realm, client : client.id , node: $scope.node.host }, function() {
+            Notifications.success('Node ' + $scope.node.host + ' unregistered successfully.');
+            $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/clustering');
+        });
+    }
+
+    if ($scope.create) {
+        $scope.node = {}
+        $scope.registered = false;
+    } else {
+        var lastRegTime = client.registeredNodes[$routeParams.node];
+
+        if (lastRegTime) {
+            $scope.registered = true;
+            $scope.node = {
+                host: $routeParams.node,
+                lastRegistration: new Date(lastRegTime * 1000)
+            }
+
+        } else {
+            $scope.registered = false;
+            $scope.node = {
+                host: $routeParams.node
+            }
+        }
+    }
+});
+
+module.controller('AddBuiltinProtocolMapperCtrl', function($scope, realm, client, serverInfo,
+                                                            ClientProtocolMappersByProtocol,
+                                                            $http, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+    if (client.protocol == null) {
+        client.protocol = 'openid-connect';
+    }
+
+    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
+    var mapperTypes = {};
+    for (var i = 0; i < protocolMappers.length; i++) {
+        mapperTypes[protocolMappers[i].id] = protocolMappers[i];
+    }
+    $scope.mapperTypes = mapperTypes;
+
+
+
+
+    var updateMappers = function() {
+        var clientMappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol}, function() {
+            var builtinMappers = serverInfo.builtinProtocolMappers[client.protocol];
+            for (var i = 0; i < clientMappers.length; i++) {
+                for (var j = 0; j < builtinMappers.length; j++) {
+                    if (builtinMappers[j].name == clientMappers[i].name
+                        && builtinMappers[j].protocolMapper == clientMappers[i].protocolMapper) {
+                        builtinMappers.splice(j, 1);
+                        break;
+                    }
+                }
+            }
+            $scope.mappers = builtinMappers;
+            for (var i = 0; i < $scope.mappers.length; i++) {
+                $scope.mappers[i].isChecked = false;
+            }
+
+
+        });
+    };
+
+    updateMappers();
+
+    $scope.add = function() {
+        var toAdd = [];
+        for (var i = 0; i < $scope.mappers.length; i++) {
+            if ($scope.mappers[i].isChecked) {
+                delete $scope.mappers[i].isChecked;
+                toAdd.push($scope.mappers[i]);
+            }
+        }
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/clients/' + client.id + '/protocol-mappers/add-models',
+                   toAdd).success(function() {
+                Notifications.success("Mappers added");
+                $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/mappers');
+            }).error(function() {
+                Notifications.error("Error adding mappers");
+                $location.url('/realms/' + realm.realm + '/clients/' + client.id +  '/mappers');
+            });
+    };
+
+});
+
+module.controller('ClientProtocolMapperListCtrl', function($scope, realm, client, serverInfo,
+                                                           ClientProtocolMappersByProtocol,
+                                                           $http, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.client = client;
+    if (client.protocol == null) {
+        client.protocol = 'openid-connect';
+    }
+
+    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
+    var mapperTypes = {};
+    for (var i = 0; i < protocolMappers.length; i++) {
+        mapperTypes[protocolMappers[i].id] = protocolMappers[i];
+    }
+    $scope.mapperTypes = mapperTypes;
+
+
+    var updateMappers = function() {
+        $scope.mappers = ClientProtocolMappersByProtocol.query({realm : realm.realm, client : client.id, protocol : client.protocol});
+    };
+
+    updateMappers();
+});
+
+module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.create = false;
+    if (client.protocol == null) {
+        client.protocol = 'openid-connect';
+    }
+    $scope.protocol = client.protocol;
+    $scope.mapper = angular.copy(mapper);
+    $scope.changed = false;
+    $scope.boolval = true;
+    $scope.boolvalId = 'boolval';
+
+    var protocolMappers = serverInfo.protocolMapperTypes[client.protocol];
+    for (var i = 0; i < protocolMappers.length; i++) {
+        if (protocolMappers[i].id == mapper.protocolMapper) {
+            $scope.mapperType = protocolMappers[i];
+        }
+    }
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('mapper', function() {
+        if (!angular.equals($scope.mapper, mapper)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        ClientProtocolMapper.update({
+            realm : realm.realm,
+            client: client.id,
+            id : mapper.id
+        }, $scope.mapper, function() {
+            $scope.changed = false;
+            mapper = angular.copy($scope.mapper);
+            $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + mapper.id);
+            Notifications.success("Your changes have been saved.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.mapper = angular.copy(mapper);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
+            ClientProtocolMapper.remove({ realm: realm.realm, client: client.id, id : $scope.mapper.id }, function() {
+                Notifications.success("The mapper has been deleted.");
+                $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers");
+            });
+        });
+    };
+
+});
+
+module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, ClientProtocolMapper, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.client = client;
+    $scope.create = true;
+    if (client.protocol == null) {
+        client.protocol = 'openid-connect';
+    }
+    var protocol = client.protocol;
+    $scope.protocol = protocol;
+    $scope.mapper = { protocol :  client.protocol, config: {}};
+    $scope.mapperTypes = serverInfo.protocolMapperTypes[protocol];
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.save = function() {
+        $scope.mapper.protocolMapper = $scope.mapperType.id;
+        ClientProtocolMapper.save({
+            realm : realm.realm, client: client.id
+        }, $scope.mapper, function(data, headers) {
+            var l = headers().location;
+            var id = l.substring(l.lastIndexOf("/") + 1);
+            $location.url("/realms/" + realm.realm + '/clients/' + client.id + "/mappers/" + id);
+            Notifications.success("Mapper has been created.");
+        });
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+
+});
+
+
+
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 789b6f0..59a3f85 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1,1740 +1,1740 @@
-module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $location, Notifications, ServerInfo) {
-    $scope.addMessage = function() {
-        Notifications.success("test");
-    };
-
-    $scope.authUrl = authUrl;
-    $scope.resourceUrl = resourceUrl;
-    $scope.auth = Auth;
-    $scope.serverInfo = ServerInfo.get();
-    $scope.serverInfoUpdate = function() {
-        $scope.serverInfo = ServerInfo.get();
-    };
-
-    function hasAnyAccess() {
-        var realmAccess = Auth.user && Auth.user['realm_access'];
-        if (realmAccess) {
-            for (var p in realmAccess){
-                return true;
-            }
-            return false;
-        } else {
-            return false;
-        }
-    }
-
-    WhoAmI.get(function (data) {
-        Auth.user = data;
-        Auth.loggedIn = true;
-        Auth.hasAnyAccess = hasAnyAccess();
-    });
-
-    function getAccess(role) {
-        if (!Current.realm) {
-            return false;
-        }
-
-        var realmAccess = Auth.user && Auth.user['realm_access'];
-        if (realmAccess) {
-            realmAccess = realmAccess[Current.realm.realm];
-            if (realmAccess) {
-                return realmAccess.indexOf(role) >= 0;
-            }
-        }
-        return false;
-    }
-
-    $scope.access = {
-        get createRealm() {
-            return Auth.user && Auth.user.createRealm;
-        },
-
-        get viewRealm() {
-            return getAccess('view-realm') || this.manageRealm;
-        },
-
-        get viewClients() {
-            return getAccess('view-clients') || this.manageClients;
-        },
-
-        get viewUsers() {
-            return getAccess('view-users') || this.manageClients;
-        },
-
-        get viewEvents() {
-            return getAccess('view-events') || this.manageClients;
-        },
-
-        get manageRealm() {
-            return getAccess('manage-realm');
-        },
-
-        get manageClients() {
-            return getAccess('manage-clients');
-        },
-
-        get manageUsers() {
-            return getAccess('manage-users');
-        },
-
-        get manageEvents() {
-            return getAccess('manage-events');
-        },
-        get impersonation() {
-            return getAccess('impersonation');
-        }
-    }
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.fragment = $location.path();
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-module.controller('HomeCtrl', function(Realm, Auth, $location) {
-    Realm.query(null, function(realms) {
-        var realm;
-        if (realms.length == 1) {
-            realm = realms[0].realm;
-        } else if (realms.length == 2) {
-            if (realms[0].realm == Auth.user.realm) {
-                realm = realms[1].realm;
-            } else if (realms[1].realm == Auth.user.realm) {
-                realm = realms[0].realm;
-            }
-        }
-        if (realm) {
-            $location.url('/realms/' + realm);
-        } else {
-            $location.url('/realms');
-        }
-    });
-});
-
-module.controller('RealmListCtrl', function($scope, Realm, Current) {
-    $scope.realms = Realm.query();
-    Current.realms = $scope.realms;
-});
-
-module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $location) {
-//    Current.realms = Realm.get();
-    $scope.current = Current;
-
-    $scope.changeRealm = function(selectedRealm) {
-        $location.url("/realms/" + selectedRealm);
-    }
-});
-
-module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, Dialog, Notifications, Auth) {
-    console.log('RealmCreateCtrl');
-
-    Current.realm = null;
-
-    $scope.realm = {
-        enabled: true
-    };
-
-    $scope.changed = false;
-    $scope.files = [];
-
-    var oldCopy = angular.copy($scope.realm);
-
-    $scope.onFileSelect = function($files) {
-        $scope.files = $files;
-    };
-
-    $scope.clearFileSelect = function() {
-        $scope.files = null;
-    }
-
-    $scope.uploadFile = function() {
-        //$files: an array of files selected, each file has name, size, and type.
-        for (var i = 0; i < $scope.files.length; i++) {
-            var $file = $scope.files[i];
-            $scope.upload = $upload.upload({
-                url: authUrl + '/admin/realms', //upload.php script, node.js route, or servlet url
-                // method: POST or PUT,
-                // headers: {'headerKey': 'headerValue'}, withCredential: true,
-                data: {myObj: ""},
-                file: $file
-                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
-                //fileFormDataName: myFile,
-                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
-                //formDataAppender: function(formData, key, val){}
-            }).progress(function(evt) {
-                    console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
-                }).success(function(data, status, headers) {
-                    Realm.query(function(data) {
-                        Current.realms = data;
-
-
-                        WhoAmI.get(function(user) {
-                            Auth.user = user;
-
-                            Notifications.success("The realm has been uploaded.");
-
-                            var location = headers('Location');
-                            if (location) {
-                                $location.url("/realms/" + location.substring(location.lastIndexOf('/') + 1));
-                            } else {
-                                $location.url("/realms");
-                            }
-                        });
-                    });
-                })
-            .error(function() {
-                    Notifications.error("The realm can not be uploaded. Please verify the file.");
-
-                });
-            //.then(success, error, progress);
-        }
-    };
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        Realm.create(realmCopy, function() {
-            Realm.query(function(data) {
-                Current.realms = data;
-
-                WhoAmI.get(function(user) {
-                    Auth.user = user;
-
-                    $location.url("/realms/" + realmCopy.realm);
-                    Notifications.success("The realm has been created.");
-                });
-            });
-        });
-    };
-
-    $scope.cancel = function() {
-        window.history.back();
-    };
-});
-
-
-module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, WhoAmI, Auth) {
-    $scope.createRealm = !realm.realm;
-    $scope.serverInfo = serverInfo;
-
-    if (Current.realm == null || Current.realm.realm != realm.realm) {
-        for (var i = 0; i < Current.realms.length; i++) {
-            if (realm.realm == Current.realms[i].realm) {
-                Current.realm = Current.realms[i];
-                break;
-            }
-        }
-    }
-    for (var i = 0; i < Current.realms.length; i++) {
-        if (Current.realms[i].realm == realm.realm) {
-            Current.realm = Current.realms[i];
-        }
-    }
-    $scope.realm = angular.copy(realm);
-
-    var oldCopy = angular.copy($scope.realm);
-
-    $scope.changed = $scope.create;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        $scope.changed = false;
-        var nameChanged = !angular.equals($scope.realm.realm, oldCopy.realm)
-        Realm.update({ id : oldCopy.realm}, realmCopy, function () {
-            var data = Realm.query(function () {
-                Current.realms = data;
-                for (var i = 0; i < Current.realms.length; i++) {
-                    if (Current.realms[i].realm == realmCopy.realm) {
-                        Current.realm = Current.realms[i];
-                        oldCopy = angular.copy($scope.realm);
-                    }
-                }
-            });
-
-            if (nameChanged) {
-                WhoAmI.get(function(user) {
-                    Auth.user = user;
-
-                    $location.url("/realms/" + realmCopy.realm);
-                    Notifications.success("Your changes have been saved to the realm.");
-                });
-            } else {
-                $location.url("/realms/" + realmCopy.realm);
-                Notifications.success("Your changes have been saved to the realm.");
-            }
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.realm = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        window.history.back();
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.realm.realm, 'realm', function() {
-            Realm.remove({ id : $scope.realm.realm }, function() {
-                Current.realms = Realm.query();
-                Notifications.success("The realm has been deleted.");
-                $location.url("/");
-            });
-        });
-    };
-});
-
-function genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, url) {
-    $scope.realm = angular.copy(realm);
-    $scope.serverInfo = serverInfo;
-    $scope.registrationAllowed = $scope.realm.registrationAllowed;
-
-    var oldCopy = angular.copy($scope.realm);
-
-    $scope.changed = false;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        console.log('updating realm...');
-        $scope.changed = false;
-        console.log('oldCopy.realm - ' + oldCopy.realm);
-        Realm.update({ id : oldCopy.realm}, realmCopy, function () {
-            var data = Realm.query(function () {
-                Current.realms = data;
-                for (var i = 0; i < Current.realms.length; i++) {
-                    if (Current.realms[i].realm == realmCopy.realm) {
-                        Current.realm = Current.realms[i];
-                        oldCopy = angular.copy($scope.realm);
-                    }
-                }
-            });
-            $location.url(url);
-            Notifications.success("Your changes have been saved to the realm.");
-            $scope.registrationAllowed = $scope.realm.registrationAllowed;
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.realm = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-}
-
-module.controller('DefenseHeadersCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
-    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/defense/headers");
-});
-
-module.controller('RealmLoginSettingsCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
-    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/login-settings");
-});
-
-module.controller('RealmThemeCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
-    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/theme-settings");
-
-    $scope.supportedLocalesOptions = {
-        'multiple' : true,
-        'simple_tags' : true,
-        'tags' : ['en', 'de', 'pt-BR', 'it']
-    };
-
-    $scope.$watch('realm.supportedLocales', function(oldVal, newVal) {
-        if(angular.isUndefined(newVal) || (angular.isArray(newVal) && newVal.length == 0)){
-            $scope.realm.defaultLocale = undefined;
-        }
-    }, true);
-});
-
-module.controller('RealmCacheCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
-    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/cache-settings");
-});
-
-module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, PasswordPolicy) {
-    console.log('RealmPasswordPolicyCtrl');
-
-    $scope.realm = realm;
-
-    var oldCopy = angular.copy($scope.realm);
-
-    $scope.allPolicies = PasswordPolicy.allPolicies;
-    $scope.policyMessages = PasswordPolicy.policyMessages;
-
-    $scope.policy = PasswordPolicy.parse(realm.passwordPolicy);
-    var oldPolicy = angular.copy($scope.policy);
-
-    $scope.addPolicy = function(policy){
-        if (!$scope.policy) {
-            $scope.policy = [];
-        }
-        $scope.policy.push(policy);
-    }
-
-    $scope.removePolicy = function(index){
-        $scope.policy.splice(index, 1);
-    }
-
-    $scope.changed = false;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.$watch('policy', function(oldVal, newVal) {
-        if (!angular.equals($scope.policy, oldPolicy)) {
-            $scope.realm.passwordPolicy = PasswordPolicy.toString($scope.policy);
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        $scope.changed = false;
-
-        Realm.update($scope.realm, function () {
-            $location.url("/realms/" + realm.realm + "/authentication/password-policy");
-            Notifications.success("Your changes have been saved to the realm.");
-            oldCopy = angular.copy($scope.realm);
-            oldPolicy = angular.copy($scope.policy);
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.realm = angular.copy(oldCopy);
-        $scope.policy = angular.copy(oldPolicy);
-        $scope.changed = false;
-    };
-});
-
-module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, clients, roles, Notifications, ClientRole, Client) {
-
-    console.log('RealmDefaultRolesCtrl');
-
-    $scope.realm = realm;
-
-    $scope.availableRealmRoles = [];
-    $scope.selectedRealmRoles = [];
-    $scope.selectedRealmDefRoles = [];
-
-    $scope.clients = angular.copy(clients);
-    for (var i = 0; i < clients.length; i++) {
-        if (clients[i].name == 'account') {
-            $scope.client = $scope.clients[i];
-            break;
-        }
-    }
-
-    $scope.availableClientRoles = [];
-    $scope.selectedClientRoles = [];
-    $scope.selectedClientDefRoles = [];
-
-    if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) {
-        $scope.realm.defaultRoles = [];
-    }
-
-    // Populate available roles. Available roles are neither already assigned
-    for (var i = 0; i < roles.length; i++) {
-        var item = roles[i].name;
-
-        if ($scope.realm.defaultRoles.indexOf(item) < 0) {
-            $scope.availableRealmRoles.push(item);
-        }
-    }
-
-    $scope.addRealmDefaultRole = function () {
-
-        // Remove selected roles from the Available roles and add them to realm default roles (move from left to right).
-        for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
-            var selectedRole = $scope.selectedRealmRoles[i];
-
-            $scope.realm.defaultRoles.push(selectedRole);
-
-            var index = $scope.availableRealmRoles.indexOf(selectedRole);
-            if (index > -1) {
-                $scope.availableRealmRoles.splice(index, 1);
-            }
-        }
-
-        $scope.selectedRealmRoles = [];
-
-        // Update/save the realm with new default roles.
-        Realm.update($scope.realm, function () {
-            Notifications.success("Realm default roles updated.");
-        });
-    };
-
-    $scope.deleteRealmDefaultRole = function () {
-
-        // Remove selected roles from the realm default roles and add them to available roles (move from right to left).
-        for (var i = 0; i < $scope.selectedRealmDefRoles.length; i++) {
-            $scope.availableRealmRoles.push($scope.selectedRealmDefRoles[i]);
-
-            var index = $scope.realm.defaultRoles.indexOf($scope.selectedRealmDefRoles[i]);
-            if (index > -1) {
-                $scope.realm.defaultRoles.splice(index, 1);
-            }
-        }
-
-        $scope.selectedRealmDefRoles = [];
-
-        // Update/save the realm with new default roles.
-        //var realmCopy = angular.copy($scope.realm);
-        Realm.update($scope.realm, function () {
-            Notifications.success("Realm default roles updated.");
-        });
-    };
-
-    $scope.changeClient = function () {
-
-        $scope.selectedClientRoles = [];
-        $scope.selectedClientDefRoles = [];
-
-        // Populate available roles for selected client
-        if ($scope.client) {
-            var appDefaultRoles = ClientRole.query({realm: $scope.realm.realm, client: $scope.client.id}, function () {
-
-                if (!$scope.client.hasOwnProperty('defaultRoles') || $scope.client.defaultRoles === null) {
-                    $scope.client.defaultRoles = [];
-                }
-
-                $scope.availableClientRoles = [];
-
-                for (var i = 0; i < appDefaultRoles.length; i++) {
-                    var roleName = appDefaultRoles[i].name;
-                    if ($scope.client.defaultRoles.indexOf(roleName) < 0) {
-                        $scope.availableClientRoles.push(roleName);
-                    }
-                }
-            });
-        } else {
-            $scope.availableClientRoles = null;
-        }
-    };
-
-    $scope.addClientDefaultRole = function () {
-
-        // Remove selected roles from the app available roles and add them to app default roles (move from left to right).
-        for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
-            var role = $scope.selectedClientRoles[i];
-
-            var idx = $scope.client.defaultRoles.indexOf(role);
-            if (idx < 0) {
-                $scope.client.defaultRoles.push(role);
-            }
-
-            idx = $scope.availableClientRoles.indexOf(role);
-
-            if (idx != -1) {
-                $scope.availableClientRoles.splice(idx, 1);
-            }
-        }
-
-        $scope.selectedClientRoles = [];
-
-        // Update/save the selected client with new default roles.
-        Client.update({
-            realm: $scope.realm.realm,
-            client: $scope.client.id
-        }, $scope.client, function () {
-            Notifications.success("Your changes have been saved to the client.");
-        });
-    };
-
-    $scope.rmClientDefaultRole = function () {
-
-        // Remove selected roles from the app default roles and add them to app available roles (move from right to left).
-        for (var i = 0; i < $scope.selectedClientDefRoles.length; i++) {
-            var role = $scope.selectedClientDefRoles[i];
-            var idx = $scope.client.defaultRoles.indexOf(role);
-            if (idx != -1) {
-                $scope.client.defaultRoles.splice(idx, 1);
-            }
-            idx = $scope.availableClientRoles.indexOf(role);
-            if (idx < 0) {
-                $scope.availableClientRoles.push(role);
-            }
-        }
-
-        $scope.selectedClientDefRoles = [];
-
-        // Update/save the selected client with new default roles.
-        Client.update({
-            realm: $scope.realm.realm,
-            client: $scope.client.id
-        }, $scope.client, function () {
-            Notifications.success("Your changes have been saved to the client.");
-        });
-    };
-
-});
-
-module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload, $http, $route, realm, instance, providerFactory, IdentityProvider, serverInfo, $location, Notifications, Dialog) {
-    console.log('RealmIdentityProviderCtrl');
-
-    $scope.realm = angular.copy(realm);
-
-    $scope.initProvider = function() {
-        if (instance && instance.alias) {
-
-        } else {
-            $scope.identityProvider.updateProfileFirstLoginMode = "on";
-        }
-
-    };
-
-    $scope.initSamlProvider = function() {
-        $scope.nameIdFormats = [
-            /*
-            {
-                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
-                name: "Transient"
-            },
-            */
-            {
-                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
-                name: "Persistent"
-
-            },
-            {
-                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
-                name: "Email"
-
-            },
-            {
-                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos",
-                name: "Kerberos"
-
-            },
-            {
-                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
-                name: "X.509 Subject Name"
-
-            },
-            {
-                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName",
-                name: "Windows Domain Qualified Name"
-
-            },
-            {
-                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
-                name: "Unspecified"
-
-            }
-        ];
-        if (instance && instance.alias) {
-
-        } else {
-            $scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
-            $scope.identityProvider.updateProfileFirstLoginMode = "off";
-        }
-    }
-
-    $scope.hidePassword = true;
-    $scope.fromUrl = {
-        data: ''
-    };
-
-    if (instance && instance.alias) {
-        $scope.identityProvider = angular.copy(instance);
-        $scope.newIdentityProvider = false;
-    } else {
-        $scope.identityProvider = {};
-        $scope.identityProvider.config = {};
-        $scope.identityProvider.alias = providerFactory.id;
-        $scope.identityProvider.providerId = providerFactory.id;
-        $scope.identityProvider.enabled = true;
-        $scope.identityProvider.updateProfileFirstLoginMode = "off";
-        $scope.identityProvider.authenticateByDefault = false;
-        $scope.newIdentityProvider = true;
-    }
-
-    $scope.changed = $scope.newIdentityProvider;
-
-    $scope.$watch('identityProvider', function() {
-        if (!angular.equals($scope.identityProvider, instance)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-
-    $scope.serverInfo = serverInfo;
-
-    $scope.allProviders = angular.copy(serverInfo.identityProviders);
-
-    $scope.configuredProviders = angular.copy(realm.identityProviders);
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-
-    $scope.files = [];
-    $scope.importFile = false;
-    $scope.importUrl = false;
-
-    $scope.onFileSelect = function($files) {
-        $scope.importFile = true;
-        $scope.files = $files;
-    };
-
-    $scope.clearFileSelect = function() {
-        $scope.importUrl = false;
-        $scope.importFile = false;
-        $scope.files = null;
-    };
-
-    var setConfig = function(data) {
-        for (var key in data) {
-            $scope.identityProvider.config[key] = data[key];
-        }
-    }
-
-
-    $scope.uploadFile = function() {
-        if (!$scope.identityProvider.alias) {
-            Notifications.error("You must specify an alias");
-            return;
-        }
-        var input = {
-            providerId: providerFactory.id
-        }
-        //$files: an array of files selected, each file has name, size, and type.
-        for (var i = 0; i < $scope.files.length; i++) {
-            var $file = $scope.files[i];
-            $scope.upload = $upload.upload({
-                url: authUrl + '/admin/realms/' + realm.realm + '/identity-provider/import-config',
-                // method: POST or PUT,
-                // headers: {'headerKey': 'headerValue'}, withCredential: true,
-                data: input,
-                file: $file
-                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
-                //fileFormDataName: myFile,
-                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
-                //formDataAppender: function(formData, key, val){}
-            }).progress(function(evt) {
-                console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
-            }).success(function(data, status, headers) {
-                setConfig(data);
-                $scope.clearFileSelect();
-                Notifications.success("The IDP metadata has been loaded from file.");
-            }).error(function() {
-                Notifications.error("The file can not be uploaded. Please verify the file.");
-            });
-        }
-    };
-
-    $scope.importFrom = function() {
-        if (!$scope.identityProvider.alias) {
-            Notifications.error("You must specify an alias");
-            return;
-        }
-        var input = {
-            fromUrl: $scope.fromUrl.data,
-            providerId: providerFactory.id
-        }
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/identity-provider/import-config', input)
-            .success(function(data, status, headers) {
-                setConfig(data);
-                $scope.fromUrl.data = '';
-                $scope.importUrl = false;
-                Notifications.success("Imported config information from url.");
-            }).error(function() {
-                Notifications.error("Config can not be imported. Please verify the url.");
-            });
-    };
-    $scope.$watch('fromUrl.data', function(newVal, oldVal){
-        if ($scope.fromUrl.data && $scope.fromUrl.data.length > 0) {
-            $scope.importUrl = true;
-        } else{
-            $scope.importUrl = false;
-        }
-    });
-
-    $scope.$watch('configuredProviders', function(configuredProviders) {
-        if (configuredProviders) {
-            $scope.configuredProviders = angular.copy(configuredProviders);
-
-            for (var j = 0; j < configuredProviders.length; j++) {
-                var configProvidedId = configuredProviders[j].providerId;
-
-                for (var i in $scope.allProviders) {
-                    var provider = $scope.allProviders[i];
-
-                    if (provider.groupName == 'Social' && (provider.id == configProvidedId)) {
-                        $scope.allProviders.splice(i, 1);
-                        break;
-                    }
-                }
-            }
-        }
-    }, true);
-
-    $scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/realms/") + realm.realm + "/broker/" ;
-
-    $scope.addProvider = function(provider) {
-        $location.url("/create/identity-provider/" + realm.realm + "/" + provider.id);
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.identityProvider.alias, 'provider', function() {
-            $scope.identityProvider.$remove({
-                realm : realm.realm,
-                alias : $scope.identityProvider.alias
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/identity-provider-settings");
-                Notifications.success("The client has been deleted.");
-            });
-        });
-    };
-
-    $scope.save = function() {
-        if ($scope.newIdentityProvider) {
-            if (!$scope.identityProvider.alias) {
-                Notifications.error("You must specify an alias");
-                return;
-            }
-            IdentityProvider.save({
-                realm: $scope.realm.realm, alias: ''
-            }, $scope.identityProvider, function () {
-                $location.url("/realms/" + realm.realm + "/identity-provider-settings/provider/" + $scope.identityProvider.providerId + "/" + $scope.identityProvider.alias);
-                Notifications.success("The " + $scope.identityProvider.alias + " provider has been created.");
-            });
-        } else {
-            IdentityProvider.update({
-                realm: $scope.realm.realm,
-                id: $scope.identityProvider.internalId
-            }, $scope.identityProvider, function () {
-                $route.reload();
-                Notifications.success("The " + $scope.identityProvider.alias + " provider has been update.");
-            });
-        }
-    };
-
-    $scope.cancel = function() {
-        if ($scope.newIdentityProvider) {
-            $location.url("/realms/" + realm.realm + "/identity-provider-settings");
-        } else {
-            $route.reload();
-        }
-    };
-
-
-    $scope.reset = function() {
-        $scope.identityProvider = {};
-        $scope.configuredProviders = angular.copy($scope.realm.identityProviders);
-    };
-
-    $scope.showPassword = function(flag) {
-        $scope.hidePassword = flag;
-    };
-
-});
-
-module.controller('RealmIdentityProviderExportCtrl', function(realm, identityProvider, $scope, $http, IdentityProviderExport) {
-    $scope.realm = realm;
-    $scope.identityProvider = identityProvider;
-    $scope.download = null;
-    $scope.exported = "";
-    $scope.exportedType = "";
-
-    var url = IdentityProviderExport.url({realm: realm.realm, alias: identityProvider.alias}) ;
-    $http.get(url).success(function(data, status, headers, config) {
-        $scope.exportedType = headers('Content-Type');
-        $scope.exported = data;
-    });
-
-    $scope.download = function() {
-        var suffix = "txt";
-        if ($scope.exportedType == 'application/xml') {
-            suffix = 'xml';
-        } else if ($scope.exportedType == 'application/json') {
-            suffix = 'json';
-        }
-        saveAs(new Blob([$scope.exported], { type: $scope.exportedType }), 'keycloak.' + suffix);
-    }
-});
-
-module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, $location, $route, Dialog, Notifications, TimeUnit) {
-    console.log('RealmTokenDetailCtrl');
-
-    $scope.realm = realm;
-
-    $scope.realm.accessTokenLifespanUnit = TimeUnit.autoUnit(realm.accessTokenLifespan);
-    $scope.realm.accessTokenLifespan = TimeUnit.toUnit(realm.accessTokenLifespan, $scope.realm.accessTokenLifespanUnit);
-    $scope.$watch('realm.accessTokenLifespanUnit', function(to, from) {
-        $scope.realm.accessTokenLifespan = TimeUnit.convert($scope.realm.accessTokenLifespan, from, to);
-    });
-
-    $scope.realm.ssoSessionIdleTimeoutUnit = TimeUnit.autoUnit(realm.ssoSessionIdleTimeout);
-    $scope.realm.ssoSessionIdleTimeout = TimeUnit.toUnit(realm.ssoSessionIdleTimeout, $scope.realm.ssoSessionIdleTimeoutUnit);
-    $scope.$watch('realm.ssoSessionIdleTimeoutUnit', function(to, from) {
-        $scope.realm.ssoSessionIdleTimeout = TimeUnit.convert($scope.realm.ssoSessionIdleTimeout, from, to);
-    });
-
-    $scope.realm.ssoSessionMaxLifespanUnit = TimeUnit.autoUnit(realm.ssoSessionMaxLifespan);
-    $scope.realm.ssoSessionMaxLifespan = TimeUnit.toUnit(realm.ssoSessionMaxLifespan, $scope.realm.ssoSessionMaxLifespanUnit);
-    $scope.$watch('realm.ssoSessionMaxLifespanUnit', function(to, from) {
-        $scope.realm.ssoSessionMaxLifespan = TimeUnit.convert($scope.realm.ssoSessionMaxLifespan, from, to);
-    });
-
-    $scope.realm.accessCodeLifespanUnit = TimeUnit.autoUnit(realm.accessCodeLifespan);
-    $scope.realm.accessCodeLifespan = TimeUnit.toUnit(realm.accessCodeLifespan, $scope.realm.accessCodeLifespanUnit);
-    $scope.$watch('realm.accessCodeLifespanUnit', function(to, from) {
-        $scope.realm.accessCodeLifespan = TimeUnit.convert($scope.realm.accessCodeLifespan, from, to);
-    });
-
-    $scope.realm.accessCodeLifespanLoginUnit = TimeUnit.autoUnit(realm.accessCodeLifespanLogin);
-    $scope.realm.accessCodeLifespanLogin = TimeUnit.toUnit(realm.accessCodeLifespanLogin, $scope.realm.accessCodeLifespanLoginUnit);
-    $scope.$watch('realm.accessCodeLifespanLoginUnit', function(to, from) {
-        $scope.realm.accessCodeLifespanLogin = TimeUnit.convert($scope.realm.accessCodeLifespanLogin, from, to);
-    });
-
-    $scope.realm.accessCodeLifespanUserActionUnit = TimeUnit.autoUnit(realm.accessCodeLifespanUserAction);
-    $scope.realm.accessCodeLifespanUserAction = TimeUnit.toUnit(realm.accessCodeLifespanUserAction, $scope.realm.accessCodeLifespanUserActionUnit);
-    $scope.$watch('realm.accessCodeLifespanUserActionUnit', function(to, from) {
-        $scope.realm.accessCodeLifespanUserAction = TimeUnit.convert($scope.realm.accessCodeLifespanUserAction, from, to);
-    });
-
-    var oldCopy = angular.copy($scope.realm);
-    $scope.changed = false;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        delete realmCopy["accessTokenLifespanUnit"];
-        delete realmCopy["ssoSessionMaxLifespanUnit"];
-        delete realmCopy["accessCodeLifespanUnit"];
-        delete realmCopy["ssoSessionIdleTimeoutUnit"];
-        delete realmCopy["accessCodeLifespanUserActionUnit"];
-        delete realmCopy["accessCodeLifespanLoginUnit"];
-
-        realmCopy.accessTokenLifespan = TimeUnit.toSeconds($scope.realm.accessTokenLifespan, $scope.realm.accessTokenLifespanUnit)
-        realmCopy.ssoSessionIdleTimeout = TimeUnit.toSeconds($scope.realm.ssoSessionIdleTimeout, $scope.realm.ssoSessionIdleTimeoutUnit)
-        realmCopy.ssoSessionMaxLifespan = TimeUnit.toSeconds($scope.realm.ssoSessionMaxLifespan, $scope.realm.ssoSessionMaxLifespanUnit)
-        realmCopy.accessCodeLifespan = TimeUnit.toSeconds($scope.realm.accessCodeLifespan, $scope.realm.accessCodeLifespanUnit)
-        realmCopy.accessCodeLifespanUserAction = TimeUnit.toSeconds($scope.realm.accessCodeLifespanUserAction, $scope.realm.accessCodeLifespanUserActionUnit)
-        realmCopy.accessCodeLifespanLogin = TimeUnit.toSeconds($scope.realm.accessCodeLifespanLogin, $scope.realm.accessCodeLifespanLoginUnit)
-
-        Realm.update(realmCopy, function () {
-            $route.reload();
-            Notifications.success("The changes have been saved to the realm.");
-        });
-    };
-
-    $scope.reset = function() {
-        $route.reload();
-    };
-});
-
-module.controller('RealmKeysDetailCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-
-    $scope.generate = function() {
-        Dialog.confirmGenerateKeys($scope.realm.realm, 'realm', function() {
-                Realm.update({ realm: realm.realm, publicKey : 'GENERATE' }, function () {
-                Notifications.success('New keys generated for realm.');
-                Realm.get({ id : realm.realm }, function(updated) {
-                    $scope.realm = updated;
-                })
-            });
-        });
-    };
-});
-
-module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmClientSessionStats, RealmLogoutAll, Notifications) {
-    $scope.realm = realm;
-    $scope.stats = stats;
-
-    $scope.logoutAll = function() {
-        RealmLogoutAll.save({realm : realm.realm}, function (globalReqResult) {
-            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
-            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
-
-            if (failedCount > 0) {
-                var msgStart = successCount>0 ? 'Successfully logout all users under: ' + globalReqResult.successRequests + ' . ' : '';
-                Notifications.error(msgStart + 'Failed to logout users under: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
-            } else {
-                window.location.reload();
-            }
-        });
-    };
-});
-
-
-module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevocation, realm, $http, $location, Dialog, Notifications) {
-    $scope.realm = angular.copy(realm);
-
-    var setNotBefore = function() {
-        if ($scope.realm.notBefore == 0) {
-            $scope.notBefore = "None";
-        } else {
-            $scope.notBefore = new Date($scope.realm.notBefore * 1000);
-        }
-    };
-
-    setNotBefore();
-
-    var reset = function() {
-        Realm.get({ id : realm.realm }, function(updated) {
-            $scope.realm = updated;
-            setNotBefore();
-        })
-
-    };
-
-    $scope.clear = function() {
-        Realm.update({ realm: realm.realm, notBefore : 0 }, function () {
-            $scope.notBefore = "None";
-            Notifications.success('Not Before cleared for realm.');
-            reset();
-        });
-    }
-    $scope.setNotBeforeNow = function() {
-        Realm.update({ realm: realm.realm, notBefore : new Date().getTime()/1000}, function () {
-            Notifications.success('Not Before set for realm.');
-            reset();
-        });
-    }
-    $scope.pushRevocation = function() {
-        RealmPushRevocation.save({ realm: realm.realm}, function (globalReqResult) {
-            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
-            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
-
-            if (successCount==0 && failedCount==0) {
-                Notifications.warn('No push sent. No admin URI configured or no registered cluster nodes available');
-            } else if (failedCount > 0) {
-                var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
-                Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
-            } else {
-                Notifications.success('Successfully push notBefore to all configured clients');
-            }
-        });
-    }
-
-});
-
-
-module.controller('RoleListCtrl', function($scope, $location, realm, roles) {
-
-    $scope.realm = realm;
-    $scope.roles = roles;
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-});
-
-
-module.controller('RoleDetailCtrl', function($scope, realm, role, roles, clients,
-                                             Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
-                                             $http, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.role = angular.copy(role);
-    $scope.create = !role.name;
-
-    $scope.changed = $scope.create;
-
-    $scope.save = function() {
-        console.log('save');
-        if ($scope.create) {
-            Role.save({
-                realm: realm.realm
-            }, $scope.role, function (data, headers) {
-                $scope.changed = false;
-                role = angular.copy($scope.role);
-
-                Role.get({ realm: realm.realm, role: role.name }, function(role) {
-                    var id = role.id;
-                    $location.url("/realms/" + realm.realm + "/roles/" + id);
-                    Notifications.success("The role has been created.");
-                });
-            });
-        } else {
-            $scope.update();
-        }
-    };
-
-    $scope.remove = function () {
-        Dialog.confirmDelete($scope.role.name, 'role', function () {
-            $scope.role.$remove({
-                realm: realm.realm,
-                role: $scope.role.id
-            }, function () {
-                $location.url("/realms/" + realm.realm + "/roles");
-                Notifications.success("The role has been deleted.");
-            });
-        });
-    };
-
-    $scope.cancel = function () {
-        $location.url("/realms/" + realm.realm + "/roles");
-    };
-
-
-
-    roleControl($scope, realm, role, roles, clients,
-        ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
-        $http, $location, Notifications, Dialog);
-});
-
-module.controller('RealmSMTPSettingsCtrl', function($scope, Current, Realm, realm, $http, $location, Dialog, Notifications) {
-    console.log('RealmSMTPSettingsCtrl');
-
-    var booleanSmtpAtts = ["auth","ssl","starttls"];
-
-    $scope.realm = realm;
-
-    if ($scope.realm.smtpServer) {
-        $scope.realm.smtpServer = typeObject($scope.realm.smtpServer);
-    };
-
-    var oldCopy = angular.copy($scope.realm);
-    $scope.changed = false;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        realmCopy['smtpServer'] = detypeObject(realmCopy.smtpServer);
-        $scope.changed = false;
-        Realm.update(realmCopy, function () {
-            $location.url("/realms/" + realm.realm + "/smtp-settings");
-            Notifications.success("Your changes have been saved to the realm.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.realm = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-
-    /* Convert string attributes containing a boolean to actual boolean type + convert an integer string (port) to integer. */
-    function typeObject(obj){
-        for (var att in obj){
-            if (booleanSmtpAtts.indexOf(att) < 0)
-                continue;
-            if (obj[att] === "true"){
-                obj[att] = true;
-            } else if (obj[att] === "false"){
-                obj[att] = false;
-            }
-        }
-
-        obj['port'] = parseInt(obj['port']);
-
-        return obj;
-    }
-
-    /* Convert all non-string values to strings to invert changes caused by the typeObject function. */
-    function detypeObject(obj){
-        for (var att in obj){
-            if (booleanSmtpAtts.indexOf(att) < 0)
-                continue;
-            if (obj[att] === true){
-                obj[att] = "true";
-            } else if (obj[att] === false){
-                obj[att] = "false"
-            }
-        }
-
-        obj['port'] = obj['port'].toString();
-
-        return obj;
-    }
-});
-
-module.controller('RealmEventsConfigCtrl', function($scope, eventsConfig, RealmEventsConfig, RealmEvents, RealmAdminEvents, realm, serverInfo, $location, Notifications, TimeUnit, Dialog) {
-    $scope.realm = realm;
-
-    $scope.eventsConfig = eventsConfig;
-
-    $scope.eventsConfig.expirationUnit = TimeUnit.autoUnit(eventsConfig.eventsExpiration);
-    $scope.eventsConfig.eventsExpiration = TimeUnit.toUnit(eventsConfig.eventsExpiration, $scope.eventsConfig.expirationUnit);
-    $scope.$watch('eventsConfig.expirationUnit', function(to, from) {
-        if ($scope.eventsConfig.eventsExpiration) {
-            $scope.eventsConfig.eventsExpiration = TimeUnit.convert($scope.eventsConfig.eventsExpiration, from, to);
-        }
-    });
-
-    $scope.eventListeners = serverInfo.eventListeners;
-
-    $scope.eventSelectOptions = {
-        'multiple': true,
-        'simple_tags': true,
-        'tags': serverInfo.enums['eventType']
-    };
-
-    var oldCopy = angular.copy($scope.eventsConfig);
-    $scope.changed = false;
-
-    $scope.$watch('eventsConfig', function() {
-        if (!angular.equals($scope.eventsConfig, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        $scope.changed = false;
-
-        var copy = angular.copy($scope.eventsConfig)
-        delete copy['expirationUnit'];
-
-        copy.eventsExpiration = TimeUnit.toSeconds($scope.eventsConfig.eventsExpiration, $scope.eventsConfig.expirationUnit);
-
-        RealmEventsConfig.update({
-            id : realm.realm
-        }, copy, function () {
-            $location.url("/realms/" + realm.realm + "/events-settings");
-            Notifications.success("Your changes have been saved to the realm.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.eventsConfig = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-
-    $scope.clearEvents = function() {
-        Dialog.confirmDelete($scope.realm.realm, 'events', function() {
-            RealmEvents.remove({ id : $scope.realm.realm }, function() {
-                Notifications.success("The events has been cleared.");
-            });
-        });
-    };
-    
-    $scope.clearAdminEvents = function() {
-        Dialog.confirmDelete($scope.realm.realm, 'admin-events', function() {
-            RealmAdminEvents.remove({ id : $scope.realm.realm }, function() {
-                Notifications.success("The admin events has been cleared.");
-            });
-        });
-    };
-});
-
-module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm, serverInfo) {
-    $scope.realm = realm;
-    $scope.page = 0;
-    
-    $scope.eventSelectOptions = {
-        'multiple': true,
-        'simple_tags': true,
-        'tags': serverInfo.enums['eventType']
-    };
-
-    $scope.query = {
-        id : realm.realm,
-        max : 5,
-        first : 0
-    }
-
-    $scope.update = function() {
-    	$scope.query.first = 0;
-        for (var i in $scope.query) {
-            if ($scope.query[i] === '') {
-                delete $scope.query[i];
-           }
-        }
-        $scope.events = RealmEvents.query($scope.query);
-    }
-    
-    $scope.reset = function() {
-    	$scope.query.first = 0;
-    	$scope.query.max = 5;
-    	$scope.query.type = '';
-    	$scope.query.client = '';
-    	$scope.query.user = '';
-    	$scope.query.dateFrom = '';
-    	$scope.query.dateTo = '';
-    	
-    	$scope.update();
-    }
-    
-    $scope.queryUpdate = function() {
-        for (var i in $scope.query) {
-            if ($scope.query[i] === '') {
-                delete $scope.query[i];
-           }
-        }
-        $scope.events = RealmEvents.query($scope.query);
-    }
-    
-    $scope.firstPage = function() {
-        $scope.query.first = 0;
-        $scope.queryUpdate();
-    }
-
-    $scope.previousPage = function() {
-        $scope.query.first -= parseInt($scope.query.max);
-        if ($scope.query.first < 0) {
-            $scope.query.first = 0;
-        }
-        $scope.queryUpdate();
-    }
-
-    $scope.nextPage = function() {
-        $scope.query.first += parseInt($scope.query.max);
-        $scope.queryUpdate();
-    }
-
-    $scope.update();
-});
-
-module.controller('RealmAdminEventsCtrl', function($scope, RealmAdminEvents, realm, serverInfo, $modal, $filter) {
-    $scope.realm = realm;
-    $scope.page = 0;
-
-    $scope.query = {
-    	id : realm.realm,
-        max : 5,
-        first : 0
-    }
-
-    $scope.adminEnabledEventOperationsOptions = {
-        'multiple': true,
-        'simple_tags': true,
-        'tags': serverInfo.enums['operationType']
-    };
-    
-    $scope.update = function() {
-    	$scope.query.first = 0;
-        for (var i in $scope.query) {
-            if ($scope.query[i] === '') {
-                delete $scope.query[i];
-           }
-        }
-        $scope.events = RealmAdminEvents.query($scope.query);
-    }
-    
-    $scope.reset = function() {
-    	$scope.query.first = 0;
-    	$scope.query.max = 5;
-    	$scope.query.operationTypes = '';
-    	$scope.query.resourcePath = '';
-    	$scope.query.authRealm = '';
-    	$scope.query.authClient = '';
-    	$scope.query.authUser = '';
-    	$scope.query.authIpAddress = '';
-    	$scope.query.dateFrom = '';
-    	$scope.query.dateTo = '';
-    	
-    	$scope.update();
-    }
-    
-    $scope.queryUpdate = function() {
-        for (var i in $scope.query) {
-            if ($scope.query[i] === '') {
-                delete $scope.query[i];
-           }
-        }
-        $scope.events = RealmAdminEvents.query($scope.query);
-    }
-    
-    $scope.firstPage = function() {
-        $scope.query.first = 0;
-        $scope.queryUpdate();
-    }
-
-    $scope.previousPage = function() {
-        $scope.query.first -= parseInt($scope.query.max);
-        if ($scope.query.first < 0) {
-            $scope.query.first = 0;
-        }
-        $scope.queryUpdate();
-    }
-
-    $scope.nextPage = function() {
-        $scope.query.first += parseInt($scope.query.max);
-        $scope.queryUpdate();
-    }
-
-    $scope.update();
-    
-    $scope.viewRepresentation = function(event) {
-        $modal.open({
-            templateUrl: resourceUrl + '/partials/modal/realm-events-admin-representation.html',
-            controller: 'RealmAdminEventsModalCtrl',
-            resolve: {
-                event: function () {
-                    return event;
-                }
-            }
-        })
-    }
-
-    $scope.viewAuth = function(event) {
-        $modal.open({
-            templateUrl: resourceUrl + '/partials/modal/realm-events-admin-auth.html',
-            controller: 'RealmAdminEventsModalCtrl',
-            resolve: {
-                event: function () {
-                    return event;
-                }
-            }
-        })
-    }
-});
-
-module.controller('RealmAdminEventsModalCtrl', function($scope, $filter, event) {
-    $scope.event = event;
-});
-
-module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, TimeUnit) {
-    console.log('RealmBruteForceCtrl');
-
-    $scope.realm = realm;
-
-    $scope.realm.waitIncrementUnit = TimeUnit.autoUnit(realm.waitIncrementSeconds);
-    $scope.realm.waitIncrement = TimeUnit.toUnit(realm.waitIncrementSeconds, $scope.realm.waitIncrementUnit);
-    $scope.$watch('realm.waitIncrementUnit', function(to, from) {
-        $scope.realm.waitIncrement = TimeUnit.convert($scope.realm.waitIncrement, from, to);
-    });
-
-    $scope.realm.minimumQuickLoginWaitUnit = TimeUnit.autoUnit(realm.minimumQuickLoginWaitSeconds);
-    $scope.realm.minimumQuickLoginWait = TimeUnit.toUnit(realm.minimumQuickLoginWaitSeconds, $scope.realm.minimumQuickLoginWaitUnit);
-    $scope.$watch('realm.minimumQuickLoginWaitUnit', function(to, from) {
-        $scope.realm.minimumQuickLoginWait = TimeUnit.convert($scope.realm.minimumQuickLoginWait, from, to);
-    });
-
-    $scope.realm.maxFailureWaitUnit = TimeUnit.autoUnit(realm.maxFailureWaitSeconds);
-    $scope.realm.maxFailureWait = TimeUnit.toUnit(realm.maxFailureWaitSeconds, $scope.realm.maxFailureWaitUnit);
-    $scope.$watch('realm.maxFailureWaitUnit', function(to, from) {
-        $scope.realm.maxFailureWait = TimeUnit.convert($scope.realm.maxFailureWait, from, to);
-    });
-
-    $scope.realm.maxDeltaTimeUnit = TimeUnit.autoUnit(realm.maxDeltaTimeSeconds);
-    $scope.realm.maxDeltaTime = TimeUnit.toUnit(realm.maxDeltaTimeSeconds, $scope.realm.maxDeltaTimeUnit);
-    $scope.$watch('realm.maxDeltaTimeUnit', function(to, from) {
-        $scope.realm.maxDeltaTime = TimeUnit.convert($scope.realm.maxDeltaTime, from, to);
-    });
-
-    var oldCopy = angular.copy($scope.realm);
-    $scope.changed = false;
-
-    $scope.$watch('realm', function() {
-        if (!angular.equals($scope.realm, oldCopy)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        var realmCopy = angular.copy($scope.realm);
-        delete realmCopy["waitIncrementUnit"];
-        delete realmCopy["waitIncrement"];
-        delete realmCopy["minimumQuickLoginWaitUnit"];
-        delete realmCopy["minimumQuickLoginWait"];
-        delete realmCopy["maxFailureWaitUnit"];
-        delete realmCopy["maxFailureWait"];
-        delete realmCopy["maxDeltaTimeUnit"];
-        delete realmCopy["maxDeltaTime"];
-
-        realmCopy.waitIncrementSeconds = TimeUnit.toSeconds($scope.realm.waitIncrement, $scope.realm.waitIncrementUnit)
-        realmCopy.minimumQuickLoginWaitSeconds = TimeUnit.toSeconds($scope.realm.minimumQuickLoginWait, $scope.realm.minimumQuickLoginWaitUnit)
-        realmCopy.maxFailureWaitSeconds = TimeUnit.toSeconds($scope.realm.maxFailureWait, $scope.realm.maxFailureWaitUnit)
-        realmCopy.maxDeltaTimeSeconds = TimeUnit.toSeconds($scope.realm.maxDeltaTime, $scope.realm.maxDeltaTimeUnit)
-
-        $scope.changed = false;
-        Realm.update(realmCopy, function () {
-            $location.url("/realms/" + realm.realm + "/defense/brute-force");
-            Notifications.success("Your changes have been saved to the realm.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.realm = angular.copy(oldCopy);
-        $scope.changed = false;
-    };
-});
-
-
-module.controller('IdentityProviderMapperListCtrl', function($scope, realm, identityProvider, mapperTypes, mappers) {
-    $scope.realm = realm;
-    $scope.identityProvider = identityProvider;
-    $scope.mapperTypes = mapperTypes;
-    $scope.mappers = mappers;
-});
-
-module.controller('IdentityProviderMapperCtrl', function($scope, realm,  identityProvider, mapperTypes, mapper, IdentityProviderMapper, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.identityProvider = identityProvider;
-    $scope.create = false;
-    $scope.mapper = angular.copy(mapper);
-    $scope.changed = false;
-    $scope.mapperType = mapperTypes[mapper.identityProviderMapper];
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.$watch('mapper', function() {
-        if (!angular.equals($scope.mapper, mapper)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        IdentityProviderMapper.update({
-            realm : realm.realm,
-            alias: identityProvider.alias,
-            mapperId : mapper.id
-        }, $scope.mapper, function() {
-            $scope.changed = false;
-            mapper = angular.copy($scope.mapper);
-            $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers/" + mapper.id);
-            Notifications.success("Your changes have been saved.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.mapper = angular.copy(mapper);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
-            IdentityProviderMapper.remove({ realm: realm.realm, alias: mapper.identityProviderAlias, mapperId : $scope.mapper.id }, function() {
-                Notifications.success("The mapper has been deleted.");
-                $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers");
-            });
-        });
-    };
-
-});
-
-module.controller('IdentityProviderMapperCreateCtrl', function($scope, realm, identityProvider, mapperTypes, IdentityProviderMapper, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.identityProvider = identityProvider;
-    $scope.create = true;
-    $scope.mapper = { identityProviderAlias: identityProvider.alias, config: {}};
-    $scope.mapperTypes = mapperTypes;
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.save = function() {
-        $scope.mapper.identityProviderMapper = $scope.mapperType.id;
-        IdentityProviderMapper.save({
-            realm : realm.realm, alias: identityProvider.alias
-        }, $scope.mapper, function(data, headers) {
-            var l = headers().location;
-            var id = l.substring(l.lastIndexOf("/") + 1);
-            $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers/" + id);
-            Notifications.success("Mapper has been created.");
-        });
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-
-});
-
-module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, AuthenticationExecutions, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.flows = flows;
-    if (flows.length > 0) {
-        $scope.flow = flows[0];
-    }
-    var setupForm = function() {
-        AuthenticationExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
-            $scope.executions = data;
-            $scope.flowmax = 0;
-            for (var i = 0; i < $scope.executions.length; i++ ) {
-                execution = $scope.executions[i];
-                if (execution.requirementChoices.length > $scope.flowmax) {
-                    $scope.flowmax = execution.requirementChoices.length;
-                }
-            }
-            for (var i = 0; i < $scope.executions.length; i++ ) {
-                execution = $scope.executions[i];
-                execution.empties = [];
-                for (j = 0; j < $scope.flowmax - execution.requirementChoices.length; j++) {
-                    execution.empties.push(j);
-                }
-            }
-        })
-    };
-
-    $scope.updateExecution = function(execution) {
-        var copy = angular.copy(execution);
-        delete copy.empties;
-        AuthenticationExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
-            Notifications.success("Auth requirement updated");
-            setupForm();
-        });
-
-    };
-    $scope.setupForm = setupForm;
-
-    setupForm();
-
-
-});
-
-module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications, Dialog, $location) {
-    console.log('RequiredActionsCtrl');
-    $scope.realm = realm;
-    $scope.requiredActions = [];
-    var setupRequiredActionsForm = function() {
-        console.log('setupRequiredActionsForm');
-        RequiredActions.query({id: realm.realm}, function(data) {
-            $scope.requiredActions = [];
-            for (var i = 0; i < data.length; i++) {
-                $scope.requiredActions.push(data[i]);
-            }
-        });
-    };
-
-    $scope.updateRequiredAction = function(action) {
-        RequiredActions.update({id: realm.realm, alias: action.alias}, action, function() {
-            Notifications.success("Required action updated");
-            setupRequiredActionsForm();
-        });
-    }
-
-    setupRequiredActionsForm();
-
-
-});
-
-module.controller('AuthenticationConfigCtrl', function($scope, realm, configType, config, AuthenticationConfig, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.configType = configType;
-    $scope.create = false;
-    $scope.config = angular.copy(config);
-    $scope.changed = false;
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.$watch('config', function() {
-        if (!angular.equals($scope.config, config)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        AuthenticationConfig.update({
-            realm : realm.realm,
-            config : config.id
-        }, $scope.config, function() {
-            $scope.changed = false;
-            config = angular.copy($scope.config);
-            $location.url("/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + config.id);
-            Notifications.success("Your changes have been saved.");
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.config = angular.copy(config);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.config.alias, 'config', function() {
-            AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() {
-                Notifications.success("The config has been deleted.");
-                $location.url("/realms/" + realm.realm + '/authentication/flows');
-            });
-        });
-    };
-
-});
-
-module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, configType, execution, AuthenticationExecutionConfig, Notifications, Dialog, $location) {
-    $scope.realm = realm;
-    $scope.create = true;
-    $scope.config = { config: {}};
-    $scope.configType = configType;
-
-    $scope.$watch(function() {
-        return $location.path();
-    }, function() {
-        $scope.path = $location.path().substring(1).split("/");
-    });
-
-    $scope.save = function() {
-        AuthenticationExecutionConfig.save({
-            realm : realm.realm,
-            execution: execution
-        }, $scope.config, function(data, headers) {
-            var l = headers().location;
-            var id = l.substring(l.lastIndexOf("/") + 1);
-            var url = "/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + id;
-            console.log('redirect url: ' + url);
-            $location.url(url);
-            Notifications.success("Config has been created.");
-        });
-    };
-
-    $scope.cancel = function() {
-        //$location.url("/realms");
-        window.history.back();
-    };
-
-
-});
-
-
-
-
-
-
-
-
+module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $location, Notifications, ServerInfo) {
+    $scope.addMessage = function() {
+        Notifications.success("test");
+    };
+
+    $scope.authUrl = authUrl;
+    $scope.resourceUrl = resourceUrl;
+    $scope.auth = Auth;
+    $scope.serverInfo = ServerInfo.get();
+    $scope.serverInfoUpdate = function() {
+        $scope.serverInfo = ServerInfo.get();
+    };
+
+    function hasAnyAccess() {
+        var realmAccess = Auth.user && Auth.user['realm_access'];
+        if (realmAccess) {
+            for (var p in realmAccess){
+                return true;
+            }
+            return false;
+        } else {
+            return false;
+        }
+    }
+
+    WhoAmI.get(function (data) {
+        Auth.user = data;
+        Auth.loggedIn = true;
+        Auth.hasAnyAccess = hasAnyAccess();
+    });
+
+    function getAccess(role) {
+        if (!Current.realm) {
+            return false;
+        }
+
+        var realmAccess = Auth.user && Auth.user['realm_access'];
+        if (realmAccess) {
+            realmAccess = realmAccess[Current.realm.realm];
+            if (realmAccess) {
+                return realmAccess.indexOf(role) >= 0;
+            }
+        }
+        return false;
+    }
+
+    $scope.access = {
+        get createRealm() {
+            return Auth.user && Auth.user.createRealm;
+        },
+
+        get viewRealm() {
+            return getAccess('view-realm') || this.manageRealm;
+        },
+
+        get viewClients() {
+            return getAccess('view-clients') || this.manageClients;
+        },
+
+        get viewUsers() {
+            return getAccess('view-users') || this.manageClients;
+        },
+
+        get viewEvents() {
+            return getAccess('view-events') || this.manageClients;
+        },
+
+        get manageRealm() {
+            return getAccess('manage-realm');
+        },
+
+        get manageClients() {
+            return getAccess('manage-clients');
+        },
+
+        get manageUsers() {
+            return getAccess('manage-users');
+        },
+
+        get manageEvents() {
+            return getAccess('manage-events');
+        },
+        get impersonation() {
+            return getAccess('impersonation');
+        }
+    }
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.fragment = $location.path();
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+module.controller('HomeCtrl', function(Realm, Auth, $location) {
+    Realm.query(null, function(realms) {
+        var realm;
+        if (realms.length == 1) {
+            realm = realms[0].realm;
+        } else if (realms.length == 2) {
+            if (realms[0].realm == Auth.user.realm) {
+                realm = realms[1].realm;
+            } else if (realms[1].realm == Auth.user.realm) {
+                realm = realms[0].realm;
+            }
+        }
+        if (realm) {
+            $location.url('/realms/' + realm);
+        } else {
+            $location.url('/realms');
+        }
+    });
+});
+
+module.controller('RealmListCtrl', function($scope, Realm, Current) {
+    $scope.realms = Realm.query();
+    Current.realms = $scope.realms;
+});
+
+module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $location) {
+//    Current.realms = Realm.get();
+    $scope.current = Current;
+
+    $scope.changeRealm = function(selectedRealm) {
+        $location.url("/realms/" + selectedRealm);
+    }
+});
+
+module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, Dialog, Notifications, Auth) {
+    console.log('RealmCreateCtrl');
+
+    Current.realm = null;
+
+    $scope.realm = {
+        enabled: true
+    };
+
+    $scope.changed = false;
+    $scope.files = [];
+
+    var oldCopy = angular.copy($scope.realm);
+
+    $scope.onFileSelect = function($files) {
+        $scope.files = $files;
+    };
+
+    $scope.clearFileSelect = function() {
+        $scope.files = null;
+    }
+
+    $scope.uploadFile = function() {
+        //$files: an array of files selected, each file has name, size, and type.
+        for (var i = 0; i < $scope.files.length; i++) {
+            var $file = $scope.files[i];
+            $scope.upload = $upload.upload({
+                url: authUrl + '/admin/realms', //upload.php script, node.js route, or servlet url
+                // method: POST or PUT,
+                // headers: {'headerKey': 'headerValue'}, withCredential: true,
+                data: {myObj: ""},
+                file: $file
+                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
+                //fileFormDataName: myFile,
+                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
+                //formDataAppender: function(formData, key, val){}
+            }).progress(function(evt) {
+                    console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
+                }).success(function(data, status, headers) {
+                    Realm.query(function(data) {
+                        Current.realms = data;
+
+
+                        WhoAmI.get(function(user) {
+                            Auth.user = user;
+
+                            Notifications.success("The realm has been uploaded.");
+
+                            var location = headers('Location');
+                            if (location) {
+                                $location.url("/realms/" + location.substring(location.lastIndexOf('/') + 1));
+                            } else {
+                                $location.url("/realms");
+                            }
+                        });
+                    });
+                })
+            .error(function() {
+                    Notifications.error("The realm can not be uploaded. Please verify the file.");
+
+                });
+            //.then(success, error, progress);
+        }
+    };
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        Realm.create(realmCopy, function() {
+            Realm.query(function(data) {
+                Current.realms = data;
+
+                WhoAmI.get(function(user) {
+                    Auth.user = user;
+
+                    $location.url("/realms/" + realmCopy.realm);
+                    Notifications.success("The realm has been created.");
+                });
+            });
+        });
+    };
+
+    $scope.cancel = function() {
+        window.history.back();
+    };
+});
+
+
+module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, WhoAmI, Auth) {
+    $scope.createRealm = !realm.realm;
+    $scope.serverInfo = serverInfo;
+
+    if (Current.realm == null || Current.realm.realm != realm.realm) {
+        for (var i = 0; i < Current.realms.length; i++) {
+            if (realm.realm == Current.realms[i].realm) {
+                Current.realm = Current.realms[i];
+                break;
+            }
+        }
+    }
+    for (var i = 0; i < Current.realms.length; i++) {
+        if (Current.realms[i].realm == realm.realm) {
+            Current.realm = Current.realms[i];
+        }
+    }
+    $scope.realm = angular.copy(realm);
+
+    var oldCopy = angular.copy($scope.realm);
+
+    $scope.changed = $scope.create;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        $scope.changed = false;
+        var nameChanged = !angular.equals($scope.realm.realm, oldCopy.realm)
+        Realm.update({ id : oldCopy.realm}, realmCopy, function () {
+            var data = Realm.query(function () {
+                Current.realms = data;
+                for (var i = 0; i < Current.realms.length; i++) {
+                    if (Current.realms[i].realm == realmCopy.realm) {
+                        Current.realm = Current.realms[i];
+                        oldCopy = angular.copy($scope.realm);
+                    }
+                }
+            });
+
+            if (nameChanged) {
+                WhoAmI.get(function(user) {
+                    Auth.user = user;
+
+                    $location.url("/realms/" + realmCopy.realm);
+                    Notifications.success("Your changes have been saved to the realm.");
+                });
+            } else {
+                $location.url("/realms/" + realmCopy.realm);
+                Notifications.success("Your changes have been saved to the realm.");
+            }
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        window.history.back();
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.realm.realm, 'realm', function() {
+            Realm.remove({ id : $scope.realm.realm }, function() {
+                Current.realms = Realm.query();
+                Notifications.success("The realm has been deleted.");
+                $location.url("/");
+            });
+        });
+    };
+});
+
+function genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, url) {
+    $scope.realm = angular.copy(realm);
+    $scope.serverInfo = serverInfo;
+    $scope.registrationAllowed = $scope.realm.registrationAllowed;
+
+    var oldCopy = angular.copy($scope.realm);
+
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        console.log('updating realm...');
+        $scope.changed = false;
+        console.log('oldCopy.realm - ' + oldCopy.realm);
+        Realm.update({ id : oldCopy.realm}, realmCopy, function () {
+            var data = Realm.query(function () {
+                Current.realms = data;
+                for (var i = 0; i < Current.realms.length; i++) {
+                    if (Current.realms[i].realm == realmCopy.realm) {
+                        Current.realm = Current.realms[i];
+                        oldCopy = angular.copy($scope.realm);
+                    }
+                }
+            });
+            $location.url(url);
+            Notifications.success("Your changes have been saved to the realm.");
+            $scope.registrationAllowed = $scope.realm.registrationAllowed;
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+}
+
+module.controller('DefenseHeadersCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
+    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/defense/headers");
+});
+
+module.controller('RealmLoginSettingsCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
+    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/login-settings");
+});
+
+module.controller('RealmThemeCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
+    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/theme-settings");
+
+    $scope.supportedLocalesOptions = {
+        'multiple' : true,
+        'simple_tags' : true,
+        'tags' : ['en', 'de', 'pt-BR', 'it']
+    };
+
+    $scope.$watch('realm.supportedLocales', function(oldVal, newVal) {
+        if(angular.isUndefined(newVal) || (angular.isArray(newVal) && newVal.length == 0)){
+            $scope.realm.defaultLocale = undefined;
+        }
+    }, true);
+});
+
+module.controller('RealmCacheCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
+    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/cache-settings");
+});
+
+module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, PasswordPolicy) {
+    console.log('RealmPasswordPolicyCtrl');
+
+    $scope.realm = realm;
+
+    var oldCopy = angular.copy($scope.realm);
+
+    $scope.allPolicies = PasswordPolicy.allPolicies;
+    $scope.policyMessages = PasswordPolicy.policyMessages;
+
+    $scope.policy = PasswordPolicy.parse(realm.passwordPolicy);
+    var oldPolicy = angular.copy($scope.policy);
+
+    $scope.addPolicy = function(policy){
+        if (!$scope.policy) {
+            $scope.policy = [];
+        }
+        $scope.policy.push(policy);
+    }
+
+    $scope.removePolicy = function(index){
+        $scope.policy.splice(index, 1);
+    }
+
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.$watch('policy', function(oldVal, newVal) {
+        if (!angular.equals($scope.policy, oldPolicy)) {
+            $scope.realm.passwordPolicy = PasswordPolicy.toString($scope.policy);
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        $scope.changed = false;
+
+        Realm.update($scope.realm, function () {
+            $location.url("/realms/" + realm.realm + "/authentication/password-policy");
+            Notifications.success("Your changes have been saved to the realm.");
+            oldCopy = angular.copy($scope.realm);
+            oldPolicy = angular.copy($scope.policy);
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.policy = angular.copy(oldPolicy);
+        $scope.changed = false;
+    };
+});
+
+module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, clients, roles, Notifications, ClientRole, Client) {
+
+    console.log('RealmDefaultRolesCtrl');
+
+    $scope.realm = realm;
+
+    $scope.availableRealmRoles = [];
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmDefRoles = [];
+
+    $scope.clients = angular.copy(clients);
+    for (var i = 0; i < clients.length; i++) {
+        if (clients[i].name == 'account') {
+            $scope.client = $scope.clients[i];
+            break;
+        }
+    }
+
+    $scope.availableClientRoles = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientDefRoles = [];
+
+    if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) {
+        $scope.realm.defaultRoles = [];
+    }
+
+    // Populate available roles. Available roles are neither already assigned
+    for (var i = 0; i < roles.length; i++) {
+        var item = roles[i].name;
+
+        if ($scope.realm.defaultRoles.indexOf(item) < 0) {
+            $scope.availableRealmRoles.push(item);
+        }
+    }
+
+    $scope.addRealmDefaultRole = function () {
+
+        // Remove selected roles from the Available roles and add them to realm default roles (move from left to right).
+        for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
+            var selectedRole = $scope.selectedRealmRoles[i];
+
+            $scope.realm.defaultRoles.push(selectedRole);
+
+            var index = $scope.availableRealmRoles.indexOf(selectedRole);
+            if (index > -1) {
+                $scope.availableRealmRoles.splice(index, 1);
+            }
+        }
+
+        $scope.selectedRealmRoles = [];
+
+        // Update/save the realm with new default roles.
+        Realm.update($scope.realm, function () {
+            Notifications.success("Realm default roles updated.");
+        });
+    };
+
+    $scope.deleteRealmDefaultRole = function () {
+
+        // Remove selected roles from the realm default roles and add them to available roles (move from right to left).
+        for (var i = 0; i < $scope.selectedRealmDefRoles.length; i++) {
+            $scope.availableRealmRoles.push($scope.selectedRealmDefRoles[i]);
+
+            var index = $scope.realm.defaultRoles.indexOf($scope.selectedRealmDefRoles[i]);
+            if (index > -1) {
+                $scope.realm.defaultRoles.splice(index, 1);
+            }
+        }
+
+        $scope.selectedRealmDefRoles = [];
+
+        // Update/save the realm with new default roles.
+        //var realmCopy = angular.copy($scope.realm);
+        Realm.update($scope.realm, function () {
+            Notifications.success("Realm default roles updated.");
+        });
+    };
+
+    $scope.changeClient = function () {
+
+        $scope.selectedClientRoles = [];
+        $scope.selectedClientDefRoles = [];
+
+        // Populate available roles for selected client
+        if ($scope.client) {
+            var appDefaultRoles = ClientRole.query({realm: $scope.realm.realm, client: $scope.client.id}, function () {
+
+                if (!$scope.client.hasOwnProperty('defaultRoles') || $scope.client.defaultRoles === null) {
+                    $scope.client.defaultRoles = [];
+                }
+
+                $scope.availableClientRoles = [];
+
+                for (var i = 0; i < appDefaultRoles.length; i++) {
+                    var roleName = appDefaultRoles[i].name;
+                    if ($scope.client.defaultRoles.indexOf(roleName) < 0) {
+                        $scope.availableClientRoles.push(roleName);
+                    }
+                }
+            });
+        } else {
+            $scope.availableClientRoles = null;
+        }
+    };
+
+    $scope.addClientDefaultRole = function () {
+
+        // Remove selected roles from the app available roles and add them to app default roles (move from left to right).
+        for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
+            var role = $scope.selectedClientRoles[i];
+
+            var idx = $scope.client.defaultRoles.indexOf(role);
+            if (idx < 0) {
+                $scope.client.defaultRoles.push(role);
+            }
+
+            idx = $scope.availableClientRoles.indexOf(role);
+
+            if (idx != -1) {
+                $scope.availableClientRoles.splice(idx, 1);
+            }
+        }
+
+        $scope.selectedClientRoles = [];
+
+        // Update/save the selected client with new default roles.
+        Client.update({
+            realm: $scope.realm.realm,
+            client: $scope.client.id
+        }, $scope.client, function () {
+            Notifications.success("Your changes have been saved to the client.");
+        });
+    };
+
+    $scope.rmClientDefaultRole = function () {
+
+        // Remove selected roles from the app default roles and add them to app available roles (move from right to left).
+        for (var i = 0; i < $scope.selectedClientDefRoles.length; i++) {
+            var role = $scope.selectedClientDefRoles[i];
+            var idx = $scope.client.defaultRoles.indexOf(role);
+            if (idx != -1) {
+                $scope.client.defaultRoles.splice(idx, 1);
+            }
+            idx = $scope.availableClientRoles.indexOf(role);
+            if (idx < 0) {
+                $scope.availableClientRoles.push(role);
+            }
+        }
+
+        $scope.selectedClientDefRoles = [];
+
+        // Update/save the selected client with new default roles.
+        Client.update({
+            realm: $scope.realm.realm,
+            client: $scope.client.id
+        }, $scope.client, function () {
+            Notifications.success("Your changes have been saved to the client.");
+        });
+    };
+
+});
+
+module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload, $http, $route, realm, instance, providerFactory, IdentityProvider, serverInfo, $location, Notifications, Dialog) {
+    console.log('RealmIdentityProviderCtrl');
+
+    $scope.realm = angular.copy(realm);
+
+    $scope.initProvider = function() {
+        if (instance && instance.alias) {
+
+        } else {
+            $scope.identityProvider.updateProfileFirstLoginMode = "on";
+        }
+
+    };
+
+    $scope.initSamlProvider = function() {
+        $scope.nameIdFormats = [
+            /*
+            {
+                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+                name: "Transient"
+            },
+            */
+            {
+                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
+                name: "Persistent"
+
+            },
+            {
+                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
+                name: "Email"
+
+            },
+            {
+                format: "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos",
+                name: "Kerberos"
+
+            },
+            {
+                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
+                name: "X.509 Subject Name"
+
+            },
+            {
+                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName",
+                name: "Windows Domain Qualified Name"
+
+            },
+            {
+                format: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
+                name: "Unspecified"
+
+            }
+        ];
+        if (instance && instance.alias) {
+
+        } else {
+            $scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
+            $scope.identityProvider.updateProfileFirstLoginMode = "off";
+        }
+    }
+
+    $scope.hidePassword = true;
+    $scope.fromUrl = {
+        data: ''
+    };
+
+    if (instance && instance.alias) {
+        $scope.identityProvider = angular.copy(instance);
+        $scope.newIdentityProvider = false;
+    } else {
+        $scope.identityProvider = {};
+        $scope.identityProvider.config = {};
+        $scope.identityProvider.alias = providerFactory.id;
+        $scope.identityProvider.providerId = providerFactory.id;
+        $scope.identityProvider.enabled = true;
+        $scope.identityProvider.updateProfileFirstLoginMode = "off";
+        $scope.identityProvider.authenticateByDefault = false;
+        $scope.newIdentityProvider = true;
+    }
+
+    $scope.changed = $scope.newIdentityProvider;
+
+    $scope.$watch('identityProvider', function() {
+        if (!angular.equals($scope.identityProvider, instance)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+
+    $scope.serverInfo = serverInfo;
+
+    $scope.allProviders = angular.copy(serverInfo.identityProviders);
+
+    $scope.configuredProviders = angular.copy(realm.identityProviders);
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+
+    $scope.files = [];
+    $scope.importFile = false;
+    $scope.importUrl = false;
+
+    $scope.onFileSelect = function($files) {
+        $scope.importFile = true;
+        $scope.files = $files;
+    };
+
+    $scope.clearFileSelect = function() {
+        $scope.importUrl = false;
+        $scope.importFile = false;
+        $scope.files = null;
+    };
+
+    var setConfig = function(data) {
+        for (var key in data) {
+            $scope.identityProvider.config[key] = data[key];
+        }
+    }
+
+
+    $scope.uploadFile = function() {
+        if (!$scope.identityProvider.alias) {
+            Notifications.error("You must specify an alias");
+            return;
+        }
+        var input = {
+            providerId: providerFactory.id
+        }
+        //$files: an array of files selected, each file has name, size, and type.
+        for (var i = 0; i < $scope.files.length; i++) {
+            var $file = $scope.files[i];
+            $scope.upload = $upload.upload({
+                url: authUrl + '/admin/realms/' + realm.realm + '/identity-provider/import-config',
+                // method: POST or PUT,
+                // headers: {'headerKey': 'headerValue'}, withCredential: true,
+                data: input,
+                file: $file
+                /* set file formData name for 'Content-Desposition' header. Default: 'file' */
+                //fileFormDataName: myFile,
+                /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
+                //formDataAppender: function(formData, key, val){}
+            }).progress(function(evt) {
+                console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
+            }).success(function(data, status, headers) {
+                setConfig(data);
+                $scope.clearFileSelect();
+                Notifications.success("The IDP metadata has been loaded from file.");
+            }).error(function() {
+                Notifications.error("The file can not be uploaded. Please verify the file.");
+            });
+        }
+    };
+
+    $scope.importFrom = function() {
+        if (!$scope.identityProvider.alias) {
+            Notifications.error("You must specify an alias");
+            return;
+        }
+        var input = {
+            fromUrl: $scope.fromUrl.data,
+            providerId: providerFactory.id
+        }
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/identity-provider/import-config', input)
+            .success(function(data, status, headers) {
+                setConfig(data);
+                $scope.fromUrl.data = '';
+                $scope.importUrl = false;
+                Notifications.success("Imported config information from url.");
+            }).error(function() {
+                Notifications.error("Config can not be imported. Please verify the url.");
+            });
+    };
+    $scope.$watch('fromUrl.data', function(newVal, oldVal){
+        if ($scope.fromUrl.data && $scope.fromUrl.data.length > 0) {
+            $scope.importUrl = true;
+        } else{
+            $scope.importUrl = false;
+        }
+    });
+
+    $scope.$watch('configuredProviders', function(configuredProviders) {
+        if (configuredProviders) {
+            $scope.configuredProviders = angular.copy(configuredProviders);
+
+            for (var j = 0; j < configuredProviders.length; j++) {
+                var configProvidedId = configuredProviders[j].providerId;
+
+                for (var i in $scope.allProviders) {
+                    var provider = $scope.allProviders[i];
+
+                    if (provider.groupName == 'Social' && (provider.id == configProvidedId)) {
+                        $scope.allProviders.splice(i, 1);
+                        break;
+                    }
+                }
+            }
+        }
+    }, true);
+
+    $scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/realms/") + realm.realm + "/broker/" ;
+
+    $scope.addProvider = function(provider) {
+        $location.url("/create/identity-provider/" + realm.realm + "/" + provider.id);
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.identityProvider.alias, 'provider', function() {
+            $scope.identityProvider.$remove({
+                realm : realm.realm,
+                alias : $scope.identityProvider.alias
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/identity-provider-settings");
+                Notifications.success("The client has been deleted.");
+            });
+        });
+    };
+
+    $scope.save = function() {
+        if ($scope.newIdentityProvider) {
+            if (!$scope.identityProvider.alias) {
+                Notifications.error("You must specify an alias");
+                return;
+            }
+            IdentityProvider.save({
+                realm: $scope.realm.realm, alias: ''
+            }, $scope.identityProvider, function () {
+                $location.url("/realms/" + realm.realm + "/identity-provider-settings/provider/" + $scope.identityProvider.providerId + "/" + $scope.identityProvider.alias);
+                Notifications.success("The " + $scope.identityProvider.alias + " provider has been created.");
+            });
+        } else {
+            IdentityProvider.update({
+                realm: $scope.realm.realm,
+                id: $scope.identityProvider.internalId
+            }, $scope.identityProvider, function () {
+                $route.reload();
+                Notifications.success("The " + $scope.identityProvider.alias + " provider has been update.");
+            });
+        }
+    };
+
+    $scope.cancel = function() {
+        if ($scope.newIdentityProvider) {
+            $location.url("/realms/" + realm.realm + "/identity-provider-settings");
+        } else {
+            $route.reload();
+        }
+    };
+
+
+    $scope.reset = function() {
+        $scope.identityProvider = {};
+        $scope.configuredProviders = angular.copy($scope.realm.identityProviders);
+    };
+
+    $scope.showPassword = function(flag) {
+        $scope.hidePassword = flag;
+    };
+
+});
+
+module.controller('RealmIdentityProviderExportCtrl', function(realm, identityProvider, $scope, $http, IdentityProviderExport) {
+    $scope.realm = realm;
+    $scope.identityProvider = identityProvider;
+    $scope.download = null;
+    $scope.exported = "";
+    $scope.exportedType = "";
+
+    var url = IdentityProviderExport.url({realm: realm.realm, alias: identityProvider.alias}) ;
+    $http.get(url).success(function(data, status, headers, config) {
+        $scope.exportedType = headers('Content-Type');
+        $scope.exported = data;
+    });
+
+    $scope.download = function() {
+        var suffix = "txt";
+        if ($scope.exportedType == 'application/xml') {
+            suffix = 'xml';
+        } else if ($scope.exportedType == 'application/json') {
+            suffix = 'json';
+        }
+        saveAs(new Blob([$scope.exported], { type: $scope.exportedType }), 'keycloak.' + suffix);
+    }
+});
+
+module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, $location, $route, Dialog, Notifications, TimeUnit) {
+    console.log('RealmTokenDetailCtrl');
+
+    $scope.realm = realm;
+
+    $scope.realm.accessTokenLifespanUnit = TimeUnit.autoUnit(realm.accessTokenLifespan);
+    $scope.realm.accessTokenLifespan = TimeUnit.toUnit(realm.accessTokenLifespan, $scope.realm.accessTokenLifespanUnit);
+    $scope.$watch('realm.accessTokenLifespanUnit', function(to, from) {
+        $scope.realm.accessTokenLifespan = TimeUnit.convert($scope.realm.accessTokenLifespan, from, to);
+    });
+
+    $scope.realm.ssoSessionIdleTimeoutUnit = TimeUnit.autoUnit(realm.ssoSessionIdleTimeout);
+    $scope.realm.ssoSessionIdleTimeout = TimeUnit.toUnit(realm.ssoSessionIdleTimeout, $scope.realm.ssoSessionIdleTimeoutUnit);
+    $scope.$watch('realm.ssoSessionIdleTimeoutUnit', function(to, from) {
+        $scope.realm.ssoSessionIdleTimeout = TimeUnit.convert($scope.realm.ssoSessionIdleTimeout, from, to);
+    });
+
+    $scope.realm.ssoSessionMaxLifespanUnit = TimeUnit.autoUnit(realm.ssoSessionMaxLifespan);
+    $scope.realm.ssoSessionMaxLifespan = TimeUnit.toUnit(realm.ssoSessionMaxLifespan, $scope.realm.ssoSessionMaxLifespanUnit);
+    $scope.$watch('realm.ssoSessionMaxLifespanUnit', function(to, from) {
+        $scope.realm.ssoSessionMaxLifespan = TimeUnit.convert($scope.realm.ssoSessionMaxLifespan, from, to);
+    });
+
+    $scope.realm.accessCodeLifespanUnit = TimeUnit.autoUnit(realm.accessCodeLifespan);
+    $scope.realm.accessCodeLifespan = TimeUnit.toUnit(realm.accessCodeLifespan, $scope.realm.accessCodeLifespanUnit);
+    $scope.$watch('realm.accessCodeLifespanUnit', function(to, from) {
+        $scope.realm.accessCodeLifespan = TimeUnit.convert($scope.realm.accessCodeLifespan, from, to);
+    });
+
+    $scope.realm.accessCodeLifespanLoginUnit = TimeUnit.autoUnit(realm.accessCodeLifespanLogin);
+    $scope.realm.accessCodeLifespanLogin = TimeUnit.toUnit(realm.accessCodeLifespanLogin, $scope.realm.accessCodeLifespanLoginUnit);
+    $scope.$watch('realm.accessCodeLifespanLoginUnit', function(to, from) {
+        $scope.realm.accessCodeLifespanLogin = TimeUnit.convert($scope.realm.accessCodeLifespanLogin, from, to);
+    });
+
+    $scope.realm.accessCodeLifespanUserActionUnit = TimeUnit.autoUnit(realm.accessCodeLifespanUserAction);
+    $scope.realm.accessCodeLifespanUserAction = TimeUnit.toUnit(realm.accessCodeLifespanUserAction, $scope.realm.accessCodeLifespanUserActionUnit);
+    $scope.$watch('realm.accessCodeLifespanUserActionUnit', function(to, from) {
+        $scope.realm.accessCodeLifespanUserAction = TimeUnit.convert($scope.realm.accessCodeLifespanUserAction, from, to);
+    });
+
+    var oldCopy = angular.copy($scope.realm);
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        delete realmCopy["accessTokenLifespanUnit"];
+        delete realmCopy["ssoSessionMaxLifespanUnit"];
+        delete realmCopy["accessCodeLifespanUnit"];
+        delete realmCopy["ssoSessionIdleTimeoutUnit"];
+        delete realmCopy["accessCodeLifespanUserActionUnit"];
+        delete realmCopy["accessCodeLifespanLoginUnit"];
+
+        realmCopy.accessTokenLifespan = TimeUnit.toSeconds($scope.realm.accessTokenLifespan, $scope.realm.accessTokenLifespanUnit)
+        realmCopy.ssoSessionIdleTimeout = TimeUnit.toSeconds($scope.realm.ssoSessionIdleTimeout, $scope.realm.ssoSessionIdleTimeoutUnit)
+        realmCopy.ssoSessionMaxLifespan = TimeUnit.toSeconds($scope.realm.ssoSessionMaxLifespan, $scope.realm.ssoSessionMaxLifespanUnit)
+        realmCopy.accessCodeLifespan = TimeUnit.toSeconds($scope.realm.accessCodeLifespan, $scope.realm.accessCodeLifespanUnit)
+        realmCopy.accessCodeLifespanUserAction = TimeUnit.toSeconds($scope.realm.accessCodeLifespanUserAction, $scope.realm.accessCodeLifespanUserActionUnit)
+        realmCopy.accessCodeLifespanLogin = TimeUnit.toSeconds($scope.realm.accessCodeLifespanLogin, $scope.realm.accessCodeLifespanLoginUnit)
+
+        Realm.update(realmCopy, function () {
+            $route.reload();
+            Notifications.success("The changes have been saved to the realm.");
+        });
+    };
+
+    $scope.reset = function() {
+        $route.reload();
+    };
+});
+
+module.controller('RealmKeysDetailCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+
+    $scope.generate = function() {
+        Dialog.confirmGenerateKeys($scope.realm.realm, 'realm', function() {
+                Realm.update({ realm: realm.realm, publicKey : 'GENERATE' }, function () {
+                Notifications.success('New keys generated for realm.');
+                Realm.get({ id : realm.realm }, function(updated) {
+                    $scope.realm = updated;
+                })
+            });
+        });
+    };
+});
+
+module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmClientSessionStats, RealmLogoutAll, Notifications) {
+    $scope.realm = realm;
+    $scope.stats = stats;
+
+    $scope.logoutAll = function() {
+        RealmLogoutAll.save({realm : realm.realm}, function (globalReqResult) {
+            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
+            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
+
+            if (failedCount > 0) {
+                var msgStart = successCount>0 ? 'Successfully logout all users under: ' + globalReqResult.successRequests + ' . ' : '';
+                Notifications.error(msgStart + 'Failed to logout users under: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
+            } else {
+                window.location.reload();
+            }
+        });
+    };
+});
+
+
+module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevocation, realm, $http, $location, Dialog, Notifications) {
+    $scope.realm = angular.copy(realm);
+
+    var setNotBefore = function() {
+        if ($scope.realm.notBefore == 0) {
+            $scope.notBefore = "None";
+        } else {
+            $scope.notBefore = new Date($scope.realm.notBefore * 1000);
+        }
+    };
+
+    setNotBefore();
+
+    var reset = function() {
+        Realm.get({ id : realm.realm }, function(updated) {
+            $scope.realm = updated;
+            setNotBefore();
+        })
+
+    };
+
+    $scope.clear = function() {
+        Realm.update({ realm: realm.realm, notBefore : 0 }, function () {
+            $scope.notBefore = "None";
+            Notifications.success('Not Before cleared for realm.');
+            reset();
+        });
+    }
+    $scope.setNotBeforeNow = function() {
+        Realm.update({ realm: realm.realm, notBefore : new Date().getTime()/1000}, function () {
+            Notifications.success('Not Before set for realm.');
+            reset();
+        });
+    }
+    $scope.pushRevocation = function() {
+        RealmPushRevocation.save({ realm: realm.realm}, function (globalReqResult) {
+            var successCount = globalReqResult.successRequests ? globalReqResult.successRequests.length : 0;
+            var failedCount  = globalReqResult.failedRequests ? globalReqResult.failedRequests.length : 0;
+
+            if (successCount==0 && failedCount==0) {
+                Notifications.warn('No push sent. No admin URI configured or no registered cluster nodes available');
+            } else if (failedCount > 0) {
+                var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
+                Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
+            } else {
+                Notifications.success('Successfully push notBefore to all configured clients');
+            }
+        });
+    }
+
+});
+
+
+module.controller('RoleListCtrl', function($scope, $location, realm, roles) {
+
+    $scope.realm = realm;
+    $scope.roles = roles;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+});
+
+
+module.controller('RoleDetailCtrl', function($scope, realm, role, roles, clients,
+                                             Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
+                                             $http, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.role = angular.copy(role);
+    $scope.create = !role.name;
+
+    $scope.changed = $scope.create;
+
+    $scope.save = function() {
+        console.log('save');
+        if ($scope.create) {
+            Role.save({
+                realm: realm.realm
+            }, $scope.role, function (data, headers) {
+                $scope.changed = false;
+                role = angular.copy($scope.role);
+
+                Role.get({ realm: realm.realm, role: role.name }, function(role) {
+                    var id = role.id;
+                    $location.url("/realms/" + realm.realm + "/roles/" + id);
+                    Notifications.success("The role has been created.");
+                });
+            });
+        } else {
+            $scope.update();
+        }
+    };
+
+    $scope.remove = function () {
+        Dialog.confirmDelete($scope.role.name, 'role', function () {
+            $scope.role.$remove({
+                realm: realm.realm,
+                role: $scope.role.id
+            }, function () {
+                $location.url("/realms/" + realm.realm + "/roles");
+                Notifications.success("The role has been deleted.");
+            });
+        });
+    };
+
+    $scope.cancel = function () {
+        $location.url("/realms/" + realm.realm + "/roles");
+    };
+
+
+
+    roleControl($scope, realm, role, roles, clients,
+        ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
+        $http, $location, Notifications, Dialog);
+});
+
+module.controller('RealmSMTPSettingsCtrl', function($scope, Current, Realm, realm, $http, $location, Dialog, Notifications) {
+    console.log('RealmSMTPSettingsCtrl');
+
+    var booleanSmtpAtts = ["auth","ssl","starttls"];
+
+    $scope.realm = realm;
+
+    if ($scope.realm.smtpServer) {
+        $scope.realm.smtpServer = typeObject($scope.realm.smtpServer);
+    };
+
+    var oldCopy = angular.copy($scope.realm);
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        realmCopy['smtpServer'] = detypeObject(realmCopy.smtpServer);
+        $scope.changed = false;
+        Realm.update(realmCopy, function () {
+            $location.url("/realms/" + realm.realm + "/smtp-settings");
+            Notifications.success("Your changes have been saved to the realm.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+
+    /* Convert string attributes containing a boolean to actual boolean type + convert an integer string (port) to integer. */
+    function typeObject(obj){
+        for (var att in obj){
+            if (booleanSmtpAtts.indexOf(att) < 0)
+                continue;
+            if (obj[att] === "true"){
+                obj[att] = true;
+            } else if (obj[att] === "false"){
+                obj[att] = false;
+            }
+        }
+
+        obj['port'] = parseInt(obj['port']);
+
+        return obj;
+    }
+
+    /* Convert all non-string values to strings to invert changes caused by the typeObject function. */
+    function detypeObject(obj){
+        for (var att in obj){
+            if (booleanSmtpAtts.indexOf(att) < 0)
+                continue;
+            if (obj[att] === true){
+                obj[att] = "true";
+            } else if (obj[att] === false){
+                obj[att] = "false"
+            }
+        }
+
+        obj['port'] = obj['port'].toString();
+
+        return obj;
+    }
+});
+
+module.controller('RealmEventsConfigCtrl', function($scope, eventsConfig, RealmEventsConfig, RealmEvents, RealmAdminEvents, realm, serverInfo, $location, Notifications, TimeUnit, Dialog) {
+    $scope.realm = realm;
+
+    $scope.eventsConfig = eventsConfig;
+
+    $scope.eventsConfig.expirationUnit = TimeUnit.autoUnit(eventsConfig.eventsExpiration);
+    $scope.eventsConfig.eventsExpiration = TimeUnit.toUnit(eventsConfig.eventsExpiration, $scope.eventsConfig.expirationUnit);
+    $scope.$watch('eventsConfig.expirationUnit', function(to, from) {
+        if ($scope.eventsConfig.eventsExpiration) {
+            $scope.eventsConfig.eventsExpiration = TimeUnit.convert($scope.eventsConfig.eventsExpiration, from, to);
+        }
+    });
+
+    $scope.eventListeners = serverInfo.eventListeners;
+
+    $scope.eventSelectOptions = {
+        'multiple': true,
+        'simple_tags': true,
+        'tags': serverInfo.enums['eventType']
+    };
+
+    var oldCopy = angular.copy($scope.eventsConfig);
+    $scope.changed = false;
+
+    $scope.$watch('eventsConfig', function() {
+        if (!angular.equals($scope.eventsConfig, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        $scope.changed = false;
+
+        var copy = angular.copy($scope.eventsConfig)
+        delete copy['expirationUnit'];
+
+        copy.eventsExpiration = TimeUnit.toSeconds($scope.eventsConfig.eventsExpiration, $scope.eventsConfig.expirationUnit);
+
+        RealmEventsConfig.update({
+            id : realm.realm
+        }, copy, function () {
+            $location.url("/realms/" + realm.realm + "/events-settings");
+            Notifications.success("Your changes have been saved to the realm.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.eventsConfig = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+
+    $scope.clearEvents = function() {
+        Dialog.confirmDelete($scope.realm.realm, 'events', function() {
+            RealmEvents.remove({ id : $scope.realm.realm }, function() {
+                Notifications.success("The events has been cleared.");
+            });
+        });
+    };
+    
+    $scope.clearAdminEvents = function() {
+        Dialog.confirmDelete($scope.realm.realm, 'admin-events', function() {
+            RealmAdminEvents.remove({ id : $scope.realm.realm }, function() {
+                Notifications.success("The admin events has been cleared.");
+            });
+        });
+    };
+});
+
+module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm, serverInfo) {
+    $scope.realm = realm;
+    $scope.page = 0;
+    
+    $scope.eventSelectOptions = {
+        'multiple': true,
+        'simple_tags': true,
+        'tags': serverInfo.enums['eventType']
+    };
+
+    $scope.query = {
+        id : realm.realm,
+        max : 5,
+        first : 0
+    }
+
+    $scope.update = function() {
+    	$scope.query.first = 0;
+        for (var i in $scope.query) {
+            if ($scope.query[i] === '') {
+                delete $scope.query[i];
+           }
+        }
+        $scope.events = RealmEvents.query($scope.query);
+    }
+    
+    $scope.reset = function() {
+    	$scope.query.first = 0;
+    	$scope.query.max = 5;
+    	$scope.query.type = '';
+    	$scope.query.client = '';
+    	$scope.query.user = '';
+    	$scope.query.dateFrom = '';
+    	$scope.query.dateTo = '';
+    	
+    	$scope.update();
+    }
+    
+    $scope.queryUpdate = function() {
+        for (var i in $scope.query) {
+            if ($scope.query[i] === '') {
+                delete $scope.query[i];
+           }
+        }
+        $scope.events = RealmEvents.query($scope.query);
+    }
+    
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.queryUpdate();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.queryUpdate();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.queryUpdate();
+    }
+
+    $scope.update();
+});
+
+module.controller('RealmAdminEventsCtrl', function($scope, RealmAdminEvents, realm, serverInfo, $modal, $filter) {
+    $scope.realm = realm;
+    $scope.page = 0;
+
+    $scope.query = {
+    	id : realm.realm,
+        max : 5,
+        first : 0
+    }
+
+    $scope.adminEnabledEventOperationsOptions = {
+        'multiple': true,
+        'simple_tags': true,
+        'tags': serverInfo.enums['operationType']
+    };
+    
+    $scope.update = function() {
+    	$scope.query.first = 0;
+        for (var i in $scope.query) {
+            if ($scope.query[i] === '') {
+                delete $scope.query[i];
+           }
+        }
+        $scope.events = RealmAdminEvents.query($scope.query);
+    }
+    
+    $scope.reset = function() {
+    	$scope.query.first = 0;
+    	$scope.query.max = 5;
+    	$scope.query.operationTypes = '';
+    	$scope.query.resourcePath = '';
+    	$scope.query.authRealm = '';
+    	$scope.query.authClient = '';
+    	$scope.query.authUser = '';
+    	$scope.query.authIpAddress = '';
+    	$scope.query.dateFrom = '';
+    	$scope.query.dateTo = '';
+    	
+    	$scope.update();
+    }
+    
+    $scope.queryUpdate = function() {
+        for (var i in $scope.query) {
+            if ($scope.query[i] === '') {
+                delete $scope.query[i];
+           }
+        }
+        $scope.events = RealmAdminEvents.query($scope.query);
+    }
+    
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.queryUpdate();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.queryUpdate();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.queryUpdate();
+    }
+
+    $scope.update();
+    
+    $scope.viewRepresentation = function(event) {
+        $modal.open({
+            templateUrl: resourceUrl + '/partials/modal/realm-events-admin-representation.html',
+            controller: 'RealmAdminEventsModalCtrl',
+            resolve: {
+                event: function () {
+                    return event;
+                }
+            }
+        })
+    }
+
+    $scope.viewAuth = function(event) {
+        $modal.open({
+            templateUrl: resourceUrl + '/partials/modal/realm-events-admin-auth.html',
+            controller: 'RealmAdminEventsModalCtrl',
+            resolve: {
+                event: function () {
+                    return event;
+                }
+            }
+        })
+    }
+});
+
+module.controller('RealmAdminEventsModalCtrl', function($scope, $filter, event) {
+    $scope.event = event;
+});
+
+module.controller('RealmBruteForceCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, TimeUnit) {
+    console.log('RealmBruteForceCtrl');
+
+    $scope.realm = realm;
+
+    $scope.realm.waitIncrementUnit = TimeUnit.autoUnit(realm.waitIncrementSeconds);
+    $scope.realm.waitIncrement = TimeUnit.toUnit(realm.waitIncrementSeconds, $scope.realm.waitIncrementUnit);
+    $scope.$watch('realm.waitIncrementUnit', function(to, from) {
+        $scope.realm.waitIncrement = TimeUnit.convert($scope.realm.waitIncrement, from, to);
+    });
+
+    $scope.realm.minimumQuickLoginWaitUnit = TimeUnit.autoUnit(realm.minimumQuickLoginWaitSeconds);
+    $scope.realm.minimumQuickLoginWait = TimeUnit.toUnit(realm.minimumQuickLoginWaitSeconds, $scope.realm.minimumQuickLoginWaitUnit);
+    $scope.$watch('realm.minimumQuickLoginWaitUnit', function(to, from) {
+        $scope.realm.minimumQuickLoginWait = TimeUnit.convert($scope.realm.minimumQuickLoginWait, from, to);
+    });
+
+    $scope.realm.maxFailureWaitUnit = TimeUnit.autoUnit(realm.maxFailureWaitSeconds);
+    $scope.realm.maxFailureWait = TimeUnit.toUnit(realm.maxFailureWaitSeconds, $scope.realm.maxFailureWaitUnit);
+    $scope.$watch('realm.maxFailureWaitUnit', function(to, from) {
+        $scope.realm.maxFailureWait = TimeUnit.convert($scope.realm.maxFailureWait, from, to);
+    });
+
+    $scope.realm.maxDeltaTimeUnit = TimeUnit.autoUnit(realm.maxDeltaTimeSeconds);
+    $scope.realm.maxDeltaTime = TimeUnit.toUnit(realm.maxDeltaTimeSeconds, $scope.realm.maxDeltaTimeUnit);
+    $scope.$watch('realm.maxDeltaTimeUnit', function(to, from) {
+        $scope.realm.maxDeltaTime = TimeUnit.convert($scope.realm.maxDeltaTime, from, to);
+    });
+
+    var oldCopy = angular.copy($scope.realm);
+    $scope.changed = false;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.realm, oldCopy)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        var realmCopy = angular.copy($scope.realm);
+        delete realmCopy["waitIncrementUnit"];
+        delete realmCopy["waitIncrement"];
+        delete realmCopy["minimumQuickLoginWaitUnit"];
+        delete realmCopy["minimumQuickLoginWait"];
+        delete realmCopy["maxFailureWaitUnit"];
+        delete realmCopy["maxFailureWait"];
+        delete realmCopy["maxDeltaTimeUnit"];
+        delete realmCopy["maxDeltaTime"];
+
+        realmCopy.waitIncrementSeconds = TimeUnit.toSeconds($scope.realm.waitIncrement, $scope.realm.waitIncrementUnit)
+        realmCopy.minimumQuickLoginWaitSeconds = TimeUnit.toSeconds($scope.realm.minimumQuickLoginWait, $scope.realm.minimumQuickLoginWaitUnit)
+        realmCopy.maxFailureWaitSeconds = TimeUnit.toSeconds($scope.realm.maxFailureWait, $scope.realm.maxFailureWaitUnit)
+        realmCopy.maxDeltaTimeSeconds = TimeUnit.toSeconds($scope.realm.maxDeltaTime, $scope.realm.maxDeltaTimeUnit)
+
+        $scope.changed = false;
+        Realm.update(realmCopy, function () {
+            $location.url("/realms/" + realm.realm + "/defense/brute-force");
+            Notifications.success("Your changes have been saved to the realm.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.realm = angular.copy(oldCopy);
+        $scope.changed = false;
+    };
+});
+
+
+module.controller('IdentityProviderMapperListCtrl', function($scope, realm, identityProvider, mapperTypes, mappers) {
+    $scope.realm = realm;
+    $scope.identityProvider = identityProvider;
+    $scope.mapperTypes = mapperTypes;
+    $scope.mappers = mappers;
+});
+
+module.controller('IdentityProviderMapperCtrl', function($scope, realm,  identityProvider, mapperTypes, mapper, IdentityProviderMapper, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.identityProvider = identityProvider;
+    $scope.create = false;
+    $scope.mapper = angular.copy(mapper);
+    $scope.changed = false;
+    $scope.mapperType = mapperTypes[mapper.identityProviderMapper];
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('mapper', function() {
+        if (!angular.equals($scope.mapper, mapper)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        IdentityProviderMapper.update({
+            realm : realm.realm,
+            alias: identityProvider.alias,
+            mapperId : mapper.id
+        }, $scope.mapper, function() {
+            $scope.changed = false;
+            mapper = angular.copy($scope.mapper);
+            $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers/" + mapper.id);
+            Notifications.success("Your changes have been saved.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.mapper = angular.copy(mapper);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
+            IdentityProviderMapper.remove({ realm: realm.realm, alias: mapper.identityProviderAlias, mapperId : $scope.mapper.id }, function() {
+                Notifications.success("The mapper has been deleted.");
+                $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers");
+            });
+        });
+    };
+
+});
+
+module.controller('IdentityProviderMapperCreateCtrl', function($scope, realm, identityProvider, mapperTypes, IdentityProviderMapper, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.identityProvider = identityProvider;
+    $scope.create = true;
+    $scope.mapper = { identityProviderAlias: identityProvider.alias, config: {}};
+    $scope.mapperTypes = mapperTypes;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.save = function() {
+        $scope.mapper.identityProviderMapper = $scope.mapperType.id;
+        IdentityProviderMapper.save({
+            realm : realm.realm, alias: identityProvider.alias
+        }, $scope.mapper, function(data, headers) {
+            var l = headers().location;
+            var id = l.substring(l.lastIndexOf("/") + 1);
+            $location.url("/realms/" + realm.realm + '/identity-provider-mappers/' + identityProvider.alias + "/mappers/" + id);
+            Notifications.success("Mapper has been created.");
+        });
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+
+});
+
+module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, AuthenticationExecutions, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.flows = flows;
+    if (flows.length > 0) {
+        $scope.flow = flows[0];
+    }
+    var setupForm = function() {
+        AuthenticationExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
+            $scope.executions = data;
+            $scope.flowmax = 0;
+            for (var i = 0; i < $scope.executions.length; i++ ) {
+                execution = $scope.executions[i];
+                if (execution.requirementChoices.length > $scope.flowmax) {
+                    $scope.flowmax = execution.requirementChoices.length;
+                }
+            }
+            for (var i = 0; i < $scope.executions.length; i++ ) {
+                execution = $scope.executions[i];
+                execution.empties = [];
+                for (j = 0; j < $scope.flowmax - execution.requirementChoices.length; j++) {
+                    execution.empties.push(j);
+                }
+            }
+        })
+    };
+
+    $scope.updateExecution = function(execution) {
+        var copy = angular.copy(execution);
+        delete copy.empties;
+        AuthenticationExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
+            Notifications.success("Auth requirement updated");
+            setupForm();
+        });
+
+    };
+    $scope.setupForm = setupForm;
+
+    setupForm();
+
+
+});
+
+module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications, Dialog, $location) {
+    console.log('RequiredActionsCtrl');
+    $scope.realm = realm;
+    $scope.requiredActions = [];
+    var setupRequiredActionsForm = function() {
+        console.log('setupRequiredActionsForm');
+        RequiredActions.query({id: realm.realm}, function(data) {
+            $scope.requiredActions = [];
+            for (var i = 0; i < data.length; i++) {
+                $scope.requiredActions.push(data[i]);
+            }
+        });
+    };
+
+    $scope.updateRequiredAction = function(action) {
+        RequiredActions.update({id: realm.realm, alias: action.alias}, action, function() {
+            Notifications.success("Required action updated");
+            setupRequiredActionsForm();
+        });
+    }
+
+    setupRequiredActionsForm();
+
+
+});
+
+module.controller('AuthenticationConfigCtrl', function($scope, realm, configType, config, AuthenticationConfig, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.configType = configType;
+    $scope.create = false;
+    $scope.config = angular.copy(config);
+    $scope.changed = false;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.$watch('config', function() {
+        if (!angular.equals($scope.config, config)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        AuthenticationConfig.update({
+            realm : realm.realm,
+            config : config.id
+        }, $scope.config, function() {
+            $scope.changed = false;
+            config = angular.copy($scope.config);
+            $location.url("/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + config.id);
+            Notifications.success("Your changes have been saved.");
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.config = angular.copy(config);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.config.alias, 'config', function() {
+            AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() {
+                Notifications.success("The config has been deleted.");
+                $location.url("/realms/" + realm.realm + '/authentication/flows');
+            });
+        });
+    };
+
+});
+
+module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, configType, execution, AuthenticationExecutionConfig, Notifications, Dialog, $location) {
+    $scope.realm = realm;
+    $scope.create = true;
+    $scope.config = { config: {}};
+    $scope.configType = configType;
+
+    $scope.$watch(function() {
+        return $location.path();
+    }, function() {
+        $scope.path = $location.path().substring(1).split("/");
+    });
+
+    $scope.save = function() {
+        AuthenticationExecutionConfig.save({
+            realm : realm.realm,
+            execution: execution
+        }, $scope.config, function(data, headers) {
+            var l = headers().location;
+            var id = l.substring(l.lastIndexOf("/") + 1);
+            var url = "/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + id;
+            console.log('redirect url: ' + url);
+            $location.url(url);
+            Notifications.success("Config has been created.");
+        });
+    };
+
+    $scope.cancel = function() {
+        //$location.url("/realms");
+        window.history.back();
+    };
+
+
+});
+
+
+
+
+
+
+
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
index 11443b4..51644ba 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
@@ -1,1001 +1,1001 @@
-module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, clients, Notifications, RealmRoleMapping,
-                                                  ClientRoleMapping, AvailableRealmRoleMapping, AvailableClientRoleMapping,
-                                                  CompositeRealmRoleMapping, CompositeClientRoleMapping) {
-    $scope.realm = realm;
-    $scope.user = user;
-    $scope.selectedRealmRoles = [];
-    $scope.selectedRealmMappings = [];
-    $scope.realmMappings = [];
-    $scope.clients = clients;
-    $scope.clientRoles = [];
-    $scope.clientComposite = [];
-    $scope.selectedClientRoles = [];
-    $scope.selectedClientMappings = [];
-    $scope.clientMappings = [];
-    $scope.dummymodel = [];
-
-    $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
-    $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-    $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-
-    $scope.addRealmRole = function() {
-        var roles = $scope.selectedRealmRoles;
-        $scope.selectedRealmRoles = [];
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/realm',
-                roles).success(function() {
-                $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.selectedRealmMappings = [];
-                $scope.selectRealmRoles = [];
-                if ($scope.client) {
-                    console.log('load available');
-                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.selectedClientRoles = [];
-                    $scope.selectedClientMappings = [];
-                }
-                Notifications.success("Role mappings updated.");
-
-            });
-    };
-
-    $scope.deleteRealmRole = function() {
-        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/realm',
-            {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
-                $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
-                $scope.selectedRealmMappings = [];
-                $scope.selectRealmRoles = [];
-                if ($scope.client) {
-                    console.log('load available');
-                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                    $scope.selectedClientRoles = [];
-                    $scope.selectedClientMappings = [];
-                }
-                Notifications.success("Role mappings updated.");
-            });
-    };
-
-    $scope.addClientRole = function() {
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/clients/' + $scope.client.id,
-                $scope.selectedClientRoles).success(function() {
-                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.selectedClientRoles = [];
-                $scope.selectedClientMappings = [];
-                Notifications.success("Role mappings updated.");
-            });
-    };
-
-    $scope.deleteClientRole = function() {
-        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/clients/' + $scope.client.id,
-            {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
-                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-                $scope.selectedClientRoles = [];
-                $scope.selectedClientMappings = [];
-                Notifications.success("Role mappings updated.");
-            });
-    };
-
-
-    $scope.changeClient = function() {
-        console.log('changeClient');
-        if ($scope.client) {
-            console.log('load available');
-            $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-            $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-            $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
-        } else {
-            $scope.clientRoles = null;
-            $scope.clientMappings = null;
-            $scope.clientComposite = null;
-        }
-        $scope.selectedClientRoles = [];
-        $scope.selectedClientMappings = [];
-    };
-
-
-
-});
-
-module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, UserSessions, UserLogout, UserSessionLogout, Notifications) {
-    $scope.realm = realm;
-    $scope.user = user;
-    $scope.sessions = sessions;
-
-    $scope.logoutAll = function() {
-        UserLogout.save({realm : realm.realm, user: user.id}, function () {
-            Notifications.success('Logged out user in all clients');
-            UserSessions.query({realm: realm.realm, user: user.id}, function(updated) {
-                $scope.sessions = updated;
-            })
-        });
-    };
-
-    $scope.logoutSession = function(sessionId) {
-        console.log('here in logoutSession');
-        UserSessionLogout.delete({realm : realm.realm, session: sessionId}, function() {
-            UserSessions.query({realm: realm.realm, user: user.id}, function(updated) {
-                $scope.sessions = updated;
-                Notifications.success('Logged out session');
-            })
-        });
-    }
-});
-
-module.controller('UserFederatedIdentityCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications, Dialog) {
-    $scope.realm = realm;
-    $scope.user = user;
-    $scope.federatedIdentities = federatedIdentities;
-
-    $scope.hasAnyProvidersToCreate = function() {
-        return realm.identityProviders.length - $scope.federatedIdentities.length > 0;
-    }
-
-    $scope.removeProviderLink = function(providerLink) {
-
-        console.log("Removing provider link: " + providerLink.identityProvider);
-
-        Dialog.confirmDelete(providerLink.identityProvider, 'Identity Provider Link', function() {
-            UserFederatedIdentity.remove({ realm: realm.realm, user: user.id, provider: providerLink.identityProvider }, function() {
-                Notifications.success("The provider link has been deleted.");
-                var indexToRemove = $scope.federatedIdentities.indexOf(providerLink);
-                $scope.federatedIdentities.splice(indexToRemove, 1);
-            });
-        });
-    }
-});
-
-module.controller('UserFederatedIdentityAddCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications) {
-    $scope.realm = realm;
-    $scope.user = user;
-    $scope.federatedIdentity = {};
-
-    var getAvailableProvidersToCreate = function() {
-        var realmProviders = [];
-        for (var i=0 ; i<realm.identityProviders.length ; i++) {
-            var providerAlias = realm.identityProviders[i].alias;
-            realmProviders.push(providerAlias);
-        };
-
-        for (var i=0 ; i<federatedIdentities.length ; i++) {
-            var providerAlias = federatedIdentities[i].identityProvider;
-            var index = realmProviders.indexOf(providerAlias);
-            realmProviders.splice(index, 1);
-        }
-
-        return realmProviders;
-    }
-    $scope.availableProvidersToCreate = getAvailableProvidersToCreate();
-
-    $scope.save = function() {
-        UserFederatedIdentity.save({
-            realm : realm.realm,
-            user: user.id,
-            provider: $scope.federatedIdentity.identityProvider
-        }, $scope.federatedIdentity, function(data, headers) {
-            $location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
-            Notifications.success("Provider link has been created.");
-        });
-    };
-
-    $scope.cancel = function() {
-         $location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
-    };
-
-});
-
-module.controller('UserConsentsCtrl', function($scope, realm, user, userConsents, UserConsents, Notifications) {
-    $scope.realm = realm;
-    $scope.user = user;
-    $scope.userConsents = userConsents;
-
-    $scope.revokeConsent = function(clientId) {
-        UserConsents.delete({realm : realm.realm, user: user.id, client: clientId }, function () {
-            UserConsents.query({realm: realm.realm, user: user.id}, function(updated) {
-                $scope.userConsents = updated;
-            })
-            Notifications.success('Consent revoked successfully');
-        }, function() {
-            Notifications.error("Consent couldn't be revoked");
-        });
-        console.log("Revoke consent " + clientId);
-    }
-});
-
-
-module.controller('UserListCtrl', function($scope, realm, User, UserImpersonation) {
-    $scope.realm = realm;
-    $scope.page = 0;
-
-    $scope.query = {
-        realm: realm.realm,
-        max : 5,
-        first : 0
-    }
-
-    $scope.impersonate = function(userId) {
-        UserImpersonation.save({realm : realm.realm, user: userId}, function (data) {
-            if (data.sameRealm) {
-                window.location = data.redirect;
-            } else {
-                window.open(data.redirect, "_blank");
-            }
-        });
-    };
-
-    $scope.firstPage = function() {
-        $scope.query.first = 0;
-        $scope.searchQuery();
-    }
-
-    $scope.previousPage = function() {
-        $scope.query.first -= parseInt($scope.query.max);
-        if ($scope.query.first < 0) {
-            $scope.query.first = 0;
-        }
-        $scope.searchQuery();
-    }
-
-    $scope.nextPage = function() {
-        $scope.query.first += parseInt($scope.query.max);
-        $scope.searchQuery();
-    }
-
-    $scope.searchQuery = function() {
-        console.log("query.search: " + $scope.query.search);
-        $scope.searchLoaded = false;
-
-        $scope.users = User.query($scope.query, function() {
-            $scope.searchLoaded = true;
-            $scope.lastSearch = $scope.query.search;
-        });
-    };
-});
-
-
-
-module.controller('UserDetailCtrl', function($scope, realm, user, User, UserFederationInstances, UserImpersonation, RequiredActions, $location, Dialog, Notifications) {
-    $scope.realm = realm;
-    $scope.create = !user.id;
-    $scope.editUsername = $scope.create || $scope.realm.editUsernameAllowed;
-
-    if ($scope.create) {
-        $scope.user = { enabled: true, attributes: {} }
-    } else {
-        if (!user.attributes) {
-            user.attributes = {}
-        }
-        convertAttributeValuesToString(user);
-
-
-        $scope.user = angular.copy(user);
-        $scope.impersonate = function() {
-            UserImpersonation.save({realm : realm.realm, user: $scope.user.id}, function (data) {
-                if (data.sameRealm) {
-                    window.location = data.redirect;
-                } else {
-                    window.open(data.redirect, "_blank");
-                }
-            });
-        };
-        if(user.federationLink) {
-            console.log("federationLink is not null");
-            UserFederationInstances.get({realm : realm.realm, instance: user.federationLink}, function(link) {
-                $scope.federationLinkName = link.displayName;
-                $scope.federationLink = "#/realms/" + realm.realm + "/user-federation/providers/" + link.providerName + "/" + link.id;
-            })
-        } else {
-            console.log("federationLink is null");
-        }
-    }
-
-    $scope.changed = false; // $scope.create;
-    if (user.requiredActions) {
-        for (var i = 0; i < user.requiredActions.length; i++) {
-            console.log("user require action: " + user.requiredActions[i]);
-        }
-    }
-    // ID - Name map for required actions. IDs are enum names.
-    RequiredActions.query({id: realm.realm}, function(data) {
-        $scope.userReqActionList = [];
-        for (var i = 0; i < data.length; i++) {
-            console.log("listed required action: " + data[i].name);
-            if (data[i].enabled) {
-                var item = data[i];
-                $scope.userReqActionList.push(item);
-            }
-        }
-
-    });
-
-        /*[
-        {id: "VERIFY_EMAIL", text: "Verify Email"},
-        {id: "UPDATE_PROFILE", text: "Update Profile"},
-        {id: "CONFIGURE_TOTP", text: "Configure Totp"},
-        {id: "UPDATE_PASSWORD", text: "Update Password"}
-    ];
-    */
-
-    $scope.$watch('user', function() {
-        if (!angular.equals($scope.user, user)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        convertAttributeValuesToLists();
-
-        if ($scope.create) {
-            User.save({
-                realm: realm.realm
-            }, $scope.user, function (data, headers) {
-                $scope.changed = false;
-                convertAttributeValuesToString($scope.user);
-                user = angular.copy($scope.user);
-                var l = headers().location;
-
-                console.debug("Location == " + l);
-
-                var id = l.substring(l.lastIndexOf("/") + 1);
-
-
-                $location.url("/realms/" + realm.realm + "/users/" + id);
-                Notifications.success("The user has been created.");
-            });
-        } else {
-            User.update({
-                realm: realm.realm,
-                userId: $scope.user.id
-            }, $scope.user, function () {
-                $scope.changed = false;
-                convertAttributeValuesToString($scope.user);
-                user = angular.copy($scope.user);
-                Notifications.success("Your changes have been saved to the user.");
-            });
-        }
-    };
-
-    function convertAttributeValuesToLists() {
-        var attrs = $scope.user.attributes;
-        for (var attribute in attrs) {
-            if (typeof attrs[attribute] === "string") {
-                var attrVals = attrs[attribute].split("##");
-                attrs[attribute] = attrVals;
-            }
-        }
-    }
-
-    function convertAttributeValuesToString(user) {
-        var attrs = user.attributes;
-        for (var attribute in attrs) {
-            if (typeof attrs[attribute] === "object") {
-                var attrVals = attrs[attribute].join("##");
-                attrs[attribute] = attrVals;
-            }
-        }
-    }
-
-    $scope.reset = function() {
-        $scope.user = angular.copy(user);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/users");
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.user.id, 'user', function() {
-            $scope.user.$remove({
-                realm : realm.realm,
-                userId : $scope.user.id
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/users");
-                Notifications.success("The user has been deleted.");
-            }, function() {
-                Notifications.error("User couldn't be deleted");
-            });
-        });
-    };
-});
-
-module.controller('UserCredentialsCtrl', function($scope, realm, user, User, UserCredentials, Notifications, Dialog) {
-    console.log('UserCredentialsCtrl');
-
-    $scope.realm = realm;
-    $scope.user = angular.copy(user);
-    $scope.temporaryPassword = true;
-
-    $scope.isTotp = false;
-    if(!!user.totp){
-        $scope.isTotp = user.totp;
-    }
-
-    $scope.resetPassword = function() {
-        if ($scope.pwdChange) {
-            if ($scope.password != $scope.confirmPassword) {
-                Notifications.error("Password and confirmation does not match.");
-                return;
-            }
-        }
-
-        var msgTitle = 'Change password';
-        var msg = 'Are you sure you want to change the users password?';
-
-        Dialog.confirm(msgTitle, msg, function() {
-            UserCredentials.resetPassword({ realm: realm.realm, userId: user.id }, { type : "password", value : $scope.password, temporary: $scope.temporaryPassword }, function() {
-                Notifications.success("The password has been reset");
-                $scope.password = null;
-                $scope.confirmPassword = null;
-            }, function(response) {
-                if (response.data && response.data.errorMessage) {
-                    Notifications.error(response.data.errorMessage);
-                } else {
-                    Notifications.error("Failed to reset user password");
-                }
-            });
-        }, function() {
-            $scope.password = null;
-            $scope.confirmPassword = null;
-        });
-    };
-
-    $scope.removeTotp = function() {
-        Dialog.confirm('Remove totp', 'Are you sure you want to remove the users totp configuration?', function() {
-            UserCredentials.removeTotp({ realm: realm.realm, userId: user.id }, { }, function() {
-                Notifications.success("The users totp configuration has been removed");
-                $scope.user.totp = false;
-            }, function() {
-                Notifications.error("Failed to remove the users totp configuration");
-            });
-        });
-    };
-
-    $scope.resetPasswordEmail = function() {
-        Dialog.confirm('Reset password email', 'Are you sure you want to send password reset email to user?', function() {
-            UserCredentials.resetPasswordEmail({ realm: realm.realm, userId: user.id }, { }, function() {
-                Notifications.success("Password reset email sent to user");
-            }, function() {
-                Notifications.error("Failed to send password reset mail to user");
-            });
-        });
-    };
-
-    $scope.$watch('user', function() {
-        if (!angular.equals($scope.user, user)) {
-            $scope.userChange = true;
-        } else {
-            $scope.userChange = false;
-        }
-    }, true);
-
-    $scope.$watch('password', function() {
-        if (!!$scope.password){
-            $scope.pwdChange = true;
-        } else {
-            $scope.pwdChange = false;
-        }
-    }, true);
-
-    $scope.reset = function() {
-        $scope.password = "";
-        $scope.confirmPassword = "";
-
-        $scope.user = angular.copy(user);
-
-        $scope.isTotp = false;
-        if(!!user.totp){
-            $scope.isTotp = user.totp;
-        }
-
-        $scope.pwdChange = false;
-        $scope.userChange = false;
-    };
-});
-
-module.controller('UserFederationCtrl', function($scope, $location, realm, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
-    console.log('UserFederationCtrl ++++****');
-    $scope.realm = realm;
-    $scope.providers = UserFederationProviders.query({realm: realm.realm});
-
-    $scope.addProvider = function(provider) {
-        console.log('Add provider: ' + provider.id);
-        $location.url("/create/user-federation/" + realm.realm + "/providers/" + provider.id);
-    };
-
-    $scope.instances = UserFederationInstances.query({realm: realm.realm});
-
-});
-
-module.controller('GenericUserFederationCtrl', function($scope, $location, Notifications, $route, Dialog, realm, instance, providerFactory, UserFederationInstances, UserFederationSync) {
-    console.log('GenericUserFederationCtrl');
-
-    $scope.create = !instance.providerName;
-    $scope.providerFactory = providerFactory;
-
-    console.log("providerFactory: " + providerFactory.id);
-
-    function initFederationSettings() {
-        if ($scope.create) {
-            instance.providerName = providerFactory.id;
-            instance.config = {};
-            instance.priority = 0;
-            $scope.fullSyncEnabled = false;
-            $scope.changedSyncEnabled = false;
-
-            if (providerFactory.id === 'kerberos') {
-                instance.config.debug = false;
-                instance.config.allowPasswordAuthentication = true;
-                instance.config.editMode = 'UNSYNCED';
-                instance.config.updateProfileFirstLogin = true;
-                instance.config.allowKerberosAuthentication = true;
-            }
-        } else {
-            $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
-            $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
-
-            if (providerFactory.id === 'kerberos') {
-                instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
-                instance.config.allowPasswordAuthentication = (instance.config.allowPasswordAuthentication === 'true' || instance.config.allowPasswordAuthentication === true);
-                instance.config.updateProfileFirstLogin = (instance.config.updateProfileFirstLogin === 'true' || instance.config.updateProfileFirstLogin === true);
-            }
-        }
-
-        $scope.changed = false;
-    }
-
-    initFederationSettings();
-    $scope.instance = angular.copy(instance);
-    $scope.realm = realm;
-
-    $scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
-        if (oldVal == newVal) {
-            return;
-        }
-
-        $scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
-        $scope.changed = true;
-    });
-
-    $scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
-        if (oldVal == newVal) {
-            return;
-        }
-
-        $scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
-        $scope.changed = true;
-    });
-
-    $scope.$watch('instance', function() {
-        if (!angular.equals($scope.instance, instance)) {
-            $scope.changed = true;
-        }
-
-    }, true);
-
-    $scope.save = function() {
-        $scope.changed = false;
-        if ($scope.create) {
-            UserFederationInstances.save({realm: realm.realm}, $scope.instance,  function (data, headers) {
-                var l = headers().location;
-                var id = l.substring(l.lastIndexOf("/") + 1);
-
-                $location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
-                Notifications.success("The provider has been created.");
-            });
-        } else {
-            UserFederationInstances.update({realm: realm.realm,
-                    instance: instance.id
-                },
-                $scope.instance,  function () {
-                    $route.reload();
-                    Notifications.success("The provider has been updated.");
-                });
-        }
-    };
-
-    $scope.reset = function() {
-        initFederationSettings();
-        $scope.instance = angular.copy(instance);
-    };
-
-    $scope.cancel = function() {
-        if ($scope.create) {
-            $location.url("/realms/" + realm.realm + "/user-federation");
-        } else {
-            $route.reload();
-        }
-    };
-
-    $scope.remove = function() {
-        Dialog.confirm('Delete', 'Are you sure you want to permanently delete this provider?  All imported users will also be deleted.', function() {
-            $scope.instance.$remove({
-                realm : realm.realm,
-                instance : $scope.instance.id
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/user-federation");
-                Notifications.success("The provider has been deleted.");
-            });
-        });
-    };
-
-    $scope.triggerFullSync = function() {
-        console.log('GenericCtrl: triggerFullSync');
-        triggerSync('triggerFullSync');
-    }
-
-    $scope.triggerChangedUsersSync = function() {
-        console.log('GenericCtrl: triggerChangedUsersSync');
-        triggerSync('triggerChangedUsersSync');
-    }
-
-    function triggerSync(action) {
-        UserFederationSync.save({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, {}, function(syncResult) {
-            Notifications.success("Sync of users finished successfully. " + syncResult.status);
-        }, function() {
-            Notifications.error("Error during sync of users");
-        });
-    }
-});
-
-
-module.controller('LDAPCtrl', function($scope, $location, $route, Notifications, Dialog, realm, instance, UserFederationInstances, UserFederationSync, RealmLDAPConnectionTester) {
-    console.log('LDAPCtrl');
-    var DEFAULT_BATCH_SIZE = "1000";
-
-    $scope.create = !instance.providerName;
-
-    function initFederationSettings() {
-        if ($scope.create) {
-            instance.providerName = "ldap";
-            instance.config = {};
-            instance.priority = 0;
-
-            instance.config.syncRegistrations = false;
-            instance.config.userAccountControlsAfterPasswordUpdate = true;
-            instance.config.connectionPooling = true;
-            instance.config.pagination = true;
-
-            instance.config.allowKerberosAuthentication = false;
-            instance.config.debug = false;
-            instance.config.useKerberosForPasswordAuthentication = false;
-
-            instance.config.authType = 'simple';
-            instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
-            instance.config.searchScope = "1";
-
-            $scope.fullSyncEnabled = false;
-            $scope.changedSyncEnabled = false;
-        } else {
-            instance.config.syncRegistrations = (instance.config.syncRegistrations === 'true' || instance.config.syncRegistrations === true);
-            instance.config.userAccountControlsAfterPasswordUpdate = (instance.config.userAccountControlsAfterPasswordUpdate === 'true' || instance.config.userAccountControlsAfterPasswordUpdate === true);
-            instance.config.connectionPooling = (instance.config.connectionPooling === 'true' || instance.config.connectionPooling === true);
-            instance.config.pagination = (instance.config.pagination === 'true' || instance.config.pagination === true);
-
-            instance.config.allowKerberosAuthentication = (instance.config.allowKerberosAuthentication === 'true' || instance.config.allowKerberosAuthentication === true);
-            instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
-            instance.config.useKerberosForPasswordAuthentication = (instance.config.useKerberosForPasswordAuthentication === 'true' || instance.config.useKerberosForPasswordAuthentication === true);
-
-            if (!instance.config.authType) {
-                instance.config.authType = 'simple';
-            }
-            if (!instance.config.batchSizeForSync) {
-                instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
-            }
-            if (!instance.config.searchScope) {
-                instance.config.searchScope = '1';
-            }
-
-            $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
-            $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
-        }
-
-        $scope.changed = false;
-        $scope.lastVendor = instance.config.vendor;
-    }
-
-    initFederationSettings();
-    $scope.instance = angular.copy(instance);
-
-    $scope.ldapVendors = [
-        { "id": "ad", "name": "Active Directory" },
-        { "id": "rhds", "name": "Red Hat Directory Server" },
-        { "id": "tivoli", "name": "Tivoli" },
-        { "id": "edirectory", "name": "Novell eDirectory" },
-        { "id": "other", "name": "Other" }
-    ];
-
-    $scope.authTypes = [
-        { "id": "none", "name": "none" },
-        { "id": "simple", "name": "simple" }
-    ];
-
-    $scope.searchScopes = [
-        { "id": "1", "name": "One Level" },
-        { "id": "2", "name": "Subtree" }
-    ];
-
-    $scope.realm = realm;
-
-    $scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
-        if (oldVal == newVal) {
-            return;
-        }
-
-        $scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
-        $scope.changed = true;
-    });
-
-    $scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
-        if (oldVal == newVal) {
-            return;
-        }
-
-        $scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
-        $scope.changed = true;
-    });
-
-    $scope.$watch('instance', function() {
-        if (!angular.equals($scope.instance, instance)) {
-            $scope.changed = true;
-        }
-
-        if (!angular.equals($scope.instance.config.vendor, $scope.lastVendor)) {
-            console.log("LDAP vendor changed");
-            $scope.lastVendor = $scope.instance.config.vendor;
-
-            if ($scope.lastVendor === "ad") {
-                $scope.instance.config.usernameLDAPAttribute = "cn";
-                $scope.instance.config.userObjectClasses = "person, organizationalPerson, user";
-            } else {
-                $scope.instance.config.usernameLDAPAttribute = "uid";
-                $scope.instance.config.userObjectClasses = "inetOrgPerson, organizationalPerson";
-            }
-
-            $scope.instance.config.rdnLDAPAttribute = $scope.instance.config.usernameLDAPAttribute;
-
-            var vendorToUUID = {
-                rhds: "nsuniqueid",
-                tivoli: "uniqueidentifier",
-                edirectory: "guid",
-                ad: "objectGUID",
-                other: "entryUUID"
-            };
-            $scope.instance.config.uuidLDAPAttribute = vendorToUUID[$scope.lastVendor];
-        }
-    }, true);
-
-    $scope.save = function() {
-        $scope.changed = false;
-
-        if (!parseInt($scope.instance.config.batchSizeForSync)) {
-            $scope.instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
-        } else {
-            $scope.instance.config.batchSizeForSync = parseInt($scope.instance.config.batchSizeForSync).toString();
-        }
-
-        if ($scope.create) {
-            UserFederationInstances.save({realm: realm.realm}, $scope.instance,  function (data, headers) {
-                var l = headers().location;
-                var id = l.substring(l.lastIndexOf("/") + 1);
-
-                $location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
-                Notifications.success("The provider has been created.");
-            });
-        } else {
-            UserFederationInstances.update({realm: realm.realm,
-                                          instance: instance.id
-                },
-                $scope.instance,  function () {
-                $route.reload();
-                Notifications.success("The provider has been updated.");
-            });
-
-        }
-    };
-
-    $scope.reset = function() {
-        $route.reload();
-    };
-
-    $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/user-federation");
-    };
-
-    $scope.remove = function() {
-        Dialog.confirm('Delete', 'Are you sure you want to permanently delete this provider?  All imported users will also be deleted.', function() {
-            $scope.instance.$remove({
-                realm : realm.realm,
-                instance : $scope.instance.id
-            }, function() {
-                $location.url("/realms/" + realm.realm + "/user-federation");
-                Notifications.success("The provider has been deleted.");
-            });
-        });
-    };
-
-
-    var initConnectionTest = function(testAction, ldapConfig) {
-        return {
-            action: testAction,
-            realm: $scope.realm.realm,
-            connectionUrl: ldapConfig.connectionUrl,
-            bindDn: ldapConfig.bindDn,
-            bindCredential: ldapConfig.bindCredential
-        };
-    };
-
-    $scope.testConnection = function() {
-        console.log('LDAPCtrl: testConnection');
-        RealmLDAPConnectionTester.get(initConnectionTest("testConnection", $scope.instance.config), function() {
-            Notifications.success("LDAP connection successful.");
-        }, function() {
-            Notifications.error("Error when trying to connect to LDAP. See server.log for details.");
-        });
-    }
-
-    $scope.testAuthentication = function() {
-        console.log('LDAPCtrl: testAuthentication');
-        RealmLDAPConnectionTester.get(initConnectionTest("testAuthentication", $scope.instance.config), function() {
-            Notifications.success("LDAP authentication successful.");
-        }, function() {
-            Notifications.error("LDAP authentication failed. See server.log for details");
-        });
-    }
-
-    $scope.triggerFullSync = function() {
-        console.log('LDAPCtrl: triggerFullSync');
-        triggerSync('triggerFullSync');
-    }
-
-    $scope.triggerChangedUsersSync = function() {
-        console.log('LDAPCtrl: triggerChangedUsersSync');
-        triggerSync('triggerChangedUsersSync');
-    }
-
-    function triggerSync(action) {
-        UserFederationSync.save({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, {}, function(syncResult) {
-            Notifications.success("Sync of users finished successfully. " + syncResult.status);
-        }, function() {
-            Notifications.error("Error during sync of users");
-        });
-    }
-
-});
-
-
-module.controller('UserFederationMapperListCtrl', function($scope, $location, Notifications, $route, Dialog, realm, provider, mapperTypes, mappers) {
-    console.log('UserFederationMapperListCtrl');
-
-    $scope.realm = realm;
-    $scope.provider = provider;
-
-    $scope.mapperTypes = mapperTypes;
-    $scope.mappers = mappers;
-
-    $scope.hasAnyMapperTypes = false;
-    for (var property in mapperTypes) {
-        if (!(property.indexOf('$') === 0)) {
-            $scope.hasAnyMapperTypes = true;
-            break;
-        }
-    }
-
-});
-
-module.controller('UserFederationMapperCtrl', function($scope, realm,  provider, mapperTypes, mapper, clients, UserFederationMapper, Notifications, Dialog, $location) {
-    console.log('UserFederationMapperCtrl');
-    $scope.realm = realm;
-    $scope.provider = provider;
-    $scope.clients = clients;
-    $scope.create = false;
-    $scope.mapper = angular.copy(mapper);
-    $scope.changed = false;
-    $scope.mapperType = mapperTypes[mapper.federationMapperType];
-
-    $scope.$watch('mapper', function() {
-        if (!angular.equals($scope.mapper, mapper)) {
-            $scope.changed = true;
-        }
-    }, true);
-
-    $scope.save = function() {
-        UserFederationMapper.update({
-            realm : realm.realm,
-            provider: provider.id,
-            mapperId : mapper.id
-        }, $scope.mapper, function() {
-            $scope.changed = false;
-            mapper = angular.copy($scope.mapper);
-            $location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + mapper.id);
-            Notifications.success("Your changes have been saved.");
-        }, function(error) {
-            if (error.status == 400 && error.data.error_description) {
-                Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
-            } else {
-                Notifications.error('Unexpected error when creating mapper');
-            }
-        });
-    };
-
-    $scope.reset = function() {
-        $scope.mapper = angular.copy(mapper);
-        $scope.changed = false;
-    };
-
-    $scope.cancel = function() {
-        window.history.back();
-    };
-
-    $scope.remove = function() {
-        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
-            UserFederationMapper.remove({ realm: realm.realm, provider: provider.id, mapperId : $scope.mapper.id }, function() {
-                Notifications.success("The mapper has been deleted.");
-                $location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers');
-            });
-        });
-    };
-
-});
-
-module.controller('UserFederationMapperCreateCtrl', function($scope, realm, provider, mapperTypes, clients, UserFederationMapper, Notifications, Dialog, $location) {
-    console.log('UserFederationMapperCreateCtrl');
-    $scope.realm = realm;
-    $scope.provider = provider;
-    $scope.clients = clients;
-    $scope.create = true;
-    $scope.mapper = { federationProviderDisplayName: provider.displayName, config: {}};
-    $scope.mapperTypes = mapperTypes;
-    $scope.mapperType = null;
-
-    $scope.$watch('mapperType', function() {
-        if ($scope.mapperType != null) {
-            $scope.mapper.config = {};
-            for ( var i = 0; i < $scope.mapperType.properties.length; i++) {
-                var property = $scope.mapperType.properties[i];
-                if (property.type === 'String' || property.type === 'boolean') {
-                    $scope.mapper.config[ property.name ] = property.defaultValue;
-                }
-            }
-        }
-    }, true);
-
-    $scope.save = function() {
-        if ($scope.mapperType == null) {
-            Notifications.error("You need to select mapper type!");
-            return;
-        }
-
-        $scope.mapper.federationMapperType = $scope.mapperType.id;
-        UserFederationMapper.save({
-            realm : realm.realm, provider: provider.id
-        }, $scope.mapper, function(data, headers) {
-            var l = headers().location;
-            var id = l.substring(l.lastIndexOf("/") + 1);
-            $location.url('/realms/' + realm.realm +'/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + id);
-            Notifications.success("Mapper has been created.");
-        }, function(error) {
-            if (error.status == 400 && error.data.error_description) {
-                Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
-            } else {
-                Notifications.error('Unexpected error when creating mapper');
-            }
-        });
-    };
-
-    $scope.cancel = function() {
-        window.history.back();
-    };
-
-
-});
-
+module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, clients, Notifications, RealmRoleMapping,
+                                                  ClientRoleMapping, AvailableRealmRoleMapping, AvailableClientRoleMapping,
+                                                  CompositeRealmRoleMapping, CompositeClientRoleMapping) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+    $scope.clients = clients;
+    $scope.clientRoles = [];
+    $scope.clientComposite = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientMappings = [];
+    $scope.clientMappings = [];
+    $scope.dummymodel = [];
+
+    $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
+    $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+    $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+
+    $scope.addRealmRole = function() {
+        var roles = $scope.selectedRealmRoles;
+        $scope.selectedRealmRoles = [];
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/realm',
+                roles).success(function() {
+                $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.selectedRealmMappings = [];
+                $scope.selectRealmRoles = [];
+                if ($scope.client) {
+                    console.log('load available');
+                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.selectedClientRoles = [];
+                    $scope.selectedClientMappings = [];
+                }
+                Notifications.success("Role mappings updated.");
+
+            });
+    };
+
+    $scope.deleteRealmRole = function() {
+        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/realm',
+            {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.realmRoles = AvailableRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.id});
+                $scope.selectedRealmMappings = [];
+                $scope.selectRealmRoles = [];
+                if ($scope.client) {
+                    console.log('load available');
+                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                    $scope.selectedClientRoles = [];
+                    $scope.selectedClientMappings = [];
+                }
+                Notifications.success("Role mappings updated.");
+            });
+    };
+
+    $scope.addClientRole = function() {
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/clients/' + $scope.client.id,
+                $scope.selectedClientRoles).success(function() {
+                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.selectedClientRoles = [];
+                $scope.selectedClientMappings = [];
+                Notifications.success("Role mappings updated.");
+            });
+    };
+
+    $scope.deleteClientRole = function() {
+        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.id + '/role-mappings/clients/' + $scope.client.id,
+            {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+                $scope.selectedClientRoles = [];
+                $scope.selectedClientMappings = [];
+                Notifications.success("Role mappings updated.");
+            });
+    };
+
+
+    $scope.changeClient = function() {
+        console.log('changeClient');
+        if ($scope.client) {
+            console.log('load available');
+            $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+            $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+            $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.id, client : $scope.client.id});
+        } else {
+            $scope.clientRoles = null;
+            $scope.clientMappings = null;
+            $scope.clientComposite = null;
+        }
+        $scope.selectedClientRoles = [];
+        $scope.selectedClientMappings = [];
+    };
+
+
+
+});
+
+module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, UserSessions, UserLogout, UserSessionLogout, Notifications) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.sessions = sessions;
+
+    $scope.logoutAll = function() {
+        UserLogout.save({realm : realm.realm, user: user.id}, function () {
+            Notifications.success('Logged out user in all clients');
+            UserSessions.query({realm: realm.realm, user: user.id}, function(updated) {
+                $scope.sessions = updated;
+            })
+        });
+    };
+
+    $scope.logoutSession = function(sessionId) {
+        console.log('here in logoutSession');
+        UserSessionLogout.delete({realm : realm.realm, session: sessionId}, function() {
+            UserSessions.query({realm: realm.realm, user: user.id}, function(updated) {
+                $scope.sessions = updated;
+                Notifications.success('Logged out session');
+            })
+        });
+    }
+});
+
+module.controller('UserFederatedIdentityCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications, Dialog) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.federatedIdentities = federatedIdentities;
+
+    $scope.hasAnyProvidersToCreate = function() {
+        return realm.identityProviders.length - $scope.federatedIdentities.length > 0;
+    }
+
+    $scope.removeProviderLink = function(providerLink) {
+
+        console.log("Removing provider link: " + providerLink.identityProvider);
+
+        Dialog.confirmDelete(providerLink.identityProvider, 'Identity Provider Link', function() {
+            UserFederatedIdentity.remove({ realm: realm.realm, user: user.id, provider: providerLink.identityProvider }, function() {
+                Notifications.success("The provider link has been deleted.");
+                var indexToRemove = $scope.federatedIdentities.indexOf(providerLink);
+                $scope.federatedIdentities.splice(indexToRemove, 1);
+            });
+        });
+    }
+});
+
+module.controller('UserFederatedIdentityAddCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.federatedIdentity = {};
+
+    var getAvailableProvidersToCreate = function() {
+        var realmProviders = [];
+        for (var i=0 ; i<realm.identityProviders.length ; i++) {
+            var providerAlias = realm.identityProviders[i].alias;
+            realmProviders.push(providerAlias);
+        };
+
+        for (var i=0 ; i<federatedIdentities.length ; i++) {
+            var providerAlias = federatedIdentities[i].identityProvider;
+            var index = realmProviders.indexOf(providerAlias);
+            realmProviders.splice(index, 1);
+        }
+
+        return realmProviders;
+    }
+    $scope.availableProvidersToCreate = getAvailableProvidersToCreate();
+
+    $scope.save = function() {
+        UserFederatedIdentity.save({
+            realm : realm.realm,
+            user: user.id,
+            provider: $scope.federatedIdentity.identityProvider
+        }, $scope.federatedIdentity, function(data, headers) {
+            $location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
+            Notifications.success("Provider link has been created.");
+        });
+    };
+
+    $scope.cancel = function() {
+         $location.url("/realms/" + realm.realm + '/users/' + $scope.user.id + '/federated-identity');
+    };
+
+});
+
+module.controller('UserConsentsCtrl', function($scope, realm, user, userConsents, UserConsents, Notifications) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.userConsents = userConsents;
+
+    $scope.revokeConsent = function(clientId) {
+        UserConsents.delete({realm : realm.realm, user: user.id, client: clientId }, function () {
+            UserConsents.query({realm: realm.realm, user: user.id}, function(updated) {
+                $scope.userConsents = updated;
+            })
+            Notifications.success('Consent revoked successfully');
+        }, function() {
+            Notifications.error("Consent couldn't be revoked");
+        });
+        console.log("Revoke consent " + clientId);
+    }
+});
+
+
+module.controller('UserListCtrl', function($scope, realm, User, UserImpersonation) {
+    $scope.realm = realm;
+    $scope.page = 0;
+
+    $scope.query = {
+        realm: realm.realm,
+        max : 5,
+        first : 0
+    }
+
+    $scope.impersonate = function(userId) {
+        UserImpersonation.save({realm : realm.realm, user: userId}, function (data) {
+            if (data.sameRealm) {
+                window.location = data.redirect;
+            } else {
+                window.open(data.redirect, "_blank");
+            }
+        });
+    };
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.searchQuery();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.searchQuery();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.searchQuery();
+    }
+
+    $scope.searchQuery = function() {
+        console.log("query.search: " + $scope.query.search);
+        $scope.searchLoaded = false;
+
+        $scope.users = User.query($scope.query, function() {
+            $scope.searchLoaded = true;
+            $scope.lastSearch = $scope.query.search;
+        });
+    };
+});
+
+
+
+module.controller('UserDetailCtrl', function($scope, realm, user, User, UserFederationInstances, UserImpersonation, RequiredActions, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.create = !user.id;
+    $scope.editUsername = $scope.create || $scope.realm.editUsernameAllowed;
+
+    if ($scope.create) {
+        $scope.user = { enabled: true, attributes: {} }
+    } else {
+        if (!user.attributes) {
+            user.attributes = {}
+        }
+        convertAttributeValuesToString(user);
+
+
+        $scope.user = angular.copy(user);
+        $scope.impersonate = function() {
+            UserImpersonation.save({realm : realm.realm, user: $scope.user.id}, function (data) {
+                if (data.sameRealm) {
+                    window.location = data.redirect;
+                } else {
+                    window.open(data.redirect, "_blank");
+                }
+            });
+        };
+        if(user.federationLink) {
+            console.log("federationLink is not null");
+            UserFederationInstances.get({realm : realm.realm, instance: user.federationLink}, function(link) {
+                $scope.federationLinkName = link.displayName;
+                $scope.federationLink = "#/realms/" + realm.realm + "/user-federation/providers/" + link.providerName + "/" + link.id;
+            })
+        } else {
+            console.log("federationLink is null");
+        }
+    }
+
+    $scope.changed = false; // $scope.create;
+    if (user.requiredActions) {
+        for (var i = 0; i < user.requiredActions.length; i++) {
+            console.log("user require action: " + user.requiredActions[i]);
+        }
+    }
+    // ID - Name map for required actions. IDs are enum names.
+    RequiredActions.query({id: realm.realm}, function(data) {
+        $scope.userReqActionList = [];
+        for (var i = 0; i < data.length; i++) {
+            console.log("listed required action: " + data[i].name);
+            if (data[i].enabled) {
+                var item = data[i];
+                $scope.userReqActionList.push(item);
+            }
+        }
+
+    });
+
+        /*[
+        {id: "VERIFY_EMAIL", text: "Verify Email"},
+        {id: "UPDATE_PROFILE", text: "Update Profile"},
+        {id: "CONFIGURE_TOTP", text: "Configure Totp"},
+        {id: "UPDATE_PASSWORD", text: "Update Password"}
+    ];
+    */
+
+    $scope.$watch('user', function() {
+        if (!angular.equals($scope.user, user)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        convertAttributeValuesToLists();
+
+        if ($scope.create) {
+            User.save({
+                realm: realm.realm
+            }, $scope.user, function (data, headers) {
+                $scope.changed = false;
+                convertAttributeValuesToString($scope.user);
+                user = angular.copy($scope.user);
+                var l = headers().location;
+
+                console.debug("Location == " + l);
+
+                var id = l.substring(l.lastIndexOf("/") + 1);
+
+
+                $location.url("/realms/" + realm.realm + "/users/" + id);
+                Notifications.success("The user has been created.");
+            });
+        } else {
+            User.update({
+                realm: realm.realm,
+                userId: $scope.user.id
+            }, $scope.user, function () {
+                $scope.changed = false;
+                convertAttributeValuesToString($scope.user);
+                user = angular.copy($scope.user);
+                Notifications.success("Your changes have been saved to the user.");
+            });
+        }
+    };
+
+    function convertAttributeValuesToLists() {
+        var attrs = $scope.user.attributes;
+        for (var attribute in attrs) {
+            if (typeof attrs[attribute] === "string") {
+                var attrVals = attrs[attribute].split("##");
+                attrs[attribute] = attrVals;
+            }
+        }
+    }
+
+    function convertAttributeValuesToString(user) {
+        var attrs = user.attributes;
+        for (var attribute in attrs) {
+            if (typeof attrs[attribute] === "object") {
+                var attrVals = attrs[attribute].join("##");
+                attrs[attribute] = attrVals;
+            }
+        }
+    }
+
+    $scope.reset = function() {
+        $scope.user = angular.copy(user);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.realm + "/users");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.user.id, 'user', function() {
+            $scope.user.$remove({
+                realm : realm.realm,
+                userId : $scope.user.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/users");
+                Notifications.success("The user has been deleted.");
+            }, function() {
+                Notifications.error("User couldn't be deleted");
+            });
+        });
+    };
+});
+
+module.controller('UserCredentialsCtrl', function($scope, realm, user, User, UserCredentials, Notifications, Dialog) {
+    console.log('UserCredentialsCtrl');
+
+    $scope.realm = realm;
+    $scope.user = angular.copy(user);
+    $scope.temporaryPassword = true;
+
+    $scope.isTotp = false;
+    if(!!user.totp){
+        $scope.isTotp = user.totp;
+    }
+
+    $scope.resetPassword = function() {
+        if ($scope.pwdChange) {
+            if ($scope.password != $scope.confirmPassword) {
+                Notifications.error("Password and confirmation does not match.");
+                return;
+            }
+        }
+
+        var msgTitle = 'Change password';
+        var msg = 'Are you sure you want to change the users password?';
+
+        Dialog.confirm(msgTitle, msg, function() {
+            UserCredentials.resetPassword({ realm: realm.realm, userId: user.id }, { type : "password", value : $scope.password, temporary: $scope.temporaryPassword }, function() {
+                Notifications.success("The password has been reset");
+                $scope.password = null;
+                $scope.confirmPassword = null;
+            }, function(response) {
+                if (response.data && response.data.errorMessage) {
+                    Notifications.error(response.data.errorMessage);
+                } else {
+                    Notifications.error("Failed to reset user password");
+                }
+            });
+        }, function() {
+            $scope.password = null;
+            $scope.confirmPassword = null;
+        });
+    };
+
+    $scope.removeTotp = function() {
+        Dialog.confirm('Remove totp', 'Are you sure you want to remove the users totp configuration?', function() {
+            UserCredentials.removeTotp({ realm: realm.realm, userId: user.id }, { }, function() {
+                Notifications.success("The users totp configuration has been removed");
+                $scope.user.totp = false;
+            }, function() {
+                Notifications.error("Failed to remove the users totp configuration");
+            });
+        });
+    };
+
+    $scope.resetPasswordEmail = function() {
+        Dialog.confirm('Reset password email', 'Are you sure you want to send password reset email to user?', function() {
+            UserCredentials.resetPasswordEmail({ realm: realm.realm, userId: user.id }, { }, function() {
+                Notifications.success("Password reset email sent to user");
+            }, function() {
+                Notifications.error("Failed to send password reset mail to user");
+            });
+        });
+    };
+
+    $scope.$watch('user', function() {
+        if (!angular.equals($scope.user, user)) {
+            $scope.userChange = true;
+        } else {
+            $scope.userChange = false;
+        }
+    }, true);
+
+    $scope.$watch('password', function() {
+        if (!!$scope.password){
+            $scope.pwdChange = true;
+        } else {
+            $scope.pwdChange = false;
+        }
+    }, true);
+
+    $scope.reset = function() {
+        $scope.password = "";
+        $scope.confirmPassword = "";
+
+        $scope.user = angular.copy(user);
+
+        $scope.isTotp = false;
+        if(!!user.totp){
+            $scope.isTotp = user.totp;
+        }
+
+        $scope.pwdChange = false;
+        $scope.userChange = false;
+    };
+});
+
+module.controller('UserFederationCtrl', function($scope, $location, realm, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
+    console.log('UserFederationCtrl ++++****');
+    $scope.realm = realm;
+    $scope.providers = UserFederationProviders.query({realm: realm.realm});
+
+    $scope.addProvider = function(provider) {
+        console.log('Add provider: ' + provider.id);
+        $location.url("/create/user-federation/" + realm.realm + "/providers/" + provider.id);
+    };
+
+    $scope.instances = UserFederationInstances.query({realm: realm.realm});
+
+});
+
+module.controller('GenericUserFederationCtrl', function($scope, $location, Notifications, $route, Dialog, realm, instance, providerFactory, UserFederationInstances, UserFederationSync) {
+    console.log('GenericUserFederationCtrl');
+
+    $scope.create = !instance.providerName;
+    $scope.providerFactory = providerFactory;
+
+    console.log("providerFactory: " + providerFactory.id);
+
+    function initFederationSettings() {
+        if ($scope.create) {
+            instance.providerName = providerFactory.id;
+            instance.config = {};
+            instance.priority = 0;
+            $scope.fullSyncEnabled = false;
+            $scope.changedSyncEnabled = false;
+
+            if (providerFactory.id === 'kerberos') {
+                instance.config.debug = false;
+                instance.config.allowPasswordAuthentication = true;
+                instance.config.editMode = 'UNSYNCED';
+                instance.config.updateProfileFirstLogin = true;
+                instance.config.allowKerberosAuthentication = true;
+            }
+        } else {
+            $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
+            $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
+
+            if (providerFactory.id === 'kerberos') {
+                instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
+                instance.config.allowPasswordAuthentication = (instance.config.allowPasswordAuthentication === 'true' || instance.config.allowPasswordAuthentication === true);
+                instance.config.updateProfileFirstLogin = (instance.config.updateProfileFirstLogin === 'true' || instance.config.updateProfileFirstLogin === true);
+            }
+        }
+
+        $scope.changed = false;
+    }
+
+    initFederationSettings();
+    $scope.instance = angular.copy(instance);
+    $scope.realm = realm;
+
+    $scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
+        if (oldVal == newVal) {
+            return;
+        }
+
+        $scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
+        $scope.changed = true;
+    });
+
+    $scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
+        if (oldVal == newVal) {
+            return;
+        }
+
+        $scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
+        $scope.changed = true;
+    });
+
+    $scope.$watch('instance', function() {
+        if (!angular.equals($scope.instance, instance)) {
+            $scope.changed = true;
+        }
+
+    }, true);
+
+    $scope.save = function() {
+        $scope.changed = false;
+        if ($scope.create) {
+            UserFederationInstances.save({realm: realm.realm}, $scope.instance,  function (data, headers) {
+                var l = headers().location;
+                var id = l.substring(l.lastIndexOf("/") + 1);
+
+                $location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
+                Notifications.success("The provider has been created.");
+            });
+        } else {
+            UserFederationInstances.update({realm: realm.realm,
+                    instance: instance.id
+                },
+                $scope.instance,  function () {
+                    $route.reload();
+                    Notifications.success("The provider has been updated.");
+                });
+        }
+    };
+
+    $scope.reset = function() {
+        initFederationSettings();
+        $scope.instance = angular.copy(instance);
+    };
+
+    $scope.cancel = function() {
+        if ($scope.create) {
+            $location.url("/realms/" + realm.realm + "/user-federation");
+        } else {
+            $route.reload();
+        }
+    };
+
+    $scope.remove = function() {
+        Dialog.confirm('Delete', 'Are you sure you want to permanently delete this provider?  All imported users will also be deleted.', function() {
+            $scope.instance.$remove({
+                realm : realm.realm,
+                instance : $scope.instance.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/user-federation");
+                Notifications.success("The provider has been deleted.");
+            });
+        });
+    };
+
+    $scope.triggerFullSync = function() {
+        console.log('GenericCtrl: triggerFullSync');
+        triggerSync('triggerFullSync');
+    }
+
+    $scope.triggerChangedUsersSync = function() {
+        console.log('GenericCtrl: triggerChangedUsersSync');
+        triggerSync('triggerChangedUsersSync');
+    }
+
+    function triggerSync(action) {
+        UserFederationSync.save({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, {}, function(syncResult) {
+            Notifications.success("Sync of users finished successfully. " + syncResult.status);
+        }, function() {
+            Notifications.error("Error during sync of users");
+        });
+    }
+});
+
+
+module.controller('LDAPCtrl', function($scope, $location, $route, Notifications, Dialog, realm, instance, UserFederationInstances, UserFederationSync, RealmLDAPConnectionTester) {
+    console.log('LDAPCtrl');
+    var DEFAULT_BATCH_SIZE = "1000";
+
+    $scope.create = !instance.providerName;
+
+    function initFederationSettings() {
+        if ($scope.create) {
+            instance.providerName = "ldap";
+            instance.config = {};
+            instance.priority = 0;
+
+            instance.config.syncRegistrations = false;
+            instance.config.userAccountControlsAfterPasswordUpdate = true;
+            instance.config.connectionPooling = true;
+            instance.config.pagination = true;
+
+            instance.config.allowKerberosAuthentication = false;
+            instance.config.debug = false;
+            instance.config.useKerberosForPasswordAuthentication = false;
+
+            instance.config.authType = 'simple';
+            instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
+            instance.config.searchScope = "1";
+
+            $scope.fullSyncEnabled = false;
+            $scope.changedSyncEnabled = false;
+        } else {
+            instance.config.syncRegistrations = (instance.config.syncRegistrations === 'true' || instance.config.syncRegistrations === true);
+            instance.config.userAccountControlsAfterPasswordUpdate = (instance.config.userAccountControlsAfterPasswordUpdate === 'true' || instance.config.userAccountControlsAfterPasswordUpdate === true);
+            instance.config.connectionPooling = (instance.config.connectionPooling === 'true' || instance.config.connectionPooling === true);
+            instance.config.pagination = (instance.config.pagination === 'true' || instance.config.pagination === true);
+
+            instance.config.allowKerberosAuthentication = (instance.config.allowKerberosAuthentication === 'true' || instance.config.allowKerberosAuthentication === true);
+            instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
+            instance.config.useKerberosForPasswordAuthentication = (instance.config.useKerberosForPasswordAuthentication === 'true' || instance.config.useKerberosForPasswordAuthentication === true);
+
+            if (!instance.config.authType) {
+                instance.config.authType = 'simple';
+            }
+            if (!instance.config.batchSizeForSync) {
+                instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
+            }
+            if (!instance.config.searchScope) {
+                instance.config.searchScope = '1';
+            }
+
+            $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
+            $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
+        }
+
+        $scope.changed = false;
+        $scope.lastVendor = instance.config.vendor;
+    }
+
+    initFederationSettings();
+    $scope.instance = angular.copy(instance);
+
+    $scope.ldapVendors = [
+        { "id": "ad", "name": "Active Directory" },
+        { "id": "rhds", "name": "Red Hat Directory Server" },
+        { "id": "tivoli", "name": "Tivoli" },
+        { "id": "edirectory", "name": "Novell eDirectory" },
+        { "id": "other", "name": "Other" }
+    ];
+
+    $scope.authTypes = [
+        { "id": "none", "name": "none" },
+        { "id": "simple", "name": "simple" }
+    ];
+
+    $scope.searchScopes = [
+        { "id": "1", "name": "One Level" },
+        { "id": "2", "name": "Subtree" }
+    ];
+
+    $scope.realm = realm;
+
+    $scope.$watch('fullSyncEnabled', function(newVal, oldVal) {
+        if (oldVal == newVal) {
+            return;
+        }
+
+        $scope.instance.fullSyncPeriod = $scope.fullSyncEnabled ? 604800 : -1;
+        $scope.changed = true;
+    });
+
+    $scope.$watch('changedSyncEnabled', function(newVal, oldVal) {
+        if (oldVal == newVal) {
+            return;
+        }
+
+        $scope.instance.changedSyncPeriod = $scope.changedSyncEnabled ? 86400 : -1;
+        $scope.changed = true;
+    });
+
+    $scope.$watch('instance', function() {
+        if (!angular.equals($scope.instance, instance)) {
+            $scope.changed = true;
+        }
+
+        if (!angular.equals($scope.instance.config.vendor, $scope.lastVendor)) {
+            console.log("LDAP vendor changed");
+            $scope.lastVendor = $scope.instance.config.vendor;
+
+            if ($scope.lastVendor === "ad") {
+                $scope.instance.config.usernameLDAPAttribute = "cn";
+                $scope.instance.config.userObjectClasses = "person, organizationalPerson, user";
+            } else {
+                $scope.instance.config.usernameLDAPAttribute = "uid";
+                $scope.instance.config.userObjectClasses = "inetOrgPerson, organizationalPerson";
+            }
+
+            $scope.instance.config.rdnLDAPAttribute = $scope.instance.config.usernameLDAPAttribute;
+
+            var vendorToUUID = {
+                rhds: "nsuniqueid",
+                tivoli: "uniqueidentifier",
+                edirectory: "guid",
+                ad: "objectGUID",
+                other: "entryUUID"
+            };
+            $scope.instance.config.uuidLDAPAttribute = vendorToUUID[$scope.lastVendor];
+        }
+    }, true);
+
+    $scope.save = function() {
+        $scope.changed = false;
+
+        if (!parseInt($scope.instance.config.batchSizeForSync)) {
+            $scope.instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
+        } else {
+            $scope.instance.config.batchSizeForSync = parseInt($scope.instance.config.batchSizeForSync).toString();
+        }
+
+        if ($scope.create) {
+            UserFederationInstances.save({realm: realm.realm}, $scope.instance,  function (data, headers) {
+                var l = headers().location;
+                var id = l.substring(l.lastIndexOf("/") + 1);
+
+                $location.url("/realms/" + realm.realm + "/user-federation/providers/" + $scope.instance.providerName + "/" + id);
+                Notifications.success("The provider has been created.");
+            });
+        } else {
+            UserFederationInstances.update({realm: realm.realm,
+                                          instance: instance.id
+                },
+                $scope.instance,  function () {
+                $route.reload();
+                Notifications.success("The provider has been updated.");
+            });
+
+        }
+    };
+
+    $scope.reset = function() {
+        $route.reload();
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.realm + "/user-federation");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirm('Delete', 'Are you sure you want to permanently delete this provider?  All imported users will also be deleted.', function() {
+            $scope.instance.$remove({
+                realm : realm.realm,
+                instance : $scope.instance.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/user-federation");
+                Notifications.success("The provider has been deleted.");
+            });
+        });
+    };
+
+
+    var initConnectionTest = function(testAction, ldapConfig) {
+        return {
+            action: testAction,
+            realm: $scope.realm.realm,
+            connectionUrl: ldapConfig.connectionUrl,
+            bindDn: ldapConfig.bindDn,
+            bindCredential: ldapConfig.bindCredential
+        };
+    };
+
+    $scope.testConnection = function() {
+        console.log('LDAPCtrl: testConnection');
+        RealmLDAPConnectionTester.get(initConnectionTest("testConnection", $scope.instance.config), function() {
+            Notifications.success("LDAP connection successful.");
+        }, function() {
+            Notifications.error("Error when trying to connect to LDAP. See server.log for details.");
+        });
+    }
+
+    $scope.testAuthentication = function() {
+        console.log('LDAPCtrl: testAuthentication');
+        RealmLDAPConnectionTester.get(initConnectionTest("testAuthentication", $scope.instance.config), function() {
+            Notifications.success("LDAP authentication successful.");
+        }, function() {
+            Notifications.error("LDAP authentication failed. See server.log for details");
+        });
+    }
+
+    $scope.triggerFullSync = function() {
+        console.log('LDAPCtrl: triggerFullSync');
+        triggerSync('triggerFullSync');
+    }
+
+    $scope.triggerChangedUsersSync = function() {
+        console.log('LDAPCtrl: triggerChangedUsersSync');
+        triggerSync('triggerChangedUsersSync');
+    }
+
+    function triggerSync(action) {
+        UserFederationSync.save({ action: action, realm: $scope.realm.realm, provider: $scope.instance.id }, {}, function(syncResult) {
+            Notifications.success("Sync of users finished successfully. " + syncResult.status);
+        }, function() {
+            Notifications.error("Error during sync of users");
+        });
+    }
+
+});
+
+
+module.controller('UserFederationMapperListCtrl', function($scope, $location, Notifications, $route, Dialog, realm, provider, mapperTypes, mappers) {
+    console.log('UserFederationMapperListCtrl');
+
+    $scope.realm = realm;
+    $scope.provider = provider;
+
+    $scope.mapperTypes = mapperTypes;
+    $scope.mappers = mappers;
+
+    $scope.hasAnyMapperTypes = false;
+    for (var property in mapperTypes) {
+        if (!(property.indexOf('$') === 0)) {
+            $scope.hasAnyMapperTypes = true;
+            break;
+        }
+    }
+
+});
+
+module.controller('UserFederationMapperCtrl', function($scope, realm,  provider, mapperTypes, mapper, clients, UserFederationMapper, Notifications, Dialog, $location) {
+    console.log('UserFederationMapperCtrl');
+    $scope.realm = realm;
+    $scope.provider = provider;
+    $scope.clients = clients;
+    $scope.create = false;
+    $scope.mapper = angular.copy(mapper);
+    $scope.changed = false;
+    $scope.mapperType = mapperTypes[mapper.federationMapperType];
+
+    $scope.$watch('mapper', function() {
+        if (!angular.equals($scope.mapper, mapper)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        UserFederationMapper.update({
+            realm : realm.realm,
+            provider: provider.id,
+            mapperId : mapper.id
+        }, $scope.mapper, function() {
+            $scope.changed = false;
+            mapper = angular.copy($scope.mapper);
+            $location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + mapper.id);
+            Notifications.success("Your changes have been saved.");
+        }, function(error) {
+            if (error.status == 400 && error.data.error_description) {
+                Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
+            } else {
+                Notifications.error('Unexpected error when creating mapper');
+            }
+        });
+    };
+
+    $scope.reset = function() {
+        $scope.mapper = angular.copy(mapper);
+        $scope.changed = false;
+    };
+
+    $scope.cancel = function() {
+        window.history.back();
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.mapper.name, 'mapper', function() {
+            UserFederationMapper.remove({ realm: realm.realm, provider: provider.id, mapperId : $scope.mapper.id }, function() {
+                Notifications.success("The mapper has been deleted.");
+                $location.url("/realms/" + realm.realm + '/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers');
+            });
+        });
+    };
+
+});
+
+module.controller('UserFederationMapperCreateCtrl', function($scope, realm, provider, mapperTypes, clients, UserFederationMapper, Notifications, Dialog, $location) {
+    console.log('UserFederationMapperCreateCtrl');
+    $scope.realm = realm;
+    $scope.provider = provider;
+    $scope.clients = clients;
+    $scope.create = true;
+    $scope.mapper = { federationProviderDisplayName: provider.displayName, config: {}};
+    $scope.mapperTypes = mapperTypes;
+    $scope.mapperType = null;
+
+    $scope.$watch('mapperType', function() {
+        if ($scope.mapperType != null) {
+            $scope.mapper.config = {};
+            for ( var i = 0; i < $scope.mapperType.properties.length; i++) {
+                var property = $scope.mapperType.properties[i];
+                if (property.type === 'String' || property.type === 'boolean') {
+                    $scope.mapper.config[ property.name ] = property.defaultValue;
+                }
+            }
+        }
+    }, true);
+
+    $scope.save = function() {
+        if ($scope.mapperType == null) {
+            Notifications.error("You need to select mapper type!");
+            return;
+        }
+
+        $scope.mapper.federationMapperType = $scope.mapperType.id;
+        UserFederationMapper.save({
+            realm : realm.realm, provider: provider.id
+        }, $scope.mapper, function(data, headers) {
+            var l = headers().location;
+            var id = l.substring(l.lastIndexOf("/") + 1);
+            $location.url('/realms/' + realm.realm +'/user-federation/providers/' + provider.providerName + '/' + provider.id + '/mappers/' + id);
+            Notifications.success("Mapper has been created.");
+        }, function(error) {
+            if (error.status == 400 && error.data.error_description) {
+                Notifications.error('Error in configuration of mapper: ' + error.data.error_description);
+            } else {
+                Notifications.error('Unexpected error when creating mapper');
+            }
+        });
+    };
+
+    $scope.cancel = function() {
+        window.history.back();
+    };
+
+
+});
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
index 4c65931..d0fc0d1 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
@@ -1,65 +1,65 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Authentication</h1>
-
-    <kc-tabs-authentication></kc-tabs-authentication>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th colspan="6" class="kc-table-actions">
-                <div class="dropdown pull-left">
-                    <select class="form-control" ng-model="flow"
-                            ng-options="flow.alias for flow in flows"
-                            data-ng-change="setupForm()">
-                    </select>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="executions.length == 0">
-            <th colspan="2">Auth Type</th>
-            <th colspan="{{flowmax}}">Requirement</th>
-            <th></th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
-            <td ng-show="execution.subFlow"></td>
-            <td><h2>{{execution.referenceType}}</h2></td>
-            <td ng-hide="execution.subFlow"></td>
-            <td ng-repeat="choice in execution.requirementChoices">
-                <!--
-                <div class="dropdown pull-left">
-                <select class="form-control"
-                        ng-model="execution.requirement"
-                        ng-options="choice for choice in execution.requirementChoices">
-                </select>
-                </div>
-                -->
-                <!--
-                <div ng-repeat="choice in execution.requirementChoices">
-                <label >
-                    <input type="radio" ng-model="execution.requirement" ng-value="choice">
-                    {{choice}}
-                </label>
-                </div>
-                -->
-            <label >
-                <input type="radio" ng-model="execution.requirement" ng-value="choice" ng-change="updateExecution(execution)">
-                {{choice}}
-            </label>
-
-            </td>
-            <td ng-repeat="emptee in execution.empties"></td>
-            <td>
-                <a data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default" href="#/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Configure</a>
-                <a data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default" href="#/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Configure</a>
-            </td>
-         </tr>
-        <tr data-ng-show="executions.length == 0">
-            <td>No executions available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Authentication</h1>
+
+    <kc-tabs-authentication></kc-tabs-authentication>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th colspan="6" class="kc-table-actions">
+                <div class="dropdown pull-left">
+                    <select class="form-control" ng-model="flow"
+                            ng-options="flow.alias for flow in flows"
+                            data-ng-change="setupForm()">
+                    </select>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="executions.length == 0">
+            <th colspan="2">Auth Type</th>
+            <th colspan="{{flowmax}}">Requirement</th>
+            <th></th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
+            <td ng-show="execution.subFlow"></td>
+            <td><h2>{{execution.referenceType}}</h2></td>
+            <td ng-hide="execution.subFlow"></td>
+            <td ng-repeat="choice in execution.requirementChoices">
+                <!--
+                <div class="dropdown pull-left">
+                <select class="form-control"
+                        ng-model="execution.requirement"
+                        ng-options="choice for choice in execution.requirementChoices">
+                </select>
+                </div>
+                -->
+                <!--
+                <div ng-repeat="choice in execution.requirementChoices">
+                <label >
+                    <input type="radio" ng-model="execution.requirement" ng-value="choice">
+                    {{choice}}
+                </label>
+                </div>
+                -->
+            <label >
+                <input type="radio" ng-model="execution.requirement" ng-value="choice" ng-change="updateExecution(execution)">
+                {{choice}}
+            </label>
+
+            </td>
+            <td ng-repeat="emptee in execution.empties"></td>
+            <td>
+                <a data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default" href="#/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Configure</a>
+                <a data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default" href="#/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Configure</a>
+            </td>
+         </tr>
+        <tr data-ng-show="executions.length == 0">
+            <td>No executions available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
index 58bae3c..9060eed 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
@@ -1,48 +1,48 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/authentication/flows">Authentication Flows</a></li>
-        <li class="active" data-ng-show="create">Create Authenticator Config</li>
-        <li class="active" data-ng-hide="create">{{config.alias}}</li>
-    </ol>
-
-    <h1 data-ng-show="create">Create Authenticator Config</h1>
-    <h1 data-ng-hide="create">{{config.alias|capitalize}}<a><i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm"
-    	data-ng-hide="changed" data-ng-click="remove()"></i></a></h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-
-        <fieldset>
-            <div class="form-group clearfix" data-ng-show="!create">
-                <label class="col-md-2 control-label" for="configId">ID </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="configId" type="text" ng-model="config.id" readonly>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="name">Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="name" type="text" ng-model="config.alias" data-ng-readonly="!create">
-                </div>
-                <kc-tooltip>Name of the configuration.</kc-tooltip>
-            </div>
-            <kc-provider-config realm="realm" config="config.config" properties="configType.properties"></kc-provider-config>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageRealm">
-                <button kc-save>Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/authentication/flows">Authentication Flows</a></li>
+        <li class="active" data-ng-show="create">Create Authenticator Config</li>
+        <li class="active" data-ng-hide="create">{{config.alias}}</li>
+    </ol>
+
+    <h1 data-ng-show="create">Create Authenticator Config</h1>
+    <h1 data-ng-hide="create">{{config.alias|capitalize}}<a><i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm"
+    	data-ng-hide="changed" data-ng-click="remove()"></i></a></h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+
+        <fieldset>
+            <div class="form-group clearfix" data-ng-show="!create">
+                <label class="col-md-2 control-label" for="configId">ID </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="configId" type="text" ng-model="config.id" readonly>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="name">Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="name" type="text" ng-model="config.alias" data-ng-readonly="!create">
+                </div>
+                <kc-tooltip>Name of the configuration.</kc-tooltip>
+            </div>
+            <kc-provider-config realm="realm" config="config.config" properties="configType.properties"></kc-provider-config>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageRealm">
+                <button kc-save>Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/brute-force.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/brute-force.html
index cd1c754..a4f6db0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/brute-force.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/brute-force.html
@@ -1,108 +1,108 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <ul class="nav nav-tabs nav-tabs-pf">
-        <li><a href="#/realms/{{realm.realm}}/defense/headers">Headers</a></li>
-        <li class="active"><a href="#/realms/{{realm.realm}}/defense/brute-force">Brute Force Detection</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="bruteForceProtected">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.bruteForceProtected" name="bruteForceProtected" id="bruteForceProtected" onoffswitch />
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="failureFactor">Failure Factor</label>
-
-                <div class="col-md-2">
-                    <input class="form-control" type="number" min="1" max="31536000" id="failureFactor" name="failureFactor" data-ng-model="realm.failureFactor" autofocus
-                           required>
-                </div>
-                <kc-tooltip>How many failures before wait is triggered.</kc-tooltip>
-            </div>
-            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="waitIncrement">Wait Increment</label>
-                <div class="col-md-6 form-inline">
-                    <input class="form-control" type="number" required min="1"
-                           max="31536000" data-ng-model="realm.waitIncrement"
-                           id="waitIncrement" name="waitIncrement"/>
-                    <select class="form-control" name="waitIncrementUnit" data-ng-model="realm.waitIncrementUnit" >
-                        <option data-ng-selected="!realm.waitIncrementUnit">Seconds</option>
-                        <option>Minutes</option>
-                        <option>Hours</option>
-                        <option>Days</option>
-                    </select>
-                </div>
-                <kc-tooltip>When failure threshold has been met, how much time should the user be locked out?</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="quickLoginCheckMilliSeconds">Quick Login Check Milli Seconds</label>
-
-                <div class="col-md-2">
-                    <input class="form-control" type="number" min="1" max="31536000" id="quickLoginCheckMilliSeconds" name="quickLoginCheckMilliSeconds" data-ng-model="realm.quickLoginCheckMilliSeconds" autofocus
-                           required>
-                </div>
-                <kc-tooltip>If a failure happens concurrently too quickly, lock out the user.</kc-tooltip>
-            </div>
-            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="minimumQuickLoginWait">Minimum Quick Login Wait</label>
-                <div class="col-md-6 form-inline">
-                    <input class="form-control" type="number" required min="1"
-                           max="31536000" data-ng-model="realm.minimumQuickLoginWait"
-                           id="minimumQuickLoginWait" name="minimumQuickLoginWait"/>
-                    <select class="form-control" name="minimumQuickLoginWaitUnit" data-ng-model="realm.minimumQuickLoginWaitUnit" >
-                        <option data-ng-selected="!realm.minimumQuickLoginWaitUnit">Seconds</option>
-                        <option>Minutes</option>
-                        <option>Hours</option>
-                        <option>Days</option>
-                    </select>
-                </div>
-                <kc-tooltip>How long to wait after a quick login failure.</kc-tooltip>
-            </div>
-            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="maxFailureWait">Max Wait</label>
-                <div class="col-md-6 form-inline">
-                    <input class="form-control" type="number" required min="1"
-                                   max="31536000" data-ng-model="realm.maxFailureWait"
-                                   id="maxFailureWait" name="maxFailureWait"/>
-                    <select class="form-control" name="maxFailureWaitUnit" data-ng-model="realm.maxFailureWaitUnit" >
-                        <option data-ng-selected="!realm.maxFailureWaitUnit">Seconds</option>
-                        <option>Minutes</option>
-                        <option>Hours</option>
-                        <option>Days</option>
-                    </select>
-                </div>
-                <kc-tooltip>Max time a user will be locked out.</kc-tooltip>
-            </div>
-            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
-                <label class="col-md-2 control-label" for="maxDeltaTime">Failure Reset Time</label>
-                <div class="col-md-6 form-inline">
-                    <input class="form-control" type="number" required min="1"
-                           max="31536000" data-ng-model="realm.maxDeltaTime"
-                           id="maxDeltaTime" name="maxDeltaTime"/>
-                    <select class="form-control" name="maxDeltaTimeUnit" data-ng-model="realm.maxDeltaTimeUnit" >
-                        <option data-ng-selected="!realm.maxDeltaTimeUnit">Seconds</option>
-                        <option>Minutes</option>
-                        <option>Hours</option>
-                        <option>Days</option>
-                    </select>
-                </div>
-                <kc-tooltip>When will failure count be reset?</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <ul class="nav nav-tabs nav-tabs-pf">
+        <li><a href="#/realms/{{realm.realm}}/defense/headers">Headers</a></li>
+        <li class="active"><a href="#/realms/{{realm.realm}}/defense/brute-force">Brute Force Detection</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="bruteForceProtected">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.bruteForceProtected" name="bruteForceProtected" id="bruteForceProtected" onoffswitch />
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="failureFactor">Failure Factor</label>
+
+                <div class="col-md-2">
+                    <input class="form-control" type="number" min="1" max="31536000" id="failureFactor" name="failureFactor" data-ng-model="realm.failureFactor" autofocus
+                           required>
+                </div>
+                <kc-tooltip>How many failures before wait is triggered.</kc-tooltip>
+            </div>
+            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="waitIncrement">Wait Increment</label>
+                <div class="col-md-6 form-inline">
+                    <input class="form-control" type="number" required min="1"
+                           max="31536000" data-ng-model="realm.waitIncrement"
+                           id="waitIncrement" name="waitIncrement"/>
+                    <select class="form-control" name="waitIncrementUnit" data-ng-model="realm.waitIncrementUnit" >
+                        <option data-ng-selected="!realm.waitIncrementUnit">Seconds</option>
+                        <option>Minutes</option>
+                        <option>Hours</option>
+                        <option>Days</option>
+                    </select>
+                </div>
+                <kc-tooltip>When failure threshold has been met, how much time should the user be locked out?</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="quickLoginCheckMilliSeconds">Quick Login Check Milli Seconds</label>
+
+                <div class="col-md-2">
+                    <input class="form-control" type="number" min="1" max="31536000" id="quickLoginCheckMilliSeconds" name="quickLoginCheckMilliSeconds" data-ng-model="realm.quickLoginCheckMilliSeconds" autofocus
+                           required>
+                </div>
+                <kc-tooltip>If a failure happens concurrently too quickly, lock out the user.</kc-tooltip>
+            </div>
+            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="minimumQuickLoginWait">Minimum Quick Login Wait</label>
+                <div class="col-md-6 form-inline">
+                    <input class="form-control" type="number" required min="1"
+                           max="31536000" data-ng-model="realm.minimumQuickLoginWait"
+                           id="minimumQuickLoginWait" name="minimumQuickLoginWait"/>
+                    <select class="form-control" name="minimumQuickLoginWaitUnit" data-ng-model="realm.minimumQuickLoginWaitUnit" >
+                        <option data-ng-selected="!realm.minimumQuickLoginWaitUnit">Seconds</option>
+                        <option>Minutes</option>
+                        <option>Hours</option>
+                        <option>Days</option>
+                    </select>
+                </div>
+                <kc-tooltip>How long to wait after a quick login failure.</kc-tooltip>
+            </div>
+            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="maxFailureWait">Max Wait</label>
+                <div class="col-md-6 form-inline">
+                    <input class="form-control" type="number" required min="1"
+                                   max="31536000" data-ng-model="realm.maxFailureWait"
+                                   id="maxFailureWait" name="maxFailureWait"/>
+                    <select class="form-control" name="maxFailureWaitUnit" data-ng-model="realm.maxFailureWaitUnit" >
+                        <option data-ng-selected="!realm.maxFailureWaitUnit">Seconds</option>
+                        <option>Minutes</option>
+                        <option>Hours</option>
+                        <option>Days</option>
+                    </select>
+                </div>
+                <kc-tooltip>Max time a user will be locked out.</kc-tooltip>
+            </div>
+            <div class="form-group input-select" data-ng-show="realm.bruteForceProtected">
+                <label class="col-md-2 control-label" for="maxDeltaTime">Failure Reset Time</label>
+                <div class="col-md-6 form-inline">
+                    <input class="form-control" type="number" required min="1"
+                           max="31536000" data-ng-model="realm.maxDeltaTime"
+                           id="maxDeltaTime" name="maxDeltaTime"/>
+                    <select class="form-control" name="maxDeltaTimeUnit" data-ng-model="realm.maxDeltaTimeUnit" >
+                        <option data-ng-selected="!realm.maxDeltaTimeUnit">Seconds</option>
+                        <option>Minutes</option>
+                        <option>Hours</option>
+                        <option>Days</option>
+                    </select>
+                </div>
+                <kc-tooltip>When will failure count be reset?</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/claims.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/claims.html
index bdca2ca..494e4f6 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/claims.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/claims.html
@@ -1,62 +1,62 @@
-    <fieldset class="border-top">
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="username">Username</label>
-            <div class="col-md-6">
-                <input ng-model="claims.username" name="username" id="username" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="claimName">Name</label>
-            <div class="col-md-6">
-                <input ng-model="claims.name" name="claimName" id="claimName" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="email">Email</label>
-            <div class="col-md-6">
-                <input ng-model="claims.email" name="email" id="email" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="gender">Gender</label>
-            <div class="col-md-6">
-                <input ng-model="claims.gender" name="gender" id="gender" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="address">Address</label>
-            <div class="col-md-6">
-                <input ng-model="claims.address" name="address" id="address" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="locale">Locale</label>
-            <div class="col-md-6">
-                <input ng-model="claims.locale" name="locale" id="locale" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="phone">Phone</label>
-            <div class="col-md-6">
-                <input ng-model="claims.phone" name="phone" id="phone" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="profile">Profile URL</label>
-            <div class="col-md-6">
-                <input ng-model="claims.profile" name="profile" id="profile" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="picture">Picture URL</label>
-            <div class="col-md-6">
-                <input ng-model="claims.picture" name="picture" id="picture" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="website">Website</label>
-            <div class="col-md-6">
-                <input ng-model="claims.website" name="website" id="website" onoffswitch />
-            </div>
-        </div>
+    <fieldset class="border-top">
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="username">Username</label>
+            <div class="col-md-6">
+                <input ng-model="claims.username" name="username" id="username" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="claimName">Name</label>
+            <div class="col-md-6">
+                <input ng-model="claims.name" name="claimName" id="claimName" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="email">Email</label>
+            <div class="col-md-6">
+                <input ng-model="claims.email" name="email" id="email" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="gender">Gender</label>
+            <div class="col-md-6">
+                <input ng-model="claims.gender" name="gender" id="gender" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="address">Address</label>
+            <div class="col-md-6">
+                <input ng-model="claims.address" name="address" id="address" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="locale">Locale</label>
+            <div class="col-md-6">
+                <input ng-model="claims.locale" name="locale" id="locale" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="phone">Phone</label>
+            <div class="col-md-6">
+                <input ng-model="claims.phone" name="phone" id="phone" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="profile">Profile URL</label>
+            <div class="col-md-6">
+                <input ng-model="claims.profile" name="profile" id="profile" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="picture">Picture URL</label>
+            <div class="col-md-6">
+                <input ng-model="claims.picture" name="picture" id="picture" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="website">Website</label>
+            <div class="col-md-6">
+                <input ng-model="claims.website" name="website" id="website" onoffswitch />
+            </div>
+        </div>
     </fieldset>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
index efdc15d..540dddb 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
@@ -1,28 +1,28 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients">
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="secret">Secret</label>
-            <div class="col-sm-6">
-                <input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret">
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
-                <button type="submit" data-ng-click="changePassword()" class="btn btn-primary">Regenerate Secret</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients">
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="secret">Secret</label>
+            <div class="col-sm-6">
+                <input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret">
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+                <button type="submit" data-ng-click="changePassword()" class="btn btn-primary">Regenerate Secret</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index 808f92a..d8ea265 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -1,288 +1,288 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li data-ng-show="create">Add Client</li>
-        <li data-ng-hide="create">{{client.clientId}}</li>
-    </ol>
-
-    <h1 data-ng-show="create">Add Client</h1>
-    <h1 data-ng-hide="create">{{client.clientId|capitalize}}<i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageClients" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="clientId">Client ID <span class="required" data-ng-show="create">*</span></label>
-                <div class="col-sm-6">
-                    <input class="form-control" type="text" id="clientId" name="clientId" data-ng-model="client.clientId" autofocus required>
-                </div>
-                <kc-tooltip>Specifies ID referenced in URI and tokens. For example 'my-client'</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="name">Name </label>
-                <div class="col-sm-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="client.name" autofocus>
-                </div>
-                <kc-tooltip>Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="enabled">Enabled</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.enabled" name="enabled" id="enabled" onoffswitch />
-                </div>
-                <kc-tooltip>Disabled clients cannot initiate a login or have obtain access tokens.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="consentRequired">Consent Required</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.consentRequired" name="consentRequired" id="consentRequired" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled users have to consent to client access.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="directGrantsOnly">Direct Grants Only</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.directGrantsOnly" name="directGrantsOnly" id="directGrantsOnly" onoffswitch />
-                </div>
-                <kc-tooltip>When enabled, client can only obtain grants from grant REST API.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="protocol">Client Protocol</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="protocol"
-                                ng-change="changeProtocol()"
-                                ng-model="protocol"
-                                ng-options="aProtocol for aProtocol in protocols">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>'OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.
-                'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="protocol == 'openid-connect'">
-                <label class="col-md-2 control-label" for="accessType">Access Type</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="accessType"
-                                ng-change="changeAccessType()"
-                                ng-model="accessType"
-                                ng-options="aType for aType in accessTypes">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>'Confidential' clients require a secret to initiate login protocol.  'Public' clients do not require a secret.  'Bearer-only' clients are web services that never initiate a login.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlServerSignature">Include AuthnStatement</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlAuthnStatement" ng-click="switchChange()" name="samlAuthnStatement" id="samlAuthnStatement" onoffswitch />
-                </div>
-                <kc-tooltip>Should a statement specifying the method and timestamp be included in login responses?</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlServerSignature">Sign Documents</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlServerSignature" ng-click="switchChange()" name="samlServerSignature" id="samlServerSignature" onoffswitch />
-                </div>
-                <kc-tooltip>Should SAML documents be signed by the realm?</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlAssertionSignature">Sign Assertions</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlAssertionSignature" ng-click="switchChange()" name="samlAssertionSignature" id="samlAssertionSignature" onoffswitch />
-                </div>
-                <kc-tooltip>Should assertions inside SAML documents be signed?  This setting isn't needed if document is already being signed.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="(samlAssertionSignature || samlServerSignature) && protocol == 'saml'">
-                <label class="col-md-2 control-label" for="signatureAlgorithm">Signature Algorithm</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="signatureAlgorithm"
-                                ng-change="changeAlgorithm()"
-                                ng-model="signatureAlgorithm"
-                                ng-options="alg for alg in signatureAlgorithms">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>The signature algorithm to use to sign documents.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlEncrypt">Encrypt Assertions</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlEncrypt" ng-click="switchChange()" name="samlEncrypt" id="samlEncrypt" onoffswitch />
-                </div>
-                <kc-tooltip>Should SAML assertions be encrypted with client's public key using AES?</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlClientSignature">Client Signature Required</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlClientSignature" ng-click="switchChange()" name="samlClientSignature" id="samlClientSignature" onoffswitch />
-                </div>
-                <kc-tooltip>Will the client sign their saml requests and responses?  And should they be validated?</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlForcePostBinding">Force POST Binding</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlForcePostBinding" ng-click="switchChange()" name="samlForcePostBinding" id="samlForcePostBinding" onoffswitch />
-                </div>
-                <kc-tooltip>Always use POST binding for responses.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="frontchannelLogout">Front Channel Logout</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.frontchannelLogout" name="frontchannelLogout" id="frontchannelLogout" onoffswitch />
-                </div>
-                <kc-tooltip>When true, logout requires a browser redirect to client.  When false, server performs a background invocation for logout.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlForceNameIdFormat">Force Name ID Format</label>
-                <div class="col-sm-6">
-                    <input ng-model="samlForceNameIdFormat" ng-click="switchChange()" name="samlForceNameIdFormat" id="samlForceNameIdFormat" onoffswitch />
-                </div>
-                <kc-tooltip>Ignore requested NameID subject format and use admin console configured one.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="samlNameIdFormat">Name ID Format</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="samlNameIdFormat"
-                                ng-change="changeNameIdFormat()"
-                                ng-model="nameIdFormat"
-                                ng-options="format for format in nameIdFormats">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>The name ID format to use for the subject.</kc-tooltip>
-            </div>
-
-            <div class="form-group clearfix block" data-ng-hide="client.bearerOnly || client.directGrantsOnly">
-                <label class="col-md-2 control-label" for="newRedirectUri"><span class="required" data-ng-show="protocol != 'saml'">*</span> Valid Redirect URIs</label>
-
-                <div class="col-sm-6">
-                    <div class="input-group" ng-repeat="(i, redirectUri) in client.redirectUris track by $index">
-                        <input class="form-control" ng-model="client.redirectUris[i]">
-                        <div class="input-group-addon">
-                            <i class="pficon pficon-remove" style="width: 10px;" data-ng-click="deleteRedirectUri($index)"></i>
-                        </div>
-                    </div>
-
-                    <div class="input-group">
-                        <input class="form-control" ng-model="newRedirectUri" id="newRedirectUri">
-                        <div class="input-group-addon">
-                            <i class="pficon pficon-add" style="width: 10px;" data-ng-click="newRedirectUri.length > 0 && addRedirectUri()"></i>
-                        </div>
-                    </div>
-                </div>
-
-                <kc-tooltip>Valid URI pattern a browser can redirect to after a successful login or logout.  Simple wildcards are allowed i.e. 'http://example.com/*'.  Relative path can be specified too i.e. /my/relative/path/*.  Relative paths will generate a redirect URI using the request's host and port.  For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request.</kc-tooltip>
-            </div>
-
-            <div class="form-group" data-ng-show="!client.bearerOnly && !create">
-                <label class="col-md-2 control-label" for="baseUrl">Base URL</label>
-                <div class="col-sm-6">
-                    <input class="form-control" type="text" name="baseUrl" id="baseUrl" data-ng-model="client.baseUrl">
-                </div>
-                <kc-tooltip>Default URL to use when the auth server needs to redirect or link back to the client.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-hide="create || protocol == 'saml'">
-                <label class="col-md-2 control-label" for="adminUrl">Admin URL</label>
-                <div class="col-sm-6">
-                    <input class="form-control" type="text" name="adminUrl" id="adminUrl"
-                           data-ng-model="client.adminUrl">
-                </div>
-                <kc-tooltip>URL to the admin interface of the client.  Set this if the client supports the adapter REST API.  This REST API allows the auth server to push revocation policies and other adminstrative tasks.  Usually this is set to the base URL of the client.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="masterSamlUrl">Master SAML Processing URL</label>
-                <div class="col-sm-6">
-                    <input class="form-control" type="text" name="masterSamlUrl" id="masterSamlUrl"
-                           data-ng-model="client.adminUrl">
-                </div>
-                <kc-tooltip>If configured, this URL will be used for every binding to both the SP's Assertion Consumer and Single Logout Services.  This can be individually overiden for each binding and service in the Fine Grain SAML Endpoint Configuration.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="urlReferenceName">IDP Initiated SSO URL Name</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_idp_initiated_sso_url_name" class="form-control" type="text" name="urlReferenceName" id="urlReferenceName" />
-                </div>
-                <kc-tooltip>URL fragment name to reference client when you want to do IDP Initiated SSO.  Leaving this empty will disable IDP Initiated SSO.  The URL you will reference from your browser will be: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="idpInitiatedRelayState">IDP Initiated SSO Relay State</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_idp_initiated_sso_relay_state" class="form-control" type="text" name="idpInitiatedRelayState" id="idpInitiatedRelayState" />
-                </div>
-                <kc-tooltip>Relay state you want to send with SAML request when you want to do IDP Initiated SSO.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="!client.bearerOnly && !create && protocol == 'openid-connect'">
-                <label class="col-md-2 control-label" for="newWebOrigin">Web Origins</label>
-
-                <div class="col-sm-6">
-                    <div class="input-group" ng-repeat="(i, webOrigin) in client.webOrigins track by $index">
-                        <input class="form-control" ng-model="client.webOrigins[i]">
-                        <div class="input-group-addon">
-                            <i class="pficon pficon-remove" style="width: 10px;" data-ng-click="deleteWebOrigin($index)"></i>
-                        </div>
-                    </div>
-
-                    <div class="input-group">
-                        <input class="form-control" ng-model="newWebOrigin" id="newWebOrigin">
-                        <div class="input-group-addon">
-                            <i class="pficon pficon-add" style="width: 10px;" data-ng-click="newWebOrigin.length > 0 && addWebOrigin()"></i>
-                        </div>
-                    </div>
-                </div>
-
-                <kc-tooltip>Allowed CORS origins.</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset data-ng-show="protocol == 'saml'">
-            <legend collapsed><span class="text">Fine Grain SAML Endpoint Configuration</span>  <kc-tooltip>Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.</kc-tooltip></legend>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="consumerServicePost">Assertion Consumer Service POST Binding URL</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_assertion_consumer_url_post" class="form-control" type="text" name="consumerServicePost" id="consumerServicePost" />
-                </div>
-                <kc-tooltip>SAML POST Binding URL for the client's assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="consumerServiceRedirect">Assertion Consumer Service Redirect Binding URL</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_assertion_consumer_url_redirect" class="form-control" type="text" name="consumerServiceRedirect" id="consumerServiceRedirect" />
-                </div>
-                <kc-tooltip>SAML Redirect Binding URL for the client's assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="logoutPostBinding">Logout Service POST Binding URL</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_single_logout_service_url_post" class="form-control" type="text" name="logoutPostBinding" id="logoutPostBinding" />
-                </div>
-                <kc-tooltip>SAML POST Binding URL for the client's single logout service.  You can leave this blank if you are using a different binding</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
-                <label class="col-md-2 control-label" for="logoutPostBinding">Logout Service Redirect Binding URL</label>
-                <div class="col-sm-6">
-                    <input ng-model="client.attributes.saml_single_logout_service_url_redirect" class="form-control" type="text" name="logoutRedirectBinding" id="logoutRedirectBinding" />
-                </div>
-                <kc-tooltip>SAML Redirect Binding URL for the client's single logout service.  You can leave this blank if you are using a different binding.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li data-ng-show="create">Add Client</li>
+        <li data-ng-hide="create">{{client.clientId}}</li>
+    </ol>
+
+    <h1 data-ng-show="create">Add Client</h1>
+    <h1 data-ng-hide="create">{{client.clientId|capitalize}}<i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageClients" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="clientId">Client ID <span class="required" data-ng-show="create">*</span></label>
+                <div class="col-sm-6">
+                    <input class="form-control" type="text" id="clientId" name="clientId" data-ng-model="client.clientId" autofocus required>
+                </div>
+                <kc-tooltip>Specifies ID referenced in URI and tokens. For example 'my-client'</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="name">Name </label>
+                <div class="col-sm-6">
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="client.name" autofocus>
+                </div>
+                <kc-tooltip>Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="enabled">Enabled</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.enabled" name="enabled" id="enabled" onoffswitch />
+                </div>
+                <kc-tooltip>Disabled clients cannot initiate a login or have obtain access tokens.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="consentRequired">Consent Required</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.consentRequired" name="consentRequired" id="consentRequired" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled users have to consent to client access.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="directGrantsOnly">Direct Grants Only</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.directGrantsOnly" name="directGrantsOnly" id="directGrantsOnly" onoffswitch />
+                </div>
+                <kc-tooltip>When enabled, client can only obtain grants from grant REST API.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="protocol">Client Protocol</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="protocol"
+                                ng-change="changeProtocol()"
+                                ng-model="protocol"
+                                ng-options="aProtocol for aProtocol in protocols">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>'OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.
+                'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="protocol == 'openid-connect'">
+                <label class="col-md-2 control-label" for="accessType">Access Type</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="accessType"
+                                ng-change="changeAccessType()"
+                                ng-model="accessType"
+                                ng-options="aType for aType in accessTypes">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>'Confidential' clients require a secret to initiate login protocol.  'Public' clients do not require a secret.  'Bearer-only' clients are web services that never initiate a login.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlServerSignature">Include AuthnStatement</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlAuthnStatement" ng-click="switchChange()" name="samlAuthnStatement" id="samlAuthnStatement" onoffswitch />
+                </div>
+                <kc-tooltip>Should a statement specifying the method and timestamp be included in login responses?</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlServerSignature">Sign Documents</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlServerSignature" ng-click="switchChange()" name="samlServerSignature" id="samlServerSignature" onoffswitch />
+                </div>
+                <kc-tooltip>Should SAML documents be signed by the realm?</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlAssertionSignature">Sign Assertions</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlAssertionSignature" ng-click="switchChange()" name="samlAssertionSignature" id="samlAssertionSignature" onoffswitch />
+                </div>
+                <kc-tooltip>Should assertions inside SAML documents be signed?  This setting isn't needed if document is already being signed.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="(samlAssertionSignature || samlServerSignature) && protocol == 'saml'">
+                <label class="col-md-2 control-label" for="signatureAlgorithm">Signature Algorithm</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="signatureAlgorithm"
+                                ng-change="changeAlgorithm()"
+                                ng-model="signatureAlgorithm"
+                                ng-options="alg for alg in signatureAlgorithms">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>The signature algorithm to use to sign documents.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlEncrypt">Encrypt Assertions</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlEncrypt" ng-click="switchChange()" name="samlEncrypt" id="samlEncrypt" onoffswitch />
+                </div>
+                <kc-tooltip>Should SAML assertions be encrypted with client's public key using AES?</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlClientSignature">Client Signature Required</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlClientSignature" ng-click="switchChange()" name="samlClientSignature" id="samlClientSignature" onoffswitch />
+                </div>
+                <kc-tooltip>Will the client sign their saml requests and responses?  And should they be validated?</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlForcePostBinding">Force POST Binding</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlForcePostBinding" ng-click="switchChange()" name="samlForcePostBinding" id="samlForcePostBinding" onoffswitch />
+                </div>
+                <kc-tooltip>Always use POST binding for responses.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="frontchannelLogout">Front Channel Logout</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.frontchannelLogout" name="frontchannelLogout" id="frontchannelLogout" onoffswitch />
+                </div>
+                <kc-tooltip>When true, logout requires a browser redirect to client.  When false, server performs a background invocation for logout.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlForceNameIdFormat">Force Name ID Format</label>
+                <div class="col-sm-6">
+                    <input ng-model="samlForceNameIdFormat" ng-click="switchChange()" name="samlForceNameIdFormat" id="samlForceNameIdFormat" onoffswitch />
+                </div>
+                <kc-tooltip>Ignore requested NameID subject format and use admin console configured one.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="samlNameIdFormat">Name ID Format</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="samlNameIdFormat"
+                                ng-change="changeNameIdFormat()"
+                                ng-model="nameIdFormat"
+                                ng-options="format for format in nameIdFormats">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>The name ID format to use for the subject.</kc-tooltip>
+            </div>
+
+            <div class="form-group clearfix block" data-ng-hide="client.bearerOnly || client.directGrantsOnly">
+                <label class="col-md-2 control-label" for="newRedirectUri"><span class="required" data-ng-show="protocol != 'saml'">*</span> Valid Redirect URIs</label>
+
+                <div class="col-sm-6">
+                    <div class="input-group" ng-repeat="(i, redirectUri) in client.redirectUris track by $index">
+                        <input class="form-control" ng-model="client.redirectUris[i]">
+                        <div class="input-group-addon">
+                            <i class="pficon pficon-remove" style="width: 10px;" data-ng-click="deleteRedirectUri($index)"></i>
+                        </div>
+                    </div>
+
+                    <div class="input-group">
+                        <input class="form-control" ng-model="newRedirectUri" id="newRedirectUri">
+                        <div class="input-group-addon">
+                            <i class="pficon pficon-add" style="width: 10px;" data-ng-click="newRedirectUri.length > 0 && addRedirectUri()"></i>
+                        </div>
+                    </div>
+                </div>
+
+                <kc-tooltip>Valid URI pattern a browser can redirect to after a successful login or logout.  Simple wildcards are allowed i.e. 'http://example.com/*'.  Relative path can be specified too i.e. /my/relative/path/*.  Relative paths will generate a redirect URI using the request's host and port.  For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request.</kc-tooltip>
+            </div>
+
+            <div class="form-group" data-ng-show="!client.bearerOnly && !create">
+                <label class="col-md-2 control-label" for="baseUrl">Base URL</label>
+                <div class="col-sm-6">
+                    <input class="form-control" type="text" name="baseUrl" id="baseUrl" data-ng-model="client.baseUrl">
+                </div>
+                <kc-tooltip>Default URL to use when the auth server needs to redirect or link back to the client.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-hide="create || protocol == 'saml'">
+                <label class="col-md-2 control-label" for="adminUrl">Admin URL</label>
+                <div class="col-sm-6">
+                    <input class="form-control" type="text" name="adminUrl" id="adminUrl"
+                           data-ng-model="client.adminUrl">
+                </div>
+                <kc-tooltip>URL to the admin interface of the client.  Set this if the client supports the adapter REST API.  This REST API allows the auth server to push revocation policies and other adminstrative tasks.  Usually this is set to the base URL of the client.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="masterSamlUrl">Master SAML Processing URL</label>
+                <div class="col-sm-6">
+                    <input class="form-control" type="text" name="masterSamlUrl" id="masterSamlUrl"
+                           data-ng-model="client.adminUrl">
+                </div>
+                <kc-tooltip>If configured, this URL will be used for every binding to both the SP's Assertion Consumer and Single Logout Services.  This can be individually overiden for each binding and service in the Fine Grain SAML Endpoint Configuration.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="urlReferenceName">IDP Initiated SSO URL Name</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_idp_initiated_sso_url_name" class="form-control" type="text" name="urlReferenceName" id="urlReferenceName" />
+                </div>
+                <kc-tooltip>URL fragment name to reference client when you want to do IDP Initiated SSO.  Leaving this empty will disable IDP Initiated SSO.  The URL you will reference from your browser will be: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="idpInitiatedRelayState">IDP Initiated SSO Relay State</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_idp_initiated_sso_relay_state" class="form-control" type="text" name="idpInitiatedRelayState" id="idpInitiatedRelayState" />
+                </div>
+                <kc-tooltip>Relay state you want to send with SAML request when you want to do IDP Initiated SSO.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="!client.bearerOnly && !create && protocol == 'openid-connect'">
+                <label class="col-md-2 control-label" for="newWebOrigin">Web Origins</label>
+
+                <div class="col-sm-6">
+                    <div class="input-group" ng-repeat="(i, webOrigin) in client.webOrigins track by $index">
+                        <input class="form-control" ng-model="client.webOrigins[i]">
+                        <div class="input-group-addon">
+                            <i class="pficon pficon-remove" style="width: 10px;" data-ng-click="deleteWebOrigin($index)"></i>
+                        </div>
+                    </div>
+
+                    <div class="input-group">
+                        <input class="form-control" ng-model="newWebOrigin" id="newWebOrigin">
+                        <div class="input-group-addon">
+                            <i class="pficon pficon-add" style="width: 10px;" data-ng-click="newWebOrigin.length > 0 && addWebOrigin()"></i>
+                        </div>
+                    </div>
+                </div>
+
+                <kc-tooltip>Allowed CORS origins.</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset data-ng-show="protocol == 'saml'">
+            <legend collapsed><span class="text">Fine Grain SAML Endpoint Configuration</span>  <kc-tooltip>Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.</kc-tooltip></legend>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="consumerServicePost">Assertion Consumer Service POST Binding URL</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_assertion_consumer_url_post" class="form-control" type="text" name="consumerServicePost" id="consumerServicePost" />
+                </div>
+                <kc-tooltip>SAML POST Binding URL for the client's assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="consumerServiceRedirect">Assertion Consumer Service Redirect Binding URL</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_assertion_consumer_url_redirect" class="form-control" type="text" name="consumerServiceRedirect" id="consumerServiceRedirect" />
+                </div>
+                <kc-tooltip>SAML Redirect Binding URL for the client's assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="logoutPostBinding">Logout Service POST Binding URL</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_single_logout_service_url_post" class="form-control" type="text" name="logoutPostBinding" id="logoutPostBinding" />
+                </div>
+                <kc-tooltip>SAML POST Binding URL for the client's single logout service.  You can leave this blank if you are using a different binding</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
+                <label class="col-md-2 control-label" for="logoutPostBinding">Logout Service Redirect Binding URL</label>
+                <div class="col-sm-6">
+                    <input ng-model="client.attributes.saml_single_logout_service_url_redirect" class="form-control" type="text" name="logoutRedirectBinding" id="logoutRedirectBinding" />
+                </div>
+                <kc-tooltip>SAML Redirect Binding URL for the client's single logout service.  You can leave this blank if you are using a different binding.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html
index 50cfc0e..910f1ce 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-import.html
@@ -1,46 +1,46 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>Import Client</li>
-    </ol>
-
-    <h1>Import Client</h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset class="border-top">
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="configFormats">Format Option</label>
-                <div class="col-md-6">
-                    <div class="input-group">
-                        <div>
-                            <select class="form-control" id="configFormats" name="configFormats" ng-model="configFormat" ng-options="format.name for format in configFormats">
-                                <option value="" selected> Select a Format </option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label">Import File </label>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
-                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
-                    </div>
-                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
-                        {{files[0].name}}
-                    </span>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
-                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
-                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>Import Client</li>
+    </ol>
+
+    <h1>Import Client</h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset class="border-top">
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="configFormats">Format Option</label>
+                <div class="col-md-6">
+                    <div class="input-group">
+                        <div>
+                            <select class="form-control" id="configFormats" name="configFormats" ng-model="configFormat" ng-options="format.name for format in configFormats">
+                                <option value="" selected> Select a Format </option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label">Import File </label>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
+                    </div>
+                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
+                        {{files[0].name}}
+                    </span>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
+                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
+                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html
index 55581c3..e6886f0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-installation.html
@@ -1,38 +1,38 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form" name="realmForm" novalidate>
-        <fieldset>
-            <div class="form-group input-select">
-                <label class="col-md-1 control-label" for="configFormats">Format Option</label>
-                <div class="col-md-6">
-                    <div class="input-group">
-                        <div>
-                            <select class="form-control" id="configFormats" name="configFormats" ng-change="changeFormat()" ng-model="configFormat" ng-options="a for a in configFormats">
-                                <option value="" selected> Select a Format </option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </fieldset>
-        <fieldset class="margin-top">
-            <div class="form-group" ng-show="installation">
-                <div class="col-sm-12">
-                    <a class="btn btn-primary btn-lg" data-ng-click="download()" type="submit" ng-show="installation">Download</a>
-                    <textarea class="form-control" rows="20" kc-select-action="click">{{installation}}</textarea>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form" name="realmForm" novalidate>
+        <fieldset>
+            <div class="form-group input-select">
+                <label class="col-md-1 control-label" for="configFormats">Format Option</label>
+                <div class="col-md-6">
+                    <div class="input-group">
+                        <div>
+                            <select class="form-control" id="configFormats" name="configFormats" ng-change="changeFormat()" ng-model="configFormat" ng-options="a for a in configFormats">
+                                <option value="" selected> Select a Format </option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+        <fieldset class="margin-top">
+            <div class="form-group" ng-show="installation">
+                <div class="col-sm-12">
+                    <a class="btn btn-primary btn-lg" data-ng-click="download()" type="submit" ng-show="installation">Download</a>
+                    <textarea class="form-control" rows="20" kc-select-action="click">{{installation}}</textarea>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
index 549b056..f1a0803 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
@@ -1,148 +1,148 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset>
-            <legend collapsed><span class="text">Import Keys and Cert</span> <kc-tooltip>Upload the client's key pair and cert.</kc-tooltip></legend>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="uploadKeyFormat"
-                                ng-model="uploadKeyFormat"
-                                ng-options="f for f in keyFormats">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
-                </div>
-                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="uploadKeyPassword" name="uploadKeyPassword" data-ng-model="uploadKeyPassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the archive itself</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label">Upload Keys </label>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <a href="#" class="btn btn-default"><span class="kc-icon-upload">Icon: Upload</span>Choose a File...</a>
-                        <input id="import-file" type="file" class="transparent" ng-file-select="onFileSelect($files)">
-                    </div>
-                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
-                        {{files[0].name}}
-                    </span>
-                </div>
-            </div>
-            <div class="pull-right form-actions" data-ng-show="files.length > 0">
-                <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-lg btn-default">Cancel</button>
-                <button type="submit" data-ng-click="uploadFile()" class="btn btn-lg btn-primary">Upload</button>
-            </div>
-        </fieldset>
-        <fieldset class="form-group col-sm-10" data-ng-hide="!keyInfo.privateKey">
-            <legend collapsed><span class="text">Download Keys and Cert</span>  <kc-tooltip>Client key pair, cert, and realm certificate will be stuffed into a PKCS12 or Java keystore that you can use in your clients.</kc-tooltip></legend>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="downloadKeyFormat"
-                                ng-model="jks.format"
-                                ng-options="f for f in keyFormats">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
-                </div>
-                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="realmAlias">Realm Certificate Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="realmAlias" name="realmAlias" data-ng-model="jks.realmAlias" autofocus required>
-                </div>
-                <kc-tooltip>Realm certificate is stored in archive too.  This is the alias to it.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storePassword">Store Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the archive itself</kc-tooltip>
-           </div>
-            <div class="form-group" data-ng-show="access.manageRealm">
-                <div class="pull-right">
-                    <button class="btn btn-primary" type="submit" data-ng-click="downloadJKS()">Download</button>
-                </div>
-            </div>
-        </fieldset>
-        <fieldset class="form-group col-sm-10">
-            <legend><span class="text">Keys and Certificate</span>  <kc-tooltip>Keys and cert in PEM format.</kc-tooltip></legend>
-            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
-                <label class="col-md-2 control-label" for="publicKey">Private key</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="Private" name="publicKey" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{keyInfo.privateKey}}</textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
-                <label class="col-md-2 control-label" for="publicKey">Public key</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="publicKey" name="publicKey" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{keyInfo.publicKey}}</textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
-                <label class="col-md-2 control-label" for="publicKey">Certificate</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="certificate" name="certificate" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{keyInfo.certificate}}</textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="access.manageRealm">
-                <div class="pull-right">
-                    <button class="btn btn-primary" type="submit" data-ng-click="generate()">Generate new keys</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset>
+            <legend collapsed><span class="text">Import Keys and Cert</span> <kc-tooltip>Upload the client's key pair and cert.</kc-tooltip></legend>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="uploadKeyFormat"
+                                ng-model="uploadKeyFormat"
+                                ng-options="f for f in keyFormats">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
+                </div>
+                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="uploadKeyPassword" name="uploadKeyPassword" data-ng-model="uploadKeyPassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the archive itself</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label">Upload Keys </label>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <a href="#" class="btn btn-default"><span class="kc-icon-upload">Icon: Upload</span>Choose a File...</a>
+                        <input id="import-file" type="file" class="transparent" ng-file-select="onFileSelect($files)">
+                    </div>
+                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
+                        {{files[0].name}}
+                    </span>
+                </div>
+            </div>
+            <div class="pull-right form-actions" data-ng-show="files.length > 0">
+                <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-lg btn-default">Cancel</button>
+                <button type="submit" data-ng-click="uploadFile()" class="btn btn-lg btn-primary">Upload</button>
+            </div>
+        </fieldset>
+        <fieldset class="form-group col-sm-10" data-ng-hide="!keyInfo.privateKey">
+            <legend collapsed><span class="text">Download Keys and Cert</span>  <kc-tooltip>Client key pair, cert, and realm certificate will be stuffed into a PKCS12 or Java keystore that you can use in your clients.</kc-tooltip></legend>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="downloadKeyFormat"
+                                ng-model="jks.format"
+                                ng-options="f for f in keyFormats">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
+                </div>
+                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="realmAlias">Realm Certificate Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="realmAlias" name="realmAlias" data-ng-model="jks.realmAlias" autofocus required>
+                </div>
+                <kc-tooltip>Realm certificate is stored in archive too.  This is the alias to it.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storePassword">Store Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the archive itself</kc-tooltip>
+           </div>
+            <div class="form-group" data-ng-show="access.manageRealm">
+                <div class="pull-right">
+                    <button class="btn btn-primary" type="submit" data-ng-click="downloadJKS()">Download</button>
+                </div>
+            </div>
+        </fieldset>
+        <fieldset class="form-group col-sm-10">
+            <legend><span class="text">Keys and Certificate</span>  <kc-tooltip>Keys and cert in PEM format.</kc-tooltip></legend>
+            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
+                <label class="col-md-2 control-label" for="publicKey">Private key</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="Private" name="publicKey" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{keyInfo.privateKey}}</textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
+                <label class="col-md-2 control-label" for="publicKey">Public key</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="publicKey" name="publicKey" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{keyInfo.publicKey}}</textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
+                <label class="col-md-2 control-label" for="publicKey">Certificate</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="certificate" name="certificate" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{keyInfo.certificate}}</textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="access.manageRealm">
+                <div class="pull-right">
+                    <button class="btn btn-primary" type="submit" data-ng-click="generate()">Generate new keys</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index ff38099..4dc4a24 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -1,50 +1,50 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>
-        <span>Clients</span>
-        <kc-tooltip>Clients are trusted browser apps and web services in a realm.  These clients can request a login. You can also define client specific roles.</kc-tooltip>
-    </h1>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="3">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." 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 class="pull-right" data-ng-show="access.manageClients">
-                        <a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">Create</a>
-                        <a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">Import</a>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="clients.length == 0">
-            <th>Client ID</th>
-            <th>Enabled</th>
-            <th>Base URL</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="client in clients | filter:search">
-            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
-            <td>{{client.enabled}}</td>
-            <td ng-class="{'text-muted': !client.baseUrl}">
-                <a href="{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.baseUrl}}</a>
-                <span data-ng-hide="client.baseUrl">Not defined</span>
-        </tr>
-        <tr data-ng-show="(clients | filter:search).length == 0">
-            <td class="text-muted" colspan="3" data-ng-show="search.clientId">No results</td>
-            <td class="text-muted" colspan="3" data-ng-hide="search.clientId">No clients available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>
+        <span>Clients</span>
+        <kc-tooltip>Clients are trusted browser apps and web services in a realm.  These clients can request a login. You can also define client specific roles.</kc-tooltip>
+    </h1>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="3">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." 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 class="pull-right" data-ng-show="access.manageClients">
+                        <a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">Create</a>
+                        <a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">Import</a>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="clients.length == 0">
+            <th>Client ID</th>
+            <th>Enabled</th>
+            <th>Base URL</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="client in clients | filter:search">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
+            <td>{{client.enabled}}</td>
+            <td ng-class="{'text-muted': !client.baseUrl}">
+                <a href="{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.baseUrl}}</a>
+                <span data-ng-hide="client.baseUrl">Not defined</span>
+        </tr>
+        <tr data-ng-show="(clients | filter:search).length == 0">
+            <td class="text-muted" colspan="3" data-ng-show="search.clientId">No results</td>
+            <td class="text-muted" colspan="3" data-ng-hide="search.clientId">No clients available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
index e270959..b62902d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
@@ -1,52 +1,52 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="4">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right" data-ng-show="access.manageClients">
-                        <a class="btn btn-default" href="#/create/client/{{realm.realm}}/{{client.id}}/mappers">Create</a>
-                        <a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">Add Builtin</a>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="mappers.length == 0">
-            <th>Name</th>
-            <th>Category</th>
-            <th>Type</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="mapper in mappers | filter:search">
-            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
-            <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
-            <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
-        </tr>
-        <tr data-ng-show="mappers.length == 0">
-            <td>No mappers available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="4">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right" data-ng-show="access.manageClients">
+                        <a class="btn btn-default" href="#/create/client/{{realm.realm}}/{{client.id}}/mappers">Create</a>
+                        <a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">Add Builtin</a>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="mappers.length == 0">
+            <th>Name</th>
+            <th>Category</th>
+            <th>Type</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="mapper in mappers | filter:search">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
+            <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
+            <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
+        </tr>
+        <tr data-ng-show="mappers.length == 0">
+            <td>No mappers available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
index c3fda83..94c0236 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
@@ -1,53 +1,53 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
-        <li class="active">Add Builtin Protocol Mappers</li>
-    </ol>
-
-    <h1>Add Builtin Protocol Mapper</h1>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="4">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right" data-ng-show="access.manageRealm">
-                        <button class="btn btn-primary" data-ng-click="add()">Add Selected</button>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="mappers.length == 0">
-            <th>Name</th>
-            <th>Category</th>
-            <th>Type</th>
-            <th>Add</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="mapper in mappers | filter:search">
-            <td>{{mapper.name}}</td>
-            <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
-            <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
-            <td><input type="checkbox" ng-model="mapper.isChecked"></td>
-        </tr>
-        <tr data-ng-show="mappers.length == 0">
-            <td>No mappers available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
+        <li class="active">Add Builtin Protocol Mappers</li>
+    </ol>
+
+    <h1>Add Builtin Protocol Mapper</h1>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="4">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right" data-ng-show="access.manageRealm">
+                        <button class="btn btn-primary" data-ng-click="add()">Add Selected</button>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="mappers.length == 0">
+            <th>Name</th>
+            <th>Category</th>
+            <th>Type</th>
+            <th>Add</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="mapper in mappers | filter:search">
+            <td>{{mapper.name}}</td>
+            <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
+            <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
+            <td><input type="checkbox" ng-model="mapper.isChecked"></td>
+        </tr>
+        <tr data-ng-show="mappers.length == 0">
+            <td>No mappers available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
index 522f554..962b802 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
@@ -1,32 +1,32 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="notBefore">Not Before</label>
-                <div class="col-md-6">
-                    <input ng-disabled="true" class="form-control" type="text" id="notBefore" name="notBefore" data-ng-model="notBefore" autofocus>
-                </div>
-                <kc-tooltip>Revoke any tokens issued before this date for this client.</kc-tooltip>
-            </div>
-        </fieldset>
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
-                <button type="submit" data-ng-click="clear()" class="btn btn-default">Clear</button>
-                <button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">Set To Now</button>
-                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip="If admin URL is configured for this client, push this policy to that client." tooltip-placement="bottom">Push</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="notBefore">Not Before</label>
+                <div class="col-md-6">
+                    <input ng-disabled="true" class="form-control" type="text" id="notBefore" name="notBefore" data-ng-model="notBefore" autofocus>
+                </div>
+                <kc-tooltip>Revoke any tokens issued before this date for this client.</kc-tooltip>
+            </div>
+        </fieldset>
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+                <button type="submit" data-ng-click="clear()" class="btn btn-default">Clear</button>
+                <button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">Set To Now</button>
+                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip="If admin URL is configured for this client, push this policy to that client." tooltip-placement="bottom">Push</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
index a64e037..1c11d57 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
@@ -1,135 +1,135 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">Roles</a></li>
-        <li data-ng-show="create">Add role</li>
-        <li data-ng-hide="create">{{role.name}}</li>
-    </ol>
-
-    <h1 data-ng-show="create">Add Role</h1>
-    <h1 data-ng-hide="create">{{role.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageClients" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
-
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="role.name" autofocus
-                           required data-ng-readonly="!create">
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="description">Description </label>
-
-                <div class="col-md-6">
-                    <textarea  class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
-                    <!-- Replaced by the textarea above <input type="text" id="description" name="description" data-ng-model="role.description" autofocus
-                                                           required> -->
-                </div>
-            </div>
-            <div class="form-group clearfix block" data-ng-hide="create">
-                <label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
-                <div class="col-md-6">
-                    <input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch />
-                </div>
-                <kc-tooltip>When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-        </div>
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-
-        <fieldset data-ng-show="!create && (compositeSwitch || role.composite)">
-            <legend uncollapsed><span class="text">Composite Roles</span> </legend>
-
-            <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
-
-                <div class="col-md-10">
-                    <div class="row">
-                        <div class="col-md-4">
-                            <label class="control-label" for="available">Available Roles</label>
-                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
-                            <select id="available" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmRoles"
-                                    ng-options="r.name for r in realmRoles">
-                            </select>
-                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-4">
-                            <label class="control-label" for="assigned">Associated Roles</label>
-                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
-                            <select id="assigned" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmMappings"
-                                    ng-options="r.name for r in realmMappings">
-                            </select>
-                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <div class="form-group" ng-show="clients.length > 0 && !create && (compositeSwitch || role.composite)">
-                <label class="col-md-2 control-label" class="control-label">
-                    <span>Client Roles</span>
-                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
-                </label>
-
-                <div class="col-md-10">
-                    <div class="row" data-ng-hide="compositeClient">
-                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
-                    </div>
-                    <div class="row" data-ng-show="compositeClient">
-                        <div class="col-md-4">
-                            <label class="control-label" for="available-client">Available Roles</label>
-                            <kc-tooltip>Roles from this client that you can associate to this composite role.</kc-tooltip>
-                            <select id="available-client" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedClientRoles"
-                                    ng-options="r.name for r in clientRoles">
-                            </select>
-                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-4">
-                            <label class="control-label" for="assigned-client">Associated Roles</label>
-                            <kc-tooltip>Client roles associated with this composite role.</kc-tooltip>
-                            <select id="assigned-client" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedClientMappings"
-                                    ng-options="r.name for r in clientMappings">
-                            </select>
-                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">Roles</a></li>
+        <li data-ng-show="create">Add role</li>
+        <li data-ng-hide="create">{{role.name}}</li>
+    </ol>
+
+    <h1 data-ng-show="create">Add Role</h1>
+    <h1 data-ng-hide="create">{{role.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageClients" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
+
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="role.name" autofocus
+                           required data-ng-readonly="!create">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="description">Description </label>
+
+                <div class="col-md-6">
+                    <textarea  class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
+                    <!-- Replaced by the textarea above <input type="text" id="description" name="description" data-ng-model="role.description" autofocus
+                                                           required> -->
+                </div>
+            </div>
+            <div class="form-group clearfix block" data-ng-hide="create">
+                <label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
+                <div class="col-md-6">
+                    <input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch />
+                </div>
+                <kc-tooltip>When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+        </div>
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+
+        <fieldset data-ng-show="!create && (compositeSwitch || role.composite)">
+            <legend uncollapsed><span class="text">Composite Roles</span> </legend>
+
+            <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
+
+                <div class="col-md-10">
+                    <div class="row">
+                        <div class="col-md-4">
+                            <label class="control-label" for="available">Available Roles</label>
+                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
+                            <select id="available" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmRoles"
+                                    ng-options="r.name for r in realmRoles">
+                            </select>
+                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-4">
+                            <label class="control-label" for="assigned">Associated Roles</label>
+                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
+                            <select id="assigned" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmMappings"
+                                    ng-options="r.name for r in realmMappings">
+                            </select>
+                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="form-group" ng-show="clients.length > 0 && !create && (compositeSwitch || role.composite)">
+                <label class="col-md-2 control-label" class="control-label">
+                    <span>Client Roles</span>
+                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
+                </label>
+
+                <div class="col-md-10">
+                    <div class="row" data-ng-hide="compositeClient">
+                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
+                    </div>
+                    <div class="row" data-ng-show="compositeClient">
+                        <div class="col-md-4">
+                            <label class="control-label" for="available-client">Available Roles</label>
+                            <kc-tooltip>Roles from this client that you can associate to this composite role.</kc-tooltip>
+                            <select id="available-client" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles">
+                            </select>
+                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-4">
+                            <label class="control-label" for="assigned-client">Associated Roles</label>
+                            <kc-tooltip>Client roles associated with this composite role.</kc-tooltip>
+                            <select id="assigned-client" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings">
+                            </select>
+                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
index 8a236f7..e6e7f2c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
@@ -1,40 +1,40 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="3" data-ng-show="access.manageClients">
-                <div class="pull-right">
-                    <a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">Add Role</a>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="!roles || roles.length == 0">
-            <th>Role Name</th>
-            <th>Composite</th>
-            <th>Description</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="role in roles">
-            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{role.name}}</a></td>
-            <td>{{role.composite}}</td>
-            <td>{{role.description}}</td>
-        </tr>
-        <tr data-ng-show="!roles || roles.length == 0">
-            <td>No client roles available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="3" data-ng-show="access.manageClients">
+                <div class="pull-right">
+                    <a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">Add Role</a>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="!roles || roles.length == 0">
+            <th>Role Name</th>
+            <th>Composite</th>
+            <th>Description</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="role in roles">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{role.name}}</a></td>
+            <td>{{role.composite}}</td>
+            <td>{{role.description}}</td>
+        </tr>
+        <tr data-ng-show="!roles || roles.length == 0">
+            <td>No client roles available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
index 70a4c7d..92e24fd 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
@@ -1,63 +1,63 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
-        <li class="active">SAML {{keyType}} Key Export</li>
-    </ol>
-
-    <h1>Export SAML Key {{client.clientId|capitalize}}</h1>
-
-    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="form-group col-sm-10">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="downloadKeyFormat"
-                                ng-model="jks.format"
-                                ng-options="f for f in keyFormats">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
-                </div>
-                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
-                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="realmAlias">Realm Certificate Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="realmAlias" name="realmAlias" data-ng-model="jks.realmAlias" autofocus required>
-                </div>
-                <kc-tooltip>Realm certificate is stored in archive too.  This is the alias to it.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storePassword">Store Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the archive itself</kc-tooltip>
-           </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                    <button class="btn btn-primary" type="submit" data-ng-click="download()">Download</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
+        <li class="active">SAML {{keyType}} Key Export</li>
+    </ol>
+
+    <h1>Export SAML Key {{client.clientId|capitalize}}</h1>
+
+    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="form-group col-sm-10">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="downloadKeyFormat"
+                                ng-model="jks.format"
+                                ng-options="f for f in keyFormats">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
+                </div>
+                <kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-hide="!keyInfo.privateKey">
+                <label class="col-md-2 control-label" for="keyPassword">Key Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the private key in the archive</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="realmAlias">Realm Certificate Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="realmAlias" name="realmAlias" data-ng-model="jks.realmAlias" autofocus required>
+                </div>
+                <kc-tooltip>Realm certificate is stored in archive too.  This is the alias to it.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storePassword">Store Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the archive itself</kc-tooltip>
+           </div>
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+                    <button class="btn btn-primary" type="submit" data-ng-click="download()">Download</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
index 8ea421b..124448a 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
@@ -1,62 +1,62 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
-        <li class="active">SAML {{keyType}} Key Import</li>
-    </ol>
-
-    <h1>Import SAML Key {{client.clientId|capitalize}}</h1>
-
-    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="uploadKeyFormat"
-                                ng-model="uploadKeyFormat"
-                                ng-options="f for f in keyFormats">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
-                </div>
-                <kc-tooltip>Archive alias for your certificate.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
-                </div>
-                <kc-tooltip>Password to access the archive itself</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label">Import File </label>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
-                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
-                    </div>
-                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
-                        {{files[0].name}}
-                    </span>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
-                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
-                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
+        <li class="active">SAML {{keyType}} Key Import</li>
+    </ol>
+
+    <h1>Import SAML Key {{client.clientId|capitalize}}</h1>
+
+    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="uploadKeyFormat"
+                                ng-model="uploadKeyFormat"
+                                ng-options="f for f in keyFormats">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
+                </div>
+                <kc-tooltip>Archive alias for your certificate.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
+                </div>
+                <kc-tooltip>Password to access the archive itself</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label">Import File </label>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
+                    </div>
+                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">
+                        {{files[0].name}}
+                    </span>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
+                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
+                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
index 74eb840..eff7050 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
@@ -1,68 +1,68 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="form-group col-sm-10" data-ng-show="client.attributes['saml.client.signature'] == 'true'">
-            <legend uncollapsed><span class="text">Signing Key</span>  <kc-tooltip>SAML Signing Key.</kc-tooltip></legend>
-            <div class="form-group" data-ng-hide="!signingKeyInfo.privateKey">
-                <label class="col-md-2 control-label" for="signingPrivateKey">Private key</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="signingPrivateKey" name="signingPrivateKey" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{signingKeyInfo.privateKey}}</textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-hide="!signingKeyInfo.certificate">
-                <label class="col-md-2 control-label" for="signingCert">Certificate</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="signingCert" name="signingCert" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{signingKeyInfo.certificate}}</textarea>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                    <button class="btn btn-primary" type="submit" data-ng-click="generateSigningKey()">Generate new keys</button>
-                    <button class="btn btn-primary" type="submit" data-ng-click="importSigningKey()">Import</button>
-                    <button class="btn btn-primary" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">Export</button>
-                </div>
-            </div>
-        </fieldset>
-        <fieldset class="form-group col-sm-10" data-ng-show="client.attributes['saml.encrypt'] == 'true'">
-            <legend uncollapsed><span class="text">Encryption Key</span>  <kc-tooltip>SAML Encryption Key.</kc-tooltip></legend>
-            <div class="form-group" data-ng-hide="!encryptionKeyInfo.privateKey">
-                <label class="col-md-2 control-label" for="encryptionPrivateKey">Private key</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="encryptionPrivateKey" name="encryptionPrivateKey" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{encryptionKeyInfo.privateKey}}</textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-hide="!encryptionKeyInfo.certificate">
-                <label class="col-md-2 control-label" for="encryptionCert">Certificate</label>
-
-                <div class="col-sm-10">
-                    <textarea type="text" id="encryptionCert" name="encryptionCert" class="form-control" rows="5"
-                              kc-select-action="click" readonly>{{encryptionKeyInfo.certificate}}</textarea>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                    <button class="btn btn-primary" type="submit" data-ng-click="generateEncryptionKey()">Generate new keys</button>
-                    <button class="btn btn-primary" type="submit" data-ng-click="importEncryptionKey()">Import</button>
-                    <button class="btn btn-primary" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">Export</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="form-group col-sm-10" data-ng-show="client.attributes['saml.client.signature'] == 'true'">
+            <legend uncollapsed><span class="text">Signing Key</span>  <kc-tooltip>SAML Signing Key.</kc-tooltip></legend>
+            <div class="form-group" data-ng-hide="!signingKeyInfo.privateKey">
+                <label class="col-md-2 control-label" for="signingPrivateKey">Private key</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="signingPrivateKey" name="signingPrivateKey" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{signingKeyInfo.privateKey}}</textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-hide="!signingKeyInfo.certificate">
+                <label class="col-md-2 control-label" for="signingCert">Certificate</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="signingCert" name="signingCert" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{signingKeyInfo.certificate}}</textarea>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+                    <button class="btn btn-primary" type="submit" data-ng-click="generateSigningKey()">Generate new keys</button>
+                    <button class="btn btn-primary" type="submit" data-ng-click="importSigningKey()">Import</button>
+                    <button class="btn btn-primary" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">Export</button>
+                </div>
+            </div>
+        </fieldset>
+        <fieldset class="form-group col-sm-10" data-ng-show="client.attributes['saml.encrypt'] == 'true'">
+            <legend uncollapsed><span class="text">Encryption Key</span>  <kc-tooltip>SAML Encryption Key.</kc-tooltip></legend>
+            <div class="form-group" data-ng-hide="!encryptionKeyInfo.privateKey">
+                <label class="col-md-2 control-label" for="encryptionPrivateKey">Private key</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="encryptionPrivateKey" name="encryptionPrivateKey" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{encryptionKeyInfo.privateKey}}</textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-hide="!encryptionKeyInfo.certificate">
+                <label class="col-md-2 control-label" for="encryptionCert">Certificate</label>
+
+                <div class="col-sm-10">
+                    <textarea type="text" id="encryptionCert" name="encryptionCert" class="form-control" rows="5"
+                              kc-select-action="click" readonly>{{encryptionKeyInfo.certificate}}</textarea>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+                    <button class="btn btn-primary" type="submit" data-ng-click="generateEncryptionKey()">Generate new keys</button>
+                    <button class="btn btn-primary" type="submit" data-ng-click="importEncryptionKey()">Import</button>
+                    <button class="btn btn-primary" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">Export</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
index e53c306..b5a2627 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
@@ -1,119 +1,119 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-        <h2><span>{{client.clientId}}</span> Scope Mappings </h2>
-        <p class="subtitle"></p>
-        <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageClients">
-            <fieldset class="border-top">
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="fullScopeAllowed">Full Scope Allowed</label>
-                    <kc-tooltip>Allows you to disable all restrictions.</kc-tooltip>
-                    <div class="col-md-6">
-                        <input ng-model="client.fullScopeAllowed" ng-click="changeFullScopeAllowed()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch />
-                    </div>
-                </div>
-            </fieldset>
-        </form>
-
-        <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-show="!client.fullScopeAllowed">
-            <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
-                <div class="col-md-10">
-                    <div class="row">
-                        <div class="col-md-3">
-                            <label class="control-label" for="available">Available Roles</label>
-                            <kc-tooltip>Realm level roles that can be assigned to scope.</kc-tooltip>
-
-                            <select id="available" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmRoles"
-                                    ng-options="r.name for r in realmRoles">
-                            </select>
-                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="assigned">Assigned Roles</label>
-                            <kc-tooltip>Realm level roles assigned to scope.</kc-tooltip>
-                            <select id="assigned" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmMappings"
-                                    ng-options="r.name for r in realmMappings">
-                            </select>
-                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="realm-composite">Effective Roles  </label>
-                            <kc-tooltip>Assigned realm level roles that may have been inherited from a composite role.</kc-tooltip>
-                            <select id="realm-composite" class="form-control" multiple size=5
-                                    disabled="true"
-                                    ng-model="dummymodel"
-                                    ng-options="r.name for r in realmComposite">
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">
-                    <span>Client Roles</span>
-                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
-                </label>
-
-                <div class="col-md-10">
-                    <div class="row" data-ng-hide="targetClient">
-                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
-                    </div>
-                    <div class="row" data-ng-show="targetClient">
-                        <div class="col-md-3">
-                            <label class="control-label" for="client-available">Available Roles</label>
-                            <kc-tooltip>Client roles available to be assigned.</kc-tooltip>
-                            <select id="client-available" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedClientRoles"
-                                    ng-options="r.name for r in clientRoles">
-                            </select>
-                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="client-assigned">Assigned Roles</label>
-                            <kc-tooltip>Assigned client roles.</kc-tooltip>
-                            <select id="client-assigned" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedClientMappings"
-                                    ng-options="r.name for r in clientMappings">
-                            </select>
-                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="client-composite">Effective Roles</label>
-                            <kc-tooltip>Assigned client roles that may have been inherited from a composite role.</kc-tooltip>
-                            <select id="client-composite" class="form-control" multiple size=5
-                                    disabled="true"
-                                    ng-model="dummymodel"
-                                    ng-options="r.name for r in clientComposite">
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </form>
-    </div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+        <h2><span>{{client.clientId}}</span> Scope Mappings </h2>
+        <p class="subtitle"></p>
+        <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageClients">
+            <fieldset class="border-top">
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="fullScopeAllowed">Full Scope Allowed</label>
+                    <kc-tooltip>Allows you to disable all restrictions.</kc-tooltip>
+                    <div class="col-md-6">
+                        <input ng-model="client.fullScopeAllowed" ng-click="changeFullScopeAllowed()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch />
+                    </div>
+                </div>
+            </fieldset>
+        </form>
+
+        <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-show="!client.fullScopeAllowed">
+            <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
+                <div class="col-md-10">
+                    <div class="row">
+                        <div class="col-md-3">
+                            <label class="control-label" for="available">Available Roles</label>
+                            <kc-tooltip>Realm level roles that can be assigned to scope.</kc-tooltip>
+
+                            <select id="available" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmRoles"
+                                    ng-options="r.name for r in realmRoles">
+                            </select>
+                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="assigned">Assigned Roles</label>
+                            <kc-tooltip>Realm level roles assigned to scope.</kc-tooltip>
+                            <select id="assigned" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmMappings"
+                                    ng-options="r.name for r in realmMappings">
+                            </select>
+                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="realm-composite">Effective Roles  </label>
+                            <kc-tooltip>Assigned realm level roles that may have been inherited from a composite role.</kc-tooltip>
+                            <select id="realm-composite" class="form-control" multiple size=5
+                                    disabled="true"
+                                    ng-model="dummymodel"
+                                    ng-options="r.name for r in realmComposite">
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">
+                    <span>Client Roles</span>
+                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
+                </label>
+
+                <div class="col-md-10">
+                    <div class="row" data-ng-hide="targetClient">
+                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
+                    </div>
+                    <div class="row" data-ng-show="targetClient">
+                        <div class="col-md-3">
+                            <label class="control-label" for="client-available">Available Roles</label>
+                            <kc-tooltip>Client roles available to be assigned.</kc-tooltip>
+                            <select id="client-available" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles">
+                            </select>
+                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="client-assigned">Assigned Roles</label>
+                            <kc-tooltip>Assigned client roles.</kc-tooltip>
+                            <select id="client-assigned" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings">
+                            </select>
+                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="client-composite">Effective Roles</label>
+                            <kc-tooltip>Assigned client roles that may have been inherited from a composite role.</kc-tooltip>
+                            <select id="client-composite" class="form-control" multiple size=5
+                                    disabled="true"
+                                    ng-model="dummymodel"
+                                    ng-options="r.name for r in clientComposite">
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html
index 61af04c..846cd92 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-sessions.html
@@ -1,59 +1,59 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li>{{client.clientId}}</li>
-    </ol>
-
-    <h1>{{client.clientId|capitalize}}</h1>
-
-    <kc-tabs-client></kc-tabs-client>
-
-    <form class="form-horizontal" name="sessionStats">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="activeSessions">Active Sessions</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="activeSessions" name="activeSessions" data-ng-model="count" ng-disabled="true">
-                </div>
-                <kc-tooltip>Total number of active user sessions for this client.</kc-tooltip>
-            </div>
-        </fieldset>
-    </form>
-    <table class="table table-striped table-bordered" data-ng-show="count > 0">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="3">
-                <div class="pull-right">
-                    <a class="btn btn-default" ng-click="loadUsers()" tooltip-placement="left" tooltip="Warning, this is a potentially expensive operation depending on number of active sessions.">Show Sessions</a>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-show="sessions">
-            <th>User</th>
-            <th>From IP</th>
-            <th>Session Start</th>
-        </tr>
-        </thead>
-        <tfoot data-ng-show="sessions && (sessions.length >= 5 || query.first != 0)">
-        <tr>
-            <td colspan="7">
-                <div class="table-nav">
-                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
-                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
-                    <button data-ng-click="nextPage()" class="next" ng-disabled="sessions.length < query.max">Next page</button>
-                </div>
-            </td>
-        </tr>
-        </tfoot>
-        <tbody>
-        <tr data-ng-repeat="session in sessions">
-            <td><a href="#/realms/{{realm.realm}}/users/{{session.userId}}">{{session.username}}</a></td>
-            <td>{{session.ipAddress}}</td>
-            <td>{{session.start | date:'medium'}}</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <h1>{{client.clientId|capitalize}}</h1>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class="form-horizontal" name="sessionStats">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="activeSessions">Active Sessions</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="activeSessions" name="activeSessions" data-ng-model="count" ng-disabled="true">
+                </div>
+                <kc-tooltip>Total number of active user sessions for this client.</kc-tooltip>
+            </div>
+        </fieldset>
+    </form>
+    <table class="table table-striped table-bordered" data-ng-show="count > 0">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="3">
+                <div class="pull-right">
+                    <a class="btn btn-default" ng-click="loadUsers()" tooltip-placement="left" tooltip="Warning, this is a potentially expensive operation depending on number of active sessions.">Show Sessions</a>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-show="sessions">
+            <th>User</th>
+            <th>From IP</th>
+            <th>Session Start</th>
+        </tr>
+        </thead>
+        <tfoot data-ng-show="sessions && (sessions.length >= 5 || query.first != 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="sessions.length < query.max">Next page</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
+        <tbody>
+        <tr data-ng-repeat="session in sessions">
+            <td><a href="#/realms/{{realm.realm}}/users/{{session.userId}}">{{session.username}}</a></td>
+            <td>{{session.ipAddress}}</td>
+            <td>{{session.start | date:'medium'}}</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
index ca8511c..d9f3b2c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
@@ -1,38 +1,38 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <ul class="nav nav-tabs nav-tabs-pf">
-        <li class="active"><a href="#/realms/{{realm.realm}}/defense/headers">Headers</a></li>
-        <li><a href="#/realms/{{realm.realm}}/defense/brute-force">Brute Force Detection</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="xFrameOptions"><a href="http://tools.ietf.org/html/rfc7034">X-Frame-Options</a></label>
-                <div class="col-sm-6">
-                    <input class="form-control" id="xFrameOptions" type="text" ng-model="realm.browserSecurityHeaders.xFrameOptions">
-                </div>
-                <kc-tooltip>Click on label link for more information.  The default value prevents pages from being included via non-origin iframes.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="contentSecurityPolicy"><a href="http://www.w3.org/TR/CSP/">Content-Security-Policy</a></label>
-                <div class="col-sm-6">
-                    <input class="form-control" id="contentSecurityPolicy" type="text" ng-model="realm.browserSecurityHeaders.contentSecurityPolicy">
-                </div>
-                <kc-tooltip>Click on label link for more information.  The default value prevents pages from being included via non-origin iframes.</kc-tooltip>
-            </div>
-        </fieldset>
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <ul class="nav nav-tabs nav-tabs-pf">
+        <li class="active"><a href="#/realms/{{realm.realm}}/defense/headers">Headers</a></li>
+        <li><a href="#/realms/{{realm.realm}}/defense/brute-force">Brute Force Detection</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="xFrameOptions"><a href="http://tools.ietf.org/html/rfc7034">X-Frame-Options</a></label>
+                <div class="col-sm-6">
+                    <input class="form-control" id="xFrameOptions" type="text" ng-model="realm.browserSecurityHeaders.xFrameOptions">
+                </div>
+                <kc-tooltip>Click on label link for more information.  The default value prevents pages from being included via non-origin iframes.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="contentSecurityPolicy"><a href="http://www.w3.org/TR/CSP/">Content-Security-Policy</a></label>
+                <div class="col-sm-6">
+                    <input class="form-control" id="contentSecurityPolicy" type="text" ng-model="realm.browserSecurityHeaders.contentSecurityPolicy">
+                </div>
+                <kc-tooltip>Click on label link for more information.  The default value prevents pages from being included via non-origin iframes.</kc-tooltip>
+            </div>
+        </fieldset>
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html
index cc8b11a..002c965 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html
@@ -1,99 +1,99 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/user-federation">User Federation</a></li>
-        <li data-ng-hide="create">{{instance.displayName|capitalize}}</li>
-        <li data-ng-show="create">Add User Federation Provider</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{instance.providerName|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add {{instance.providerName|capitalize}} User Federation Provide</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="create">
-        <li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset>
-            <legend><span class="text">Required Settings</span></legend>
-            <div class="form-group clearfix" data-ng-show="!create">
-                <label class="col-md-2 control-label" for="providerId">Provider ID </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="providerId" type="text" ng-model="instance.id" readonly>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="consoleDisplayName">Console display name </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="consoleDisplayName" type="text" ng-model="instance.displayName" placeholder="defaults to id">
-                </div>
-                <kc-tooltip>Display name of provider when linked in admin console.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="priority">Priority </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="priority" type="text" ng-model="instance.priority">
-                </div>
-                <kc-tooltip>Priority of provider when doing a user lookup.  Lowest first.</kc-tooltip>
-            </div>
-            <div data-ng-repeat="option in providerFactory.options" class="form-group">
-                <label class="col-md-2 control-label">{{option|capitalize}} </label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" data-ng-model="instance.config[ option ]" >
-                </div>
-            </div>
-        </fieldset>
-
-        <fieldset>
-            <legend><span class="text">Sync settings</span></legend>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="fullSyncEnabled">Periodic full sync</label>
-                <div class="col-md-6">
-                    <input ng-model="fullSyncEnabled" name="fullSyncEnabled" id="fullSyncEnabled" onoffswitch />
-                </div>
-                <kc-tooltip>Does periodic full synchronization of provider users to Keycloak should be enabled or not</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="fullSyncEnabled">
-                <label class="col-md-2 control-label" for="fullSyncPeriod">Full sync period</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="number" ng-model="instance.fullSyncPeriod" id="fullSyncPeriod" />
-                </div>
-                <kc-tooltip>Period for full synchronization in seconds</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="changedSyncEnabled">Periodic changed users sync</label>
-                <div class="col-md-6">
-                    <input ng-model="changedSyncEnabled" name="changedSyncEnabled" id="changedSyncEnabled" onoffswitch />
-                </div>
-                <kc-tooltip>Does periodic synchronization of changed or newly created provider users to Keycloak should be enabled or not</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="changedSyncEnabled">
-                <label class="col-md-2 control-label" for="changedSyncPeriod">Changed users sync period</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="number" ng-model="instance.changedSyncPeriod" id="changedSyncPeriod" />
-                </div>
-                <kc-tooltip>Period for synchronization of changed or newly created provider users in seconds</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
-                <button kc-save>Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-                <button class="btn btn-primary" data-ng-click="triggerChangedUsersSync()" data-ng-hide="changed">Synchronize changed users</button>
-                <button class="btn btn-primary" data-ng-click="triggerFullSync()" data-ng-hide="changed">Synchronize all users</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/user-federation">User Federation</a></li>
+        <li data-ng-hide="create">{{instance.displayName|capitalize}}</li>
+        <li data-ng-show="create">Add User Federation Provider</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{instance.providerName|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add {{instance.providerName|capitalize}} User Federation Provide</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="create">
+        <li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset>
+            <legend><span class="text">Required Settings</span></legend>
+            <div class="form-group clearfix" data-ng-show="!create">
+                <label class="col-md-2 control-label" for="providerId">Provider ID </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="providerId" type="text" ng-model="instance.id" readonly>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="consoleDisplayName">Console display name </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="consoleDisplayName" type="text" ng-model="instance.displayName" placeholder="defaults to id">
+                </div>
+                <kc-tooltip>Display name of provider when linked in admin console.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="priority">Priority </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="priority" type="text" ng-model="instance.priority">
+                </div>
+                <kc-tooltip>Priority of provider when doing a user lookup.  Lowest first.</kc-tooltip>
+            </div>
+            <div data-ng-repeat="option in providerFactory.options" class="form-group">
+                <label class="col-md-2 control-label">{{option|capitalize}} </label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" data-ng-model="instance.config[ option ]" >
+                </div>
+            </div>
+        </fieldset>
+
+        <fieldset>
+            <legend><span class="text">Sync settings</span></legend>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="fullSyncEnabled">Periodic full sync</label>
+                <div class="col-md-6">
+                    <input ng-model="fullSyncEnabled" name="fullSyncEnabled" id="fullSyncEnabled" onoffswitch />
+                </div>
+                <kc-tooltip>Does periodic full synchronization of provider users to Keycloak should be enabled or not</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="fullSyncEnabled">
+                <label class="col-md-2 control-label" for="fullSyncPeriod">Full sync period</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="number" ng-model="instance.fullSyncPeriod" id="fullSyncPeriod" />
+                </div>
+                <kc-tooltip>Period for full synchronization in seconds</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="changedSyncEnabled">Periodic changed users sync</label>
+                <div class="col-md-6">
+                    <input ng-model="changedSyncEnabled" name="changedSyncEnabled" id="changedSyncEnabled" onoffswitch />
+                </div>
+                <kc-tooltip>Does periodic synchronization of changed or newly created provider users to Keycloak should be enabled or not</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="changedSyncEnabled">
+                <label class="col-md-2 control-label" for="changedSyncPeriod">Changed users sync period</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="number" ng-model="instance.changedSyncPeriod" id="changedSyncPeriod" />
+                </div>
+                <kc-tooltip>Period for synchronization of changed or newly created provider users in seconds</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
+                <button kc-save>Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+                <button class="btn btn-primary" data-ng-click="triggerChangedUsersSync()" data-ng-hide="changed">Synchronize changed users</button>
+                <button class="btn btn-primary" data-ng-click="triggerFullSync()" data-ng-hide="changed">Synchronize all users</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
index 8c05a49..f01dd4f 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
@@ -1,293 +1,293 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/user-federation">User Federation</a></li>
-        <li data-ng-hide="create">{{instance.displayName|capitalize}}</li>
-        <li data-ng-show="create">Add User Federation Provider</li>
-    </ol>
-
-    <h1 data-ng-hide="create">LDAP<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add LDAP User Federation Provider</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="create">
-        <li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-
-        <fieldset>
-            <legend><span class="text">Required Settings</span></legend>
-            <div class="form-group clearfix" data-ng-show="!create">
-                <label class="col-md-2 control-label" for="providerId">Provider ID </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="providerId" type="text" ng-model="instance.id" readonly>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="consoleDisplayName">Console display name </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="consoleDisplayName" type="text" ng-model="instance.displayName" placeholder="defaults to id">
-                </div>
-                <kc-tooltip>Display name of provider when linked in admin console.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="priority">Priority </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="priority" type="text" ng-model="instance.priority">
-                </div>
-                <kc-tooltip>Priority of provider when doing a user lookup.  Lowest first.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="editMode">Edit mode</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="editMode"
-                                ng-model="instance.config.editMode">
-                            <option>READ_ONLY</option>
-                            <option>WRITABLE</option>
-                            <option>UNSYNCED</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>READ_ONLY is a read only LDAP store.  WRITABLE means data will be synced back to LDAP on demand.  UNSYNCED means user data will be imported, but not synced back to LDAP.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="syncRegistrations">Sync Registrations</label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.syncRegistrations" name="syncRegistrations" id="syncRegistrations" onoffswitch />
-                </div>
-                <kc-tooltip>Should newly created users be created within LDAP store?  Priority effects which provider is chose to sync the new user.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="vendor"><span class="required">*</span> Vendor</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="vendor"
-                                ng-model="instance.config.vendor"
-                                ng-options="vendor.id as vendor.name for vendor in ldapVendors"
-                                required>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>LDAP vendor (provider)</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="usernameLDAPAttribute"><span class="required">*</span> Username LDAP attribute</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="usernameLDAPAttribute" type="text" ng-model="instance.config.usernameLDAPAttribute" placeholder="LDAP attribute name for username" required>
-                </div>
-                <kc-tooltip>Name of LDAP attribute, which is mapped as Keycloak username. For many LDAP server vendors it's 'uid'. For Active directory it's usually 'sAMAccountName' or 'cn'</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="rdnLDAPAttribute"><span class="required">*</span> RDN LDAP attribute</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="rdnLDAPAttribute" type="text" ng-model="instance.config.rdnLDAPAttribute" placeholder="LDAP attribute name for user RDN" required>
-                </div>
-                <kc-tooltip>Name of LDAP attribute, which is used as RDN (top attribute) of typical user DN. Usually it's the same as Username LDAP attribute, however for Active directory it could be 'cn' when username attribute might be 'sAMAccountName' </kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="uuidLDAPAttribute"><span class="required">*</span> UUID LDAP attribute</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="uuidLDAPAttribute" type="text" ng-model="instance.config.uuidLDAPAttribute" placeholder="LDAP attribute name for UUID" required>
-                </div>
-                <kc-tooltip>Name of LDAP attribute, which is used as unique object identifier (UUID) for objects in LDAP. For many LDAP server vendors it's 'entryUUID' however some are different. For example for Active directory it should be 'objectGUID' </kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="userObjectClasses"><span class="required">*</span> User Object Classes</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="userObjectClasses" type="text" ng-model="instance.config.userObjectClasses" placeholder="LDAP User Object Classes (div. by comma)" required>
-                </div>
-                <kc-tooltip>All values of LDAP objectClass attribute for users in LDAP divided by comma. For example: 'inetOrgPerson, organizationalPerson' . Newly created Keycloak users will be written to LDAP
-                    with all those object classes and existing LDAP user records are found just if they contain all those object classes. </kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="ldapConnectionUrl"><span class="required">*</span> Connection URL</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="ldapConnectionUrl" type="text" ng-model="instance.config.connectionUrl" placeholder="LDAP connection URL" required>
-                </div>
-                <kc-tooltip>Connection URL to your LDAP server</kc-tooltip>
-                <div class="col-sm-4" data-ng-show="access.manageRealm">
-                    <a class="btn btn-primary" data-ng-click="testConnection()">Test connection</a>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="ldapUsersDn"><span class="required">*</span> Users DN</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="ldapUsersDn" type="text" ng-model="instance.config.usersDn" placeholder="LDAP Users DN" required>
-                </div>
-                <kc-tooltip>Full DN of LDAP tree where your users are. This DN is parent of LDAP users. It could be for example 'ou=users,dc=example,dc=com' assuming
-                    that your typical user will have DN like 'uid=john,ou=users,dc=example,dc=com'
-                </kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="authType"><span class="required">*</span> Authentication Type</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="authType"
-                                ng-model="instance.config.authType"
-                                ng-options="authType.id as authType.name for authType in authTypes"
-                                required>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>LDAP Authentication type. Right now just 'none' (anonymous LDAP authentication) or 'simple' (Bind credential + Bind password authentication) mechanisms are available</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
-                <label class="col-md-2 control-label" for="ldapBindDn"><span class="required">*</span> Bind DN</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="ldapBindDn" type="text" ng-model="instance.config.bindDn" placeholder="LDAP Bind DN" data-ng-required="instance.config.authType != 'none'">
-                </div>
-                <kc-tooltip>DN of LDAP admin, which will be used by Keycloak to access LDAP server</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
-                <label class="col-md-2 control-label" for="ldapBindCredential"><span class="required">*</span> Bind Credential</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="ldapBindCredential" type="password" ng-model="instance.config.bindCredential" placeholder="LDAP Bind Credentials" data-ng-required="instance.config.authType != 'none'">
-                </div>
-                <kc-tooltip>Password of LDAP admin</kc-tooltip>
-                <div class="col-sm-4" data-ng-show="access.manageRealm">
-                    <a class="btn btn-primary" data-ng-click="testAuthentication()">Test authentication</a>
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="searchScope">Search scope</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="searchScope"
-                                ng-model="instance.config.searchScope"
-                                ng-options="searchScope.id as searchScope.name for searchScope in searchScopes"
-                                required>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>For one level, we search for users just in DNs specified by User DNs. For subtree, we search in whole of their subtree. See LDAP documentation for more details</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="connectionPooling">Connection pooling</label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.connectionPooling" name="connectionPooling" id="connectionPooling" onoffswitch />
-                </div>
-                <kc-tooltip>Does Keycloak should use connection pooling for accessing LDAP server</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="pagination">Pagination</label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.pagination" name="pagination" id="pagination" onoffswitch />
-                </div>
-                <kc-tooltip>Does the LDAP server support pagination.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="instance.config.vendor === 'ad' ">
-                <label class="col-md-2 control-label" for="userAccountControlsAfterPasswordUpdate">Enable Account After Password Update</label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.userAccountControlsAfterPasswordUpdate" name="userAccountControlsAfterPasswordUpdate" id="userAccountControlsAfterPasswordUpdate" onoffswitch />
-                </div>
-                <kc-tooltip>Useful just for Active Directory. If enabled, then Keycloak will always set
-                Active Directory userAccountControl attribute to 512 after password update. This would mean that particular user will be enabled in Active Directory</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <fieldset>
-            <legend><span class="text">Kerberos integration</span></legend>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="allowKerberosAuthentication">Allow Kerberos authentication </label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.allowKerberosAuthentication" id="allowKerberosAuthentication" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable HTTP authentication of users with SPNEGO/Kerberos tokens. The data about authenticated users will be provisioned from this LDAP server</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="kerberosRealm"><span class="required">*</span> Kerberos Realm</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="kerberosRealm" type="text" ng-model="instance.config.kerberosRealm" ng-required="instance.config.allowKerberosAuthentication">
-                </div>
-                <kc-tooltip>Name of kerberos realm. For example FOO.ORG</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="serverPrincipal"><span class="required">*</span> Server principal</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="serverPrincipal" type="text" ng-model="instance.config.serverPrincipal" ng-required="instance.config.allowKerberosAuthentication">
-                </div>
-                <kc-tooltip>Full name of server principal for HTTP service including server and domain name. For example HTTP/host.foo.org@FOO.ORG</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="keyTab"><span class="required">*</span> KeyTab</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="keyTab" type="text" ng-model="instance.config.keyTab" ng-required="instance.config.allowKerberosAuthentication">
-                </div>
-                <kc-tooltip>Location of Kerberos KeyTab file containing the credentials of server principal. For example /etc/krb5.keytab</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="debug">Debug </label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.debug" id="debug" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable debug logging to standard output for Krb5LoginModule.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="debug">Use Kerberos For Password Authentication </label>
-                <div class="col-md-6">
-                    <input ng-model="instance.config.useKerberosForPasswordAuthentication" id="useKerberosForPasswordAuthentication" onoffswitch />
-                </div>
-                <kc-tooltip>Use Kerberos login module for authenticate username/password against Kerberos server instead of authenticating against LDAP server with Directory Service API</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <fieldset>
-            <legend><span class="text">Sync settings</span></legend>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="batchSizeForSync">Batch size</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" ng-model="instance.config.batchSizeForSync" id="batchSizeForSync" />
-                </div>
-                <kc-tooltip>Count of LDAP users to be imported from LDAP to Keycloak within single transaction.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="fullSyncEnabled">Periodic full sync</label>
-                <div class="col-md-6">
-                    <input ng-model="fullSyncEnabled" name="fullSyncEnabled" id="fullSyncEnabled" onoffswitch />
-                </div>
-                <kc-tooltip>Does periodic full synchronization of LDAP users to Keycloak should be enabled or not</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="fullSyncEnabled">
-                <label class="col-md-2 control-label" for="fullSyncPeriod">Full sync period</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="number" ng-model="instance.fullSyncPeriod" id="fullSyncPeriod" />
-                </div>
-                <kc-tooltip>Period for full synchronization in seconds</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="changedSyncEnabled">Periodic changed users sync</label>
-                <div class="col-md-6">
-                    <input ng-model="changedSyncEnabled" name="changedSyncEnabled" id="changedSyncEnabled" onoffswitch />
-                </div>
-                <kc-tooltip>Does periodic synchronization of changed or newly created LDAP users to Keycloak should be enabled or not</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="changedSyncEnabled">
-                <label class="col-md-2 control-label" for="changedSyncPeriod">Changed users sync period</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="number" ng-model="instance.changedSyncPeriod" id="changedSyncPeriod" />
-                </div>
-                <kc-tooltip>Period for synchronization of changed or newly created LDAP users in seconds</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
-                <button kc-save>Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-                <button class="btn btn-primary" data-ng-click="triggerChangedUsersSync()" data-ng-hide="changed">Synchronize changed users</button>
-                <button class="btn btn-primary" data-ng-click="triggerFullSync()" data-ng-hide="changed">Synchronize all users</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/user-federation">User Federation</a></li>
+        <li data-ng-hide="create">{{instance.displayName|capitalize}}</li>
+        <li data-ng-show="create">Add User Federation Provider</li>
+    </ol>
+
+    <h1 data-ng-hide="create">LDAP<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add LDAP User Federation Provider</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="create">
+        <li class="active"><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}/mappers">Mappers</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+
+        <fieldset>
+            <legend><span class="text">Required Settings</span></legend>
+            <div class="form-group clearfix" data-ng-show="!create">
+                <label class="col-md-2 control-label" for="providerId">Provider ID </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="providerId" type="text" ng-model="instance.id" readonly>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="consoleDisplayName">Console display name </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="consoleDisplayName" type="text" ng-model="instance.displayName" placeholder="defaults to id">
+                </div>
+                <kc-tooltip>Display name of provider when linked in admin console.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="priority">Priority </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="priority" type="text" ng-model="instance.priority">
+                </div>
+                <kc-tooltip>Priority of provider when doing a user lookup.  Lowest first.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="editMode">Edit mode</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="editMode"
+                                ng-model="instance.config.editMode">
+                            <option>READ_ONLY</option>
+                            <option>WRITABLE</option>
+                            <option>UNSYNCED</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>READ_ONLY is a read only LDAP store.  WRITABLE means data will be synced back to LDAP on demand.  UNSYNCED means user data will be imported, but not synced back to LDAP.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="syncRegistrations">Sync Registrations</label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.syncRegistrations" name="syncRegistrations" id="syncRegistrations" onoffswitch />
+                </div>
+                <kc-tooltip>Should newly created users be created within LDAP store?  Priority effects which provider is chose to sync the new user.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="vendor"><span class="required">*</span> Vendor</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="vendor"
+                                ng-model="instance.config.vendor"
+                                ng-options="vendor.id as vendor.name for vendor in ldapVendors"
+                                required>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>LDAP vendor (provider)</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="usernameLDAPAttribute"><span class="required">*</span> Username LDAP attribute</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="usernameLDAPAttribute" type="text" ng-model="instance.config.usernameLDAPAttribute" placeholder="LDAP attribute name for username" required>
+                </div>
+                <kc-tooltip>Name of LDAP attribute, which is mapped as Keycloak username. For many LDAP server vendors it's 'uid'. For Active directory it's usually 'sAMAccountName' or 'cn'</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="rdnLDAPAttribute"><span class="required">*</span> RDN LDAP attribute</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="rdnLDAPAttribute" type="text" ng-model="instance.config.rdnLDAPAttribute" placeholder="LDAP attribute name for user RDN" required>
+                </div>
+                <kc-tooltip>Name of LDAP attribute, which is used as RDN (top attribute) of typical user DN. Usually it's the same as Username LDAP attribute, however for Active directory it could be 'cn' when username attribute might be 'sAMAccountName' </kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="uuidLDAPAttribute"><span class="required">*</span> UUID LDAP attribute</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="uuidLDAPAttribute" type="text" ng-model="instance.config.uuidLDAPAttribute" placeholder="LDAP attribute name for UUID" required>
+                </div>
+                <kc-tooltip>Name of LDAP attribute, which is used as unique object identifier (UUID) for objects in LDAP. For many LDAP server vendors it's 'entryUUID' however some are different. For example for Active directory it should be 'objectGUID' </kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="userObjectClasses"><span class="required">*</span> User Object Classes</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="userObjectClasses" type="text" ng-model="instance.config.userObjectClasses" placeholder="LDAP User Object Classes (div. by comma)" required>
+                </div>
+                <kc-tooltip>All values of LDAP objectClass attribute for users in LDAP divided by comma. For example: 'inetOrgPerson, organizationalPerson' . Newly created Keycloak users will be written to LDAP
+                    with all those object classes and existing LDAP user records are found just if they contain all those object classes. </kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="ldapConnectionUrl"><span class="required">*</span> Connection URL</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="ldapConnectionUrl" type="text" ng-model="instance.config.connectionUrl" placeholder="LDAP connection URL" required>
+                </div>
+                <kc-tooltip>Connection URL to your LDAP server</kc-tooltip>
+                <div class="col-sm-4" data-ng-show="access.manageRealm">
+                    <a class="btn btn-primary" data-ng-click="testConnection()">Test connection</a>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="ldapUsersDn"><span class="required">*</span> Users DN</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="ldapUsersDn" type="text" ng-model="instance.config.usersDn" placeholder="LDAP Users DN" required>
+                </div>
+                <kc-tooltip>Full DN of LDAP tree where your users are. This DN is parent of LDAP users. It could be for example 'ou=users,dc=example,dc=com' assuming
+                    that your typical user will have DN like 'uid=john,ou=users,dc=example,dc=com'
+                </kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="authType"><span class="required">*</span> Authentication Type</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="authType"
+                                ng-model="instance.config.authType"
+                                ng-options="authType.id as authType.name for authType in authTypes"
+                                required>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>LDAP Authentication type. Right now just 'none' (anonymous LDAP authentication) or 'simple' (Bind credential + Bind password authentication) mechanisms are available</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
+                <label class="col-md-2 control-label" for="ldapBindDn"><span class="required">*</span> Bind DN</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="ldapBindDn" type="text" ng-model="instance.config.bindDn" placeholder="LDAP Bind DN" data-ng-required="instance.config.authType != 'none'">
+                </div>
+                <kc-tooltip>DN of LDAP admin, which will be used by Keycloak to access LDAP server</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
+                <label class="col-md-2 control-label" for="ldapBindCredential"><span class="required">*</span> Bind Credential</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="ldapBindCredential" type="password" ng-model="instance.config.bindCredential" placeholder="LDAP Bind Credentials" data-ng-required="instance.config.authType != 'none'">
+                </div>
+                <kc-tooltip>Password of LDAP admin</kc-tooltip>
+                <div class="col-sm-4" data-ng-show="access.manageRealm">
+                    <a class="btn btn-primary" data-ng-click="testAuthentication()">Test authentication</a>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="searchScope">Search scope</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="searchScope"
+                                ng-model="instance.config.searchScope"
+                                ng-options="searchScope.id as searchScope.name for searchScope in searchScopes"
+                                required>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>For one level, we search for users just in DNs specified by User DNs. For subtree, we search in whole of their subtree. See LDAP documentation for more details</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="connectionPooling">Connection pooling</label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.connectionPooling" name="connectionPooling" id="connectionPooling" onoffswitch />
+                </div>
+                <kc-tooltip>Does Keycloak should use connection pooling for accessing LDAP server</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="pagination">Pagination</label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.pagination" name="pagination" id="pagination" onoffswitch />
+                </div>
+                <kc-tooltip>Does the LDAP server support pagination.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config.vendor === 'ad' ">
+                <label class="col-md-2 control-label" for="userAccountControlsAfterPasswordUpdate">Enable Account After Password Update</label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.userAccountControlsAfterPasswordUpdate" name="userAccountControlsAfterPasswordUpdate" id="userAccountControlsAfterPasswordUpdate" onoffswitch />
+                </div>
+                <kc-tooltip>Useful just for Active Directory. If enabled, then Keycloak will always set
+                Active Directory userAccountControl attribute to 512 after password update. This would mean that particular user will be enabled in Active Directory</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <fieldset>
+            <legend><span class="text">Kerberos integration</span></legend>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="allowKerberosAuthentication">Allow Kerberos authentication </label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.allowKerberosAuthentication" id="allowKerberosAuthentication" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable HTTP authentication of users with SPNEGO/Kerberos tokens. The data about authenticated users will be provisioned from this LDAP server</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
+                <label class="col-md-2 control-label" for="kerberosRealm"><span class="required">*</span> Kerberos Realm</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="kerberosRealm" type="text" ng-model="instance.config.kerberosRealm" ng-required="instance.config.allowKerberosAuthentication">
+                </div>
+                <kc-tooltip>Name of kerberos realm. For example FOO.ORG</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
+                <label class="col-md-2 control-label" for="serverPrincipal"><span class="required">*</span> Server principal</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="serverPrincipal" type="text" ng-model="instance.config.serverPrincipal" ng-required="instance.config.allowKerberosAuthentication">
+                </div>
+                <kc-tooltip>Full name of server principal for HTTP service including server and domain name. For example HTTP/host.foo.org@FOO.ORG</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config.allowKerberosAuthentication">
+                <label class="col-md-2 control-label" for="keyTab"><span class="required">*</span> KeyTab</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="keyTab" type="text" ng-model="instance.config.keyTab" ng-required="instance.config.allowKerberosAuthentication">
+                </div>
+                <kc-tooltip>Location of Kerberos KeyTab file containing the credentials of server principal. For example /etc/krb5.keytab</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="instance.config.allowKerberosAuthentication">
+                <label class="col-md-2 control-label" for="debug">Debug </label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.debug" id="debug" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable debug logging to standard output for Krb5LoginModule.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="instance.config.allowKerberosAuthentication">
+                <label class="col-md-2 control-label" for="debug">Use Kerberos For Password Authentication </label>
+                <div class="col-md-6">
+                    <input ng-model="instance.config.useKerberosForPasswordAuthentication" id="useKerberosForPasswordAuthentication" onoffswitch />
+                </div>
+                <kc-tooltip>Use Kerberos login module for authenticate username/password against Kerberos server instead of authenticating against LDAP server with Directory Service API</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <fieldset>
+            <legend><span class="text">Sync settings</span></legend>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="batchSizeForSync">Batch size</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" ng-model="instance.config.batchSizeForSync" id="batchSizeForSync" />
+                </div>
+                <kc-tooltip>Count of LDAP users to be imported from LDAP to Keycloak within single transaction.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="fullSyncEnabled">Periodic full sync</label>
+                <div class="col-md-6">
+                    <input ng-model="fullSyncEnabled" name="fullSyncEnabled" id="fullSyncEnabled" onoffswitch />
+                </div>
+                <kc-tooltip>Does periodic full synchronization of LDAP users to Keycloak should be enabled or not</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="fullSyncEnabled">
+                <label class="col-md-2 control-label" for="fullSyncPeriod">Full sync period</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="number" ng-model="instance.fullSyncPeriod" id="fullSyncPeriod" />
+                </div>
+                <kc-tooltip>Period for full synchronization in seconds</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="changedSyncEnabled">Periodic changed users sync</label>
+                <div class="col-md-6">
+                    <input ng-model="changedSyncEnabled" name="changedSyncEnabled" id="changedSyncEnabled" onoffswitch />
+                </div>
+                <kc-tooltip>Does periodic synchronization of changed or newly created LDAP users to Keycloak should be enabled or not</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="changedSyncEnabled">
+                <label class="col-md-2 control-label" for="changedSyncPeriod">Changed users sync period</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="number" ng-model="instance.changedSyncPeriod" id="changedSyncPeriod" />
+                </div>
+                <kc-tooltip>Period for synchronization of changed or newly created LDAP users in seconds</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
+                <button kc-save>Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+                <button class="btn btn-primary" data-ng-click="triggerChangedUsersSync()" data-ng-hide="changed">Synchronize changed users</button>
+                <button class="btn btn-primary" data-ng-click="triggerFullSync()" data-ng-hide="changed">Synchronize all users</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/forbidden.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/forbidden.html
index 6a0d5bf..b40f2e7 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/forbidden.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/forbidden.html
@@ -1,7 +1,7 @@
-<div id="content-area" class="col-sm-12" role="main">
-    <div class="error-container">
-        <h2>Forbidden</h2>
-        <p class="instruction">You don't have access to the requested resource.</p>
-        <a href="#" class="link-right">Go to the home page &raquo;</a>
-    </div>
+<div id="content-area" class="col-sm-12" role="main">
+    <div class="error-container">
+        <h2>Forbidden</h2>
+        <p class="instruction">You don't have access to the requested resource.</p>
+        <a href="#" class="link-right">Go to the home page &raquo;</a>
+    </div>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/home.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/home.html
index acf8d6a..dc2471b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/home.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/home.html
@@ -1,4 +1,4 @@
-<div id="wrapper" class="container">
-    <div class="row">
-    </div>
+<div id="wrapper" class="container">
+    <div class="row">
+    </div>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
index 7b2b50d..1b46810 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
@@ -1,62 +1,62 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Identity Provider Mappers</a></li>
-        <li class="active" data-ng-show="create">Create IdentityProvider Mapper</li>
-        <li class="active" data-ng-hide="create">{{mapper.name|capitalize}}</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add Identity Provider Mapper</h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset>
-            <div class="form-group clearfix" data-ng-show="!create">
-                <label class="col-md-2 control-label" for="mapperId">ID </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="mapperId" type="text" ng-model="mapper.id" readonly>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="name">Name <span class="required">*</span></label>
-                <div class="col-md-6">
-                    <input class="form-control" id="name" type="text" ng-model="mapper.name" data-ng-readonly="!create" required>
-                </div>
-                <kc-tooltip>Name of the mapper.</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="create">
-                <label class="col-md-2 control-label" for="mapperTypeCreate">Mapper Type</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="mapperTypeCreate"
-                                ng-model="mapperType"
-                                ng-options="mapperType.name for (mapperKey, mapperType) in mapperTypes">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-hide="create">
-                <label class="col-md-2 control-label" for="mapperType">Mapper Type</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="mapperType" type="text" ng-model="mapperType.name" data-ng-readonly="true">
-                </div>
-                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
-            </div>
-            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
-        </fieldset>
-        <div class="pull-right form-actions" data-ng-show="create && access.manageRealm">
-            <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            <button kc-save>Save</button>
-        </div>
-
-        <div class="pull-right form-actions" data-ng-show="!create && access.manageRealm">
-            <button kc-reset data-ng-show="changed">Clear changes</button>
-            <button kc-save  data-ng-show="changed">Save</button>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Identity Provider Mappers</a></li>
+        <li class="active" data-ng-show="create">Create IdentityProvider Mapper</li>
+        <li class="active" data-ng-hide="create">{{mapper.name|capitalize}}</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add Identity Provider Mapper</h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset>
+            <div class="form-group clearfix" data-ng-show="!create">
+                <label class="col-md-2 control-label" for="mapperId">ID </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="mapperId" type="text" ng-model="mapper.id" readonly>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="name">Name <span class="required">*</span></label>
+                <div class="col-md-6">
+                    <input class="form-control" id="name" type="text" ng-model="mapper.name" data-ng-readonly="!create" required>
+                </div>
+                <kc-tooltip>Name of the mapper.</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="create">
+                <label class="col-md-2 control-label" for="mapperTypeCreate">Mapper Type</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="mapperTypeCreate"
+                                ng-model="mapperType"
+                                ng-options="mapperType.name for (mapperKey, mapperType) in mapperTypes">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-hide="create">
+                <label class="col-md-2 control-label" for="mapperType">Mapper Type</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="mapperType" type="text" ng-model="mapperType.name" data-ng-readonly="true">
+                </div>
+                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
+            </div>
+            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
+        </fieldset>
+        <div class="pull-right form-actions" data-ng-show="create && access.manageRealm">
+            <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            <button kc-save>Save</button>
+        </div>
+
+        <div class="pull-right form-actions" data-ng-show="!create && access.manageRealm">
+            <button kc-reset data-ng-show="changed">Clear changes</button>
+            <button kc-save  data-ng-show="changed">Save</button>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
index 20339e1..24409e2 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
@@ -1,53 +1,53 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li>{{identityProvider.alias}}</li>
-    </ol>
-
-    <h1>{{identityProvider.alias|capitalize}}</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
-        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider && identityProvider.providerId == 'saml'">Export</a></li>
-    </ul>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="4">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right">
-                        <a class="btn btn-primary" href="#/create/identity-provider-mappers/{{realm.realm}}/{{identityProvider.alias}}">Create</a>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="mappers.length == 0">
-            <th>Name</th>
-            <th>Category</th>
-            <th>Type</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="mapper in mappers | filter:search">
-            <td><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
-            <td>{{mapperTypes[mapper.identityProviderMapper].category}}</td>
-            <td>{{mapperTypes[mapper.identityProviderMapper].name}}</td>
-        </tr>
-        <tr data-ng-show="mappers.length == 0">
-            <td>No mappers available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li>{{identityProvider.alias}}</li>
+    </ol>
+
+    <h1>{{identityProvider.alias|capitalize}}</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
+        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider && identityProvider.providerId == 'saml'">Export</a></li>
+    </ul>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="4">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." data-ng-model="search.name" 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 class="pull-right">
+                        <a class="btn btn-primary" href="#/create/identity-provider-mappers/{{realm.realm}}/{{identityProvider.alias}}">Create</a>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-hide="mappers.length == 0">
+            <th>Name</th>
+            <th>Category</th>
+            <th>Type</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="mapper in mappers | filter:search">
+            <td><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers/{{mapper.id}}">{{mapper.name}}</a></td>
+            <td>{{mapperTypes[mapper.identityProviderMapper].category}}</td>
+            <td>{{mapperTypes[mapper.identityProviderMapper].name}}</td>
+        </tr>
+        <tr data-ng-show="mappers.length == 0">
+            <td>No mappers available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/menu.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/menu.html
index c85e83e..df5560d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/menu.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/menu.html
@@ -1,25 +1,25 @@
-<div class="navbar-header">
-    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
-        <span class="sr-only">Toggle navigation</span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-    </button>
-    <a class="navbar-brand" href="#/"></a>
-</div>
-<div class="collapse navbar-collapse navbar-collapse-1">
-    <ul class="nav navbar-nav navbar-utility">
-        <li class="dropdown">
-            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
-                <span class="pficon pficon-user"></span>
-                {{auth.user.displayName|capitalize}} <b class="caret"></b>
-            </a>
-            <ul class="dropdown-menu">
-                <li><a href="{{authUrl}}/realms/{{auth.user.realm}}/account?referrer=security-admin-console">Manage Account</a></li>
-                <li><a href="#/server-info">Server Info</a></li>
-                <li class="divider"></li>
-                <li><a href="" ng-click="auth.authz.logout()">Sign Out</a></li>
-            </ul>
-        </li>
-    </ul>
+<div class="navbar-header">
+    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
+        <span class="sr-only">Toggle navigation</span>
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+    </button>
+    <a class="navbar-brand" href="#/"></a>
+</div>
+<div class="collapse navbar-collapse navbar-collapse-1">
+    <ul class="nav navbar-nav navbar-utility">
+        <li class="dropdown">
+            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+                <span class="pficon pficon-user"></span>
+                {{auth.user.displayName|capitalize}} <b class="caret"></b>
+            </a>
+            <ul class="dropdown-menu">
+                <li><a href="{{authUrl}}/realms/{{auth.user.realm}}/account?referrer=security-admin-console">Manage Account</a></li>
+                <li><a href="#/server-info">Server Info</a></li>
+                <li class="divider"></li>
+                <li><a href="" ng-click="auth.authz.logout()">Sign Out</a></li>
+            </ul>
+        </li>
+    </ul>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
index be2f42c..55c5430 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
@@ -1,40 +1,40 @@
-<div style="padding: 15px 60px 75px 60px">
-    <h2>Role Selector</h2>
-    <form>
-        <div data-ng-show="realmRoles.length > 0">
-        <label class="control-label" for="available">Realm Roles</label>
-        <kc-tooltip>Realm roles that can be selected.</kc-tooltip>
-        <select id="available" class="form-control" size="5"
-                ng-dblclick="selectRealmRole()"
-                ng-model="selectedRealmRole.role"
-                ng-options="r.name for r in realmRoles | orderBy:'toString()'">
-            <option style="display:none" value="">Select a role</option>
-        </select>
-        <button class="btn btn-default" type="submit" ng-click="selectRealmRole()" tooltip="Select realm role" tooltip-placement="right">
-            Select Realm Role</i>
-        </button>
-        </div>
-        <br>
-        <br>
-        <div data-ng-show="clients.length > 0">
-        <label class="control-label">
-            <span>Client Roles</span>
-            <kc-tooltip>Client roles that can be selected.</kc-tooltip>
-            <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client.selected" ng-options="a.clientId for a in clients" ng-disabled="false">
-            </select>
-        </label>
-        <select id="available-client" class="form-control" size="5"
-                ng-dblclick="selectClientRole()"
-                ng-model="selectedClientRole.role"
-                ng-options="r.name for r in clientRoles | orderBy:'toString()'">
-            <option style="display:none" value="">Select a role</option>
-        </select>
-        <button class="btn btn-default" type="submit" ng-click="selectClientRole()" tooltip="Select client role" tooltip-placement="right">
-            Select Client Role
-        </button>
-        </div>
-    </form>
-    <div class="modal-footer">
-        <button type="button" data-ng-class="btns.cancel.cssClass" ng-click="cancel()">Cancel</button>
-    </div>
-</div>
+<div style="padding: 15px 60px 75px 60px">
+    <h2>Role Selector</h2>
+    <form>
+        <div data-ng-show="realmRoles.length > 0">
+        <label class="control-label" for="available">Realm Roles</label>
+        <kc-tooltip>Realm roles that can be selected.</kc-tooltip>
+        <select id="available" class="form-control" size="5"
+                ng-dblclick="selectRealmRole()"
+                ng-model="selectedRealmRole.role"
+                ng-options="r.name for r in realmRoles | orderBy:'toString()'">
+            <option style="display:none" value="">Select a role</option>
+        </select>
+        <button class="btn btn-default" type="submit" ng-click="selectRealmRole()" tooltip="Select realm role" tooltip-placement="right">
+            Select Realm Role</i>
+        </button>
+        </div>
+        <br>
+        <br>
+        <div data-ng-show="clients.length > 0">
+        <label class="control-label">
+            <span>Client Roles</span>
+            <kc-tooltip>Client roles that can be selected.</kc-tooltip>
+            <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client.selected" ng-options="a.clientId for a in clients" ng-disabled="false">
+            </select>
+        </label>
+        <select id="available-client" class="form-control" size="5"
+                ng-dblclick="selectClientRole()"
+                ng-model="selectedClientRole.role"
+                ng-options="r.name for r in clientRoles | orderBy:'toString()'">
+            <option style="display:none" value="">Select a role</option>
+        </select>
+        <button class="btn btn-default" type="submit" ng-click="selectClientRole()" tooltip="Select client role" tooltip-placement="right">
+            Select Client Role
+        </button>
+        </div>
+    </form>
+    <div class="modal-footer">
+        <button type="button" data-ng-class="btns.cancel.cssClass" ng-click="cancel()">Cancel</button>
+    </div>
+</div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/notfound.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/notfound.html
index 05652f0..20286c4 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/notfound.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/notfound.html
@@ -1,7 +1,7 @@
-<div id="content-area" class="col-sm-12" role="main">
-    <div class="error-container">
-        <h2>Resource <strong>not found</strong>...</h2>
-        <p class="instruction">We could not find the resource you are looking for. Please make sure the URL you entered is correct.</p>
-        <a href="#" class="link-right">Go to the home page &raquo;</a>
-    </div>
+<div id="content-area" class="col-sm-12" role="main">
+    <div class="error-container">
+        <h2>Resource <strong>not found</strong>...</h2>
+        <p class="instruction">We could not find the resource you are looking for. Please make sure the URL you entered is correct.</p>
+        <a href="#" class="link-right">Go to the home page &raquo;</a>
+    </div>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/pagenotfound.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/pagenotfound.html
index 769d71e..b11cbcc 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/pagenotfound.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/pagenotfound.html
@@ -1,7 +1,7 @@
-<div id="content-area" class="col-sm-12" role="main">
-    <div class="error-container">
-        <h2>Page <strong>not found</strong>...</h2>
-        <p class="instruction">We could not find the page you are looking for. Please make sure the URL you entered is correct.</p>
-        <a href="#" class="link-right">Go to the home page &raquo;</a>
-    </div>
+<div id="content-area" class="col-sm-12" role="main">
+    <div class="error-container">
+        <h2>Page <strong>not found</strong>...</h2>
+        <p class="instruction">We could not find the page you are looking for. Please make sure the URL you entered is correct.</p>
+        <a href="#" class="link-right">Go to the home page &raquo;</a>
+    </div>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
index a076c06..f9d7c43 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
@@ -1,57 +1,57 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Authentication</h1>
-
-    <kc-tabs-authentication></kc-tabs-authentication>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <legend><span class="text">Realm Password Policy</span> <kc-tooltip>Specify required password format.  You can also set how many times a password is hashed before it is stored in database. Multiple Regex patterns, separated by comma, can be added.</kc-tooltip></legend>
-            <table class="table table-striped table-bordered">
-                <caption class="hidden">Table of Password Policies</caption>
-                <thead>
-                <tr ng-show="(allPolicies|remove:policy:'name').length > 0">
-                    <th colspan="5" class="kc-table-actions">
-                        <div class="pull-right">
-                            <div>
-                                <select class="form-control" ng-model="selectedPolicy"
-                                        ng-options="(p.name|capitalize) for p in (allPolicies|remove:policy:'name')"
-                                        data-ng-change="addPolicy(selectedPolicy); selectedPolicy = null">
-                                    <option value="" disabled selected>Add policy...</option>
-                                </select>
-                            </div>
-                        </div>
-                    </th>
-                </tr>
-                <tr>
-                    <th>Policy Type</th>
-                    <th>Policy Value</th>
-                    <th class="actions">Actions</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr ng-repeat="p in policy">
-                    <td>{{p.name|capitalize}}</td>
-                    <td>
-                        <input class="form-control" ng-model="p.value" ng-show="p.name != 'notUsername' "
-                               placeholder="No value assigned" min="1" required>
-                    </td>
-                    <td class="actions">
-                        <div class="action-div"><i class="pficon pficon-delete" ng-click="removePolicy($index)" tooltip-placement="right" tooltip="Remove Policy"></i></div>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </fieldset>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Authentication</h1>
+
+    <kc-tabs-authentication></kc-tabs-authentication>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <legend><span class="text">Realm Password Policy</span> <kc-tooltip>Specify required password format.  You can also set how many times a password is hashed before it is stored in database. Multiple Regex patterns, separated by comma, can be added.</kc-tooltip></legend>
+            <table class="table table-striped table-bordered">
+                <caption class="hidden">Table of Password Policies</caption>
+                <thead>
+                <tr ng-show="(allPolicies|remove:policy:'name').length > 0">
+                    <th colspan="5" class="kc-table-actions">
+                        <div class="pull-right">
+                            <div>
+                                <select class="form-control" ng-model="selectedPolicy"
+                                        ng-options="(p.name|capitalize) for p in (allPolicies|remove:policy:'name')"
+                                        data-ng-change="addPolicy(selectedPolicy); selectedPolicy = null">
+                                    <option value="" disabled selected>Add policy...</option>
+                                </select>
+                            </div>
+                        </div>
+                    </th>
+                </tr>
+                <tr>
+                    <th>Policy Type</th>
+                    <th>Policy Value</th>
+                    <th class="actions">Actions</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr ng-repeat="p in policy">
+                    <td>{{p.name|capitalize}}</td>
+                    <td>
+                        <input class="form-control" ng-model="p.value" ng-show="p.name != 'notUsername' "
+                               placeholder="No value assigned" min="1" required>
+                    </td>
+                    <td class="actions">
+                        <div class="action-div"><i class="pficon pficon-delete" ng-click="removePolicy($index)" tooltip-placement="right" tooltip="Remove Policy"></i></div>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </fieldset>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
index bf78e31..27e49cd 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
@@ -1,91 +1,91 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
-        <li class="active" data-ng-show="create">Create Protocol Mappers</li>
-        <li class="active" data-ng-hide="create">{{mapper.name}}</li>
-    </ol>
-
-    <h1 data-ng-show="create">Create Protocol Mapper</h1>
-    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="protocol">Protocol</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="protocol" type="text" ng-model="protocol" readonly>
-                </div>
-                <kc-tooltip>Protocol.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="!create">
-                <label class="col-md-2 control-label" for="mapperId">ID </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="mapperId" type="text" ng-model="mapper.id" readonly>
-                </div>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="name">Name</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="name" type="text" ng-model="mapper.name" data-ng-readonly="!create">
-                </div>
-                <kc-tooltip>Name of the mapper.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label for="consentRequired" class="col-sm-2 control-label">Consent required</label>
-                <div class="col-md-6">
-                    <input ng-model="mapper.consentRequired" name="consentRequired" id="consentRequired" onoffswitch />
-                </div>
-                <kc-tooltip>When granting temporary access, must the user consent to providing this data to the client?</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="mapper.consentRequired">
-                <label class="col-md-2 control-label" for="consentText">Consent Text </label>
-
-                <div class="col-md-6">
-                    <textarea class="form-control" rows="5" cols="50" id="consentText" name="consentText" data-ng-model="mapper.consentText"></textarea>
-                </div>
-                <kc-tooltip>Text to display on consent page</kc-tooltip>
-            </div>
-            <div class="form-group" data-ng-show="create">
-                <label class="col-md-2 control-label" for="mapperTypeCreate">Mapper Type</label>
-                <div class="col-sm-6">
-                    <div>
-                        <select class="form-control" id="mapperTypeCreate"
-                                ng-model="mapperType"
-                                ng-options="mapperType.name for mapperType in mapperTypes">
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-hide="create">
-                <label class="col-md-2 control-label" for="mapperType">Mapper Type</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="mapperType" type="text" ng-model="mapperType.name" data-ng-readonly="true">
-                </div>
-                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
-            </div>
-            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageRealm">
-                <button kc-save>Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
+        <li class="active" data-ng-show="create">Create Protocol Mappers</li>
+        <li class="active" data-ng-hide="create">{{mapper.name}}</li>
+    </ol>
+
+    <h1 data-ng-show="create">Create Protocol Mapper</h1>
+    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="protocol">Protocol</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="protocol" type="text" ng-model="protocol" readonly>
+                </div>
+                <kc-tooltip>Protocol.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="!create">
+                <label class="col-md-2 control-label" for="mapperId">ID </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="mapperId" type="text" ng-model="mapper.id" readonly>
+                </div>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="name">Name</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="name" type="text" ng-model="mapper.name" data-ng-readonly="!create">
+                </div>
+                <kc-tooltip>Name of the mapper.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label for="consentRequired" class="col-sm-2 control-label">Consent required</label>
+                <div class="col-md-6">
+                    <input ng-model="mapper.consentRequired" name="consentRequired" id="consentRequired" onoffswitch />
+                </div>
+                <kc-tooltip>When granting temporary access, must the user consent to providing this data to the client?</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="mapper.consentRequired">
+                <label class="col-md-2 control-label" for="consentText">Consent Text </label>
+
+                <div class="col-md-6">
+                    <textarea class="form-control" rows="5" cols="50" id="consentText" name="consentText" data-ng-model="mapper.consentText"></textarea>
+                </div>
+                <kc-tooltip>Text to display on consent page</kc-tooltip>
+            </div>
+            <div class="form-group" data-ng-show="create">
+                <label class="col-md-2 control-label" for="mapperTypeCreate">Mapper Type</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="mapperTypeCreate"
+                                ng-model="mapperType"
+                                ng-options="mapperType.name for mapperType in mapperTypes">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-hide="create">
+                <label class="col-md-2 control-label" for="mapperType">Mapper Type</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="mapperType" type="text" ng-model="mapperType.name" data-ng-readonly="true">
+                </div>
+                <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
+            </div>
+            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageRealm">
+                <button kc-save>Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
index aa829d7..74febd7 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
@@ -1,31 +1,31 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="realmCacheEnabled">Realm Cache Enabled</label>
-            <div class="col-md-6">
-                <input ng-model="realm.realmCacheEnabled" name="realmCacheEnabled" id="realmCacheEnabled" onoffswitch />
-            </div>
-             <kc-tooltip>Enable/disable cache for realm, client and role data.</kc-tooltip>
-         </div>
-        <div class="form-group">
-            <label class="col-md-2 control-label" for="userCacheEnabled">User Cache Enabled</label>
-            <div class="col-md-6">
-                <input ng-model="realm.userCacheEnabled" name="userCacheEnabled" id="userCacheEnabled" onoffswitch />
-            </div>
-            <kc-tooltip>Enable/disable user and user role mapping cache.</kc-tooltip>
-        </div>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="realmCacheEnabled">Realm Cache Enabled</label>
+            <div class="col-md-6">
+                <input ng-model="realm.realmCacheEnabled" name="realmCacheEnabled" id="realmCacheEnabled" onoffswitch />
+            </div>
+             <kc-tooltip>Enable/disable cache for realm, client and role data.</kc-tooltip>
+         </div>
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="userCacheEnabled">User Cache Enabled</label>
+            <div class="col-md-6">
+                <input ng-model="realm.userCacheEnabled" name="userCacheEnabled" id="userCacheEnabled" onoffswitch />
+            </div>
+            <kc-tooltip>Enable/disable user and user role mapping cache.</kc-tooltip>
+        </div>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
index 687ea8e..c28f12b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-create.html
@@ -1,53 +1,53 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <h1>Add Realm</h1>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset>
-            <legend><span class="text">Import Realm</span></legend>
-            <div class="form-group">
-                <label for="import-file" class="col-sm-2 control-label">Import JSON File </label>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
-                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
-                    </div>
-                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">{{files[0].name}}</span>
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="files.length > 0">
-                <div class="col-md-10 col-md-offset-2">
-                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Upload</button>
-                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset>
-            <legend><span class="text">Create Realm</span></legend>
-            <div class="form-group">
-                <label for="name" class="col-sm-2 control-label">Name <span class="required">*</span></label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocusrequired>
-                </div>
-            </div>
-            <div class="form-group">
-                <label for="enabled" class="col-sm-2 control-label">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
-                </div>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <h1>Add Realm</h1>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset>
+            <legend><span class="text">Import Realm</span></legend>
+            <div class="form-group">
+                <label for="import-file" class="col-sm-2 control-label">Import JSON File </label>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
+                    </div>
+                    <span class="kc-uploaded-file" data-ng-show="files.length > 0">{{files[0].name}}</span>
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="files.length > 0">
+                <div class="col-md-10 col-md-offset-2">
+                    <button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Upload</button>
+                    <button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset>
+            <legend><span class="text">Create Realm</span></legend>
+            <div class="form-group">
+                <label for="name" class="col-sm-2 control-label">Name <span class="required">*</span></label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocusrequired>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="enabled" class="col-sm-2 control-label">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
+                </div>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
index 7d9ad1c..841feef 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
@@ -1,82 +1,82 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Roles</h1>
-
-    <ul class="nav nav-tabs">
-        <li><a href="#/realms/{{realm.realm}}/roles">Realm Roles</a></li>
-        <li class="active"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
-    </ul>
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <div class="form-group">
-            <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
-
-            <div class="col-md-10">
-                <div class="row">
-                    <div class="col-md-4">
-                        <label class="control-label" for="available">Available Roles</label>
-                        <kc-tooltip>Realm level roles that can be assigned.</kc-tooltip>
-                        <select id="available" class="form-control" multiple size="5"
-                                ng-multiple="true"
-                                ng-model="selectedRealmRoles"
-                                ng-options="r for r in availableRealmRoles | orderBy:'toString()'">
-                        </select>
-                        <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmDefaultRole()">
-                            Add selected <i class="fa fa-angle-double-right"></i>
-                        </button>
-                    </div>
-                    <div class="col-md-4">
-                        <label class="control-label" for="assigned">Realm Default Roles</label>
-                        <kc-tooltip>Realm level roles assigned to new users.</kc-tooltip>
-                        <select id="assigned" class="form-control" multiple size=5
-                                ng-multiple="true"
-                                ng-model="selectedRealmDefRoles"
-                                ng-options="r for r in realm.defaultRoles | orderBy:'toString()'">
-                        </select>
-                        <button ng-disabled="selectedRealmDefRoles.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmDefaultRole()">
-                            <i class="fa fa-angle-double-left"></i> Remove selected
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <label class="col-md-2 control-label" class="control-label">
-                <span>Client Roles</span>
-                <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
-            </label>
-            <div class="col-md-10" data-ng-show="client">
-                <div class="row" data-ng-hide="client">
-                    <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
-                </div>
-                <div class="row" data-ng-show="client">
-                    <div class="col-md-4">
-                        <label class="control-label" for="available-client">Available Roles</label>
-                        <kc-tooltip>Roles from this client that are assignable as a default.</kc-tooltip>
-                        <select id="available-client" class="form-control" multiple size="5"
-                                ng-multiple="true"
-                                ng-model="selectedClientRoles"
-                                ng-options="r for r in availableClientRoles | orderBy:'toString()'">
-                        </select>
-                        <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientDefaultRole()">
-                            Add selected <i class="fa fa-angle-double-right"></i>
-                        </button>
-                    </div>
-                    <div class="col-md-4">
-                        <label class="control-label" for="assigned-client">Client Default Roles</label>
-                        <kc-tooltip>Roles from this client assigned as a default role.</kc-tooltip>
-                        <select id="assigned-client" class="form-control" multiple size=5
-                                ng-multiple="true"
-                                ng-model="selectedClientDefRoles"
-                                ng-options="r for r in client.defaultRoles | orderBy:'toString()'">
-                        </select>
-                        <button ng-disabled="selectedClientDefRoles.length == 0" class="btn btn-default" type="submit" ng-click="rmClientDefaultRole()">
-                            <i class="fa fa-angle-double-left"></i> Remove selected
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Roles</h1>
+
+    <ul class="nav nav-tabs">
+        <li><a href="#/realms/{{realm.realm}}/roles">Realm Roles</a></li>
+        <li class="active"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
+    </ul>
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <div class="form-group">
+            <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
+
+            <div class="col-md-10">
+                <div class="row">
+                    <div class="col-md-4">
+                        <label class="control-label" for="available">Available Roles</label>
+                        <kc-tooltip>Realm level roles that can be assigned.</kc-tooltip>
+                        <select id="available" class="form-control" multiple size="5"
+                                ng-multiple="true"
+                                ng-model="selectedRealmRoles"
+                                ng-options="r for r in availableRealmRoles | orderBy:'toString()'">
+                        </select>
+                        <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmDefaultRole()">
+                            Add selected <i class="fa fa-angle-double-right"></i>
+                        </button>
+                    </div>
+                    <div class="col-md-4">
+                        <label class="control-label" for="assigned">Realm Default Roles</label>
+                        <kc-tooltip>Realm level roles assigned to new users.</kc-tooltip>
+                        <select id="assigned" class="form-control" multiple size=5
+                                ng-multiple="true"
+                                ng-model="selectedRealmDefRoles"
+                                ng-options="r for r in realm.defaultRoles | orderBy:'toString()'">
+                        </select>
+                        <button ng-disabled="selectedRealmDefRoles.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmDefaultRole()">
+                            <i class="fa fa-angle-double-left"></i> Remove selected
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-md-2 control-label" class="control-label">
+                <span>Client Roles</span>
+                <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
+            </label>
+            <div class="col-md-10" data-ng-show="client">
+                <div class="row" data-ng-hide="client">
+                    <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
+                </div>
+                <div class="row" data-ng-show="client">
+                    <div class="col-md-4">
+                        <label class="control-label" for="available-client">Available Roles</label>
+                        <kc-tooltip>Roles from this client that are assignable as a default.</kc-tooltip>
+                        <select id="available-client" class="form-control" multiple size="5"
+                                ng-multiple="true"
+                                ng-model="selectedClientRoles"
+                                ng-options="r for r in availableClientRoles | orderBy:'toString()'">
+                        </select>
+                        <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientDefaultRole()">
+                            Add selected <i class="fa fa-angle-double-right"></i>
+                        </button>
+                    </div>
+                    <div class="col-md-4">
+                        <label class="control-label" for="assigned-client">Client Default Roles</label>
+                        <kc-tooltip>Roles from this client assigned as a default role.</kc-tooltip>
+                        <select id="assigned-client" class="form-control" multiple size=5
+                                ng-multiple="true"
+                                ng-model="selectedClientDefRoles"
+                                ng-options="r for r in client.defaultRoles | orderBy:'toString()'">
+                        </select>
+                        <button ng-disabled="selectedClientDefRoles.length == 0" class="btn btn-default" type="submit" ng-click="rmClientDefaultRole()">
+                            <i class="fa fa-angle-double-left"></i> Remove selected
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
index 67d7534..14ea2bc 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
@@ -1,38 +1,38 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1 data-ng-hide="createRealm">Settings</h1>
-    <h1 data-ng-show="createRealm">Add Realm</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal " name="realmForm" novalidate kc-read-only="!access.manageRealm">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="name"><span class="required">*</span> Name</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocus required>
-                </div>
-            </div>
-
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="enabled">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
-                </div>
-                <kc-tooltip>Users and clients can only access a realm if it's enabled</kc-tooltip>
-            </div>
-
-            <div class="form-group">
-                <div class="col-md-10 col-md-offset-2" data-ng-show="createRealm && access.manageRealm">
-                    <button kc-save data-ng-show="changed">Save</button>
-                    <button kc-cancel data-ng-click="cancel()">Cancel</button>
-                </div>
-
-                <div class="col-md-10 col-md-offset-2" data-ng-show="!createRealm && access.manageRealm">
-                    <button kc-save  data-ng-show="changed">Save</button>
-                    <button kc-reset data-ng-show="changed">Cancel</button>
-                    <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete Realm</button>
-                </div>
-            </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1 data-ng-hide="createRealm">Settings</h1>
+    <h1 data-ng-show="createRealm">Add Realm</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal " name="realmForm" novalidate kc-read-only="!access.manageRealm">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="name"><span class="required">*</span> Name</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocus required>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="enabled">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
+                </div>
+                <kc-tooltip>Users and clients can only access a realm if it's enabled</kc-tooltip>
+            </div>
+
+            <div class="form-group">
+                <div class="col-md-10 col-md-offset-2" data-ng-show="createRealm && access.manageRealm">
+                    <button kc-save data-ng-show="changed">Save</button>
+                    <button kc-cancel data-ng-click="cancel()">Cancel</button>
+                </div>
+
+                <div class="col-md-10 col-md-offset-2" data-ng-show="!createRealm && access.manageRealm">
+                    <button kc-save  data-ng-show="changed">Save</button>
+                    <button kc-reset data-ng-show="changed">Cancel</button>
+                    <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete Realm</button>
+                </div>
+            </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
index 4df17ba..8e7e1d3 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
@@ -1,125 +1,125 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>
-        <span>Events</span>
-        <kc-tooltip>Displays saved events for the realm. Events are related to user accounts, for example a user login. To enable persisted events go to config.</kc-tooltip>
-    </h1>
-
-    <ul class="nav nav-tabs">
-        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
-        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
-        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
-    </ul>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="4">
-                <div class="pull-right">
-                    <select data-ng-model="query.max" data-ng-click="update()" class="btn btn-default">
-                        <option>5</option>
-                        <option>10</option>
-                        <option>50</option>
-                        <option>100</option>
-                    </select>
-                    <button class="btn btn-default" data-ng-click="filter = !filter">
-                        <span class="glyphicon glyphicon-plus" data-ng-show="!filter"></span>
-                        <span class="glyphicon glyphicon-minus" data-ng-show="filter"></span>
-                        Filter
-                    </button>
-                    <button class="btn btn-default btn-default" data-ng-click="update()">Update</button>
-                    <button class="btn btn-default btn-default" data-ng-click="reset()">Reset</button>
-                </div>
-                <form class="form-horizontal">
-                    <div class="form-group" data-ng-show="filter">
-                <label class="col-md-2 control-label" for="eventTypes">Event Type</label>
-                        <div class="col-sm-5">
-                            <input ui-select2="eventSelectOptions" id="eventTypes" ng-model="query.type" data-placeholder="Select event types..."/>
-            </div>
-        </div>
-                    <div class="form-group" data-ng-show="filter">
-                        <label class="col-md-2 control-label" for="client">Client</label>
-                        <div class="col-md-6">
-                            <input class="form-control" type="text" id="client" name="client" data-ng-model="query.client">
-                        </div>
-                    </div>
-                    <div class="form-group" data-ng-show="filter">
-                        <label class="col-md-2 control-label" for="user">User</label>
-                        <div class="col-md-6">
-                            <input class="form-control" type="text" id="user" name="user" data-ng-model="query.user">
-                        </div>
-                    </div>
-
-                    <div class="form-group" data-ng-show="filter">
-                        <label class="col-md-2 control-label" for="dateFrom">Date (From)</label>
-                        <div class="col-md-6">
-                            <input class="form-control" type="text" id="dateFrom" name="dateFrom" data-ng-model="query.dateFrom" placeholder="yyyy-MM-dd">
-                        </div>
-                    </div>
-                    <div class="form-group" data-ng-show="filter">
-                        <label class="col-md-2 control-label" for="dateTo">Date (To)</label>
-                        <div class="col-md-6">
-                            <input class="form-control" type="text" id="dateTo" name="dateTo" data-ng-model="query.dateTo" placeholder="yyyy-MM-dd">
-                        </div>
-                    </div>
-
-                </form>
-            </th>
-        </tr>
-        <tr>
-            <th width="100px">Time</th>
-            <th width="180px">Event Type</th>
-            <th>Details</th>
-        </tr>
-        </thead>
-        <tfoot>
-        <tr>
-            <td colspan="7">
-                <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-double-left"></i></button>
-                <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-left"></i></button>
-                <button data-ng-click="nextPage()" class="next" ng-disabled="events.length < query.max"><i data-ng-class="events.length < query.max && 'text-muted'" class="fa fa-angle-right"></i></button>
-            </td>
-        </tr>
-        </tfoot>
-        <tbody>
-            <tr ng-repeat="event in events">
-                <td>{{event.time|date:'shortDate'}}<br>{{event.time|date:'mediumTime'}}</td>
-                <td>{{event.type}}</td>
-                <td>
-                    <table class="table table-striped table-bordered">
-                        <tr><td width="100px">Client</td><td>{{event.clientId}}</td></tr>
-                        <tr><td>User</td><td>{{event.userId}}</td></tr>
-                        <tr><td>IP Address</td><td>{{event.ipAddress}}</td></tr>
-                        <tr data-ng-show="event.error"><td>Error</td><td>{{event.error}}</td></tr>
-                        <tr>
-                            <td>Details</td>
-                            <td>
-                                <button type="button" class="btn btn-default btn-xs" ng-click="event.collapse = !event.collapse">
-                                    <span class="glyphicon glyphicon-plus" data-ng-show="!event.collapse"></span>
-                                    <span class="glyphicon glyphicon-minus" data-ng-show="event.collapse"></span>
-                                </button>
-                                <table data-ng-show="event.collapse" class="table table-striped table-bordered">
-                                    <tr ng-repeat="(key, value) in event.details">
-                                        <td>{{key}}</td>
-                                        <td>{{value}}</td>
-                                    </tr>
-                                </table>
-                            </td>
-                        </tr>
-                        <tr data-ng-show="event.representation">
-                            <td>Representation</td>
-                            <td>
-                                <button type="button" class="btn btn-default btn-xs" ng-click="collapseRep = !collapseRep">
-                                    <span class="glyphicon glyphicon-plus" data-ng-show="!collapseRep"></span>
-                                    <span class="glyphicon glyphicon-minus" data-ng-show="collapseRep"></span>
-                                </button>
-                                <pre data-ng-show="collapseRep">{{event.representation}}</pre>
-                            </td>
-                        </tr>
-                    </table>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>
+        <span>Events</span>
+        <kc-tooltip>Displays saved events for the realm. Events are related to user accounts, for example a user login. To enable persisted events go to config.</kc-tooltip>
+    </h1>
+
+    <ul class="nav nav-tabs">
+        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
+        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
+        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
+    </ul>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="4">
+                <div class="pull-right">
+                    <select data-ng-model="query.max" data-ng-click="update()" class="btn btn-default">
+                        <option>5</option>
+                        <option>10</option>
+                        <option>50</option>
+                        <option>100</option>
+                    </select>
+                    <button class="btn btn-default" data-ng-click="filter = !filter">
+                        <span class="glyphicon glyphicon-plus" data-ng-show="!filter"></span>
+                        <span class="glyphicon glyphicon-minus" data-ng-show="filter"></span>
+                        Filter
+                    </button>
+                    <button class="btn btn-default btn-default" data-ng-click="update()">Update</button>
+                    <button class="btn btn-default btn-default" data-ng-click="reset()">Reset</button>
+                </div>
+                <form class="form-horizontal">
+                    <div class="form-group" data-ng-show="filter">
+                <label class="col-md-2 control-label" for="eventTypes">Event Type</label>
+                        <div class="col-sm-5">
+                            <input ui-select2="eventSelectOptions" id="eventTypes" ng-model="query.type" data-placeholder="Select event types..."/>
+            </div>
+        </div>
+                    <div class="form-group" data-ng-show="filter">
+                        <label class="col-md-2 control-label" for="client">Client</label>
+                        <div class="col-md-6">
+                            <input class="form-control" type="text" id="client" name="client" data-ng-model="query.client">
+                        </div>
+                    </div>
+                    <div class="form-group" data-ng-show="filter">
+                        <label class="col-md-2 control-label" for="user">User</label>
+                        <div class="col-md-6">
+                            <input class="form-control" type="text" id="user" name="user" data-ng-model="query.user">
+                        </div>
+                    </div>
+
+                    <div class="form-group" data-ng-show="filter">
+                        <label class="col-md-2 control-label" for="dateFrom">Date (From)</label>
+                        <div class="col-md-6">
+                            <input class="form-control" type="text" id="dateFrom" name="dateFrom" data-ng-model="query.dateFrom" placeholder="yyyy-MM-dd">
+                        </div>
+                    </div>
+                    <div class="form-group" data-ng-show="filter">
+                        <label class="col-md-2 control-label" for="dateTo">Date (To)</label>
+                        <div class="col-md-6">
+                            <input class="form-control" type="text" id="dateTo" name="dateTo" data-ng-model="query.dateTo" placeholder="yyyy-MM-dd">
+                        </div>
+                    </div>
+
+                </form>
+            </th>
+        </tr>
+        <tr>
+            <th width="100px">Time</th>
+            <th width="180px">Event Type</th>
+            <th>Details</th>
+        </tr>
+        </thead>
+        <tfoot>
+        <tr>
+            <td colspan="7">
+                <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-double-left"></i></button>
+                <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-left"></i></button>
+                <button data-ng-click="nextPage()" class="next" ng-disabled="events.length < query.max"><i data-ng-class="events.length < query.max && 'text-muted'" class="fa fa-angle-right"></i></button>
+            </td>
+        </tr>
+        </tfoot>
+        <tbody>
+            <tr ng-repeat="event in events">
+                <td>{{event.time|date:'shortDate'}}<br>{{event.time|date:'mediumTime'}}</td>
+                <td>{{event.type}}</td>
+                <td>
+                    <table class="table table-striped table-bordered">
+                        <tr><td width="100px">Client</td><td>{{event.clientId}}</td></tr>
+                        <tr><td>User</td><td>{{event.userId}}</td></tr>
+                        <tr><td>IP Address</td><td>{{event.ipAddress}}</td></tr>
+                        <tr data-ng-show="event.error"><td>Error</td><td>{{event.error}}</td></tr>
+                        <tr>
+                            <td>Details</td>
+                            <td>
+                                <button type="button" class="btn btn-default btn-xs" ng-click="event.collapse = !event.collapse">
+                                    <span class="glyphicon glyphicon-plus" data-ng-show="!event.collapse"></span>
+                                    <span class="glyphicon glyphicon-minus" data-ng-show="event.collapse"></span>
+                                </button>
+                                <table data-ng-show="event.collapse" class="table table-striped table-bordered">
+                                    <tr ng-repeat="(key, value) in event.details">
+                                        <td>{{key}}</td>
+                                        <td>{{value}}</td>
+                                    </tr>
+                                </table>
+                            </td>
+                        </tr>
+                        <tr data-ng-show="event.representation">
+                            <td>Representation</td>
+                            <td>
+                                <button type="button" class="btn btn-default btn-xs" ng-click="collapseRep = !collapseRep">
+                                    <span class="glyphicon glyphicon-plus" data-ng-show="!collapseRep"></span>
+                                    <span class="glyphicon glyphicon-minus" data-ng-show="collapseRep"></span>
+                                </button>
+                                <pre data-ng-show="collapseRep">{{event.representation}}</pre>
+                            </td>
+                        </tr>
+                    </table>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
index 1598ea5..b18ac03 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
@@ -1,127 +1,127 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>
-        <span>Admin Events</span>
-        <kc-tooltip>Displays saved admin events for the realm. Events are related to admin account, for example a realm creation. To enable persisted events go to config.</kc-tooltip>
-    </h1>
-    
-    <ul class="nav nav-tabs">
-        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
-        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
-        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
-    </ul>
-    <h2></h2>
-
-    <div id="content">
-        <table class="table table-striped table-bordered">
-            <thead>
-            <tr>
-                <th class="kc-table-actions" colspan="5">
-                    <div class="pull-right">
-                        <select data-ng-model="query.max" data-ng-click="update()" class="btn btn-default">
-                            <option>5</option>
-                            <option>10</option>
-                            <option>50</option>
-                            <option>100</option>
-                        </select>
-                        <button class="btn btn-default" data-ng-click="filter = !filter">
-                            <span class="glyphicon glyphicon-plus" data-ng-show="!filter"></span>
-                            <span class="glyphicon glyphicon-minus" data-ng-show="filter"></span>
-                            Filter
-                        </button>
-                        <button class="btn btn-default btn-default" data-ng-click="update()">Update</button>
-                        <button class="btn btn-default btn-default" data-ng-click="reset()">Reset</button>
-                    </div>
-                    <form class="form-horizontal" data-ng-show="filter">
-                        <div class="form-group">
-      			            <label class="col-sm-2 control-label" for="adminEnabledEventOperations">Operation Types</label>
-                    	    <div class="col-sm-5">
-                                <input ui-select2="adminEnabledEventOperationsOptions" id="adminEnabledEventOperations" ng-model="query.operationTypes" data-placeholder="Select operations..."/>
-			                </div>
-			            </div>
-                        <div class="form-group">
-                            <label class="col-sm-2 control-label" for="resource">Resource Path</label>
-                            <div class="col-sm-4">
-                                <input class="form-control" type="text" id="resource" name="resource" data-ng-model="query.resourcePath">
-                            </div>
-                            <span tooltip-placement="right" tooltip="Filter by resource path. Supports wildcards '*' to match a single part of the path and '**' matches multiple parts. For example 'realms/*/clients/asbc' matches client with id asbc in any realm, while or 'realms/master/**' matches anything in the master realm." class="fa fa-info-circle"></span>
-                        </div>
-                        <div class="form-group">
-                            <label class="col-sm-2 control-label" for="dateFrom">Date (From)</label>
-                            <div class="col-sm-4">
-                                <input class="form-control" type="text" id="dateFrom" name="dateFrom" data-ng-model="query.dateFrom"  placeholder="yyyy-MM-dd">
-                            </div>
-                        </div>
-                        <div class="form-group">
-                            <label class="col-sm-2 control-label" for="dateTo">Date (To)</label>
-                            <div class="col-sm-4">
-                                <input class="form-control" type="text" id="dateTo" name="dateTo" data-ng-model="query.dateTo"  placeholder="yyyy-MM-dd">
-                            </div>
-                        </div>
-
-                        <fieldset>
-                            <legend><span class="text">Authentication Details</span></legend>
-
-                            <div class="form-group">
-                                <label class="col-sm-2 control-label" for="realm">Realm</label>
-                                <div class="col-sm-4">
-                                    <input class="form-control" type="text" id="realm" name="realm" data-ng-model="query.authRealm">
-                                </div>
-                            </div>
-                            <div class="form-group">
-                                <label class="col-sm-2 control-label" for="client">Client</label>
-                                <div class="col-sm-4">
-                                    <input class="form-control" type="text" id="client" name="client" data-ng-model="query.authClient">
-                                </div>
-                            </div>
-                            <div class="form-group">
-                                <label class="col-sm-2 control-label" for="user">User</label>
-                                <div class="col-sm-4">
-                                    <input class="form-control" type="text" id="user" name="user" data-ng-model="query.authUser">
-                                </div>
-                            </div>
-                            <div class="form-group">
-                                <label class="col-sm-2 control-label" for="ipAddress">IP Address</label>
-                                <div class="col-sm-4">
-                                    <input class="form-control" type="text" id="ipAddress" name="ipAddress" data-ng-model="query.authIpAddress">
-                                </div>
-                            </div>
-                        </fieldset>
-
-                    </form>
-                </th>
-            </tr>
-            <tr>
-                <th width="100px">Time</th>
-                <th width="180px">Operation Type</th>
-                <th width="180px">Resource Path</th>
-                <th>Details</th>
-            </tr>
-            </thead>
-            <tfoot>
-            <tr>
-            	<td colspan="7">
-                	<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-double-left"></i></button>
-                	<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-left"></i></button>
-                	<button data-ng-click="nextPage()" class="next" ng-disabled="events.length < query.max"><i data-ng-class="events.length < query.max && 'text-muted'" class="fa fa-angle-right"></i></button>
-            	</td>
-            </tr>
-            </tfoot>
-            <tbody>
-                <tr data-ng-repeat="event in events">
-                    <td>{{event.time|date:'shortDate'}}<br>{{event.time|date:'mediumTime'}}</td>
-                    <td data-ng-class="events-error">{{event.operationType}}</td>
-                    <td>{{event.resourcePath}}</td>
-                    <td>
-                        <button type="button" class="btn btn-default btn-xs" data-ng-click="viewAuth(event)">
-                            Auth
-                        </button>
-                        <button type="button" class="btn btn-default btn-xs" data-ng-click="viewRepresentation(event)" data-ng-show="event.representation">
-                            Representation
-                        </button>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
-    </div>
-</div>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>
+        <span>Admin Events</span>
+        <kc-tooltip>Displays saved admin events for the realm. Events are related to admin account, for example a realm creation. To enable persisted events go to config.</kc-tooltip>
+    </h1>
+    
+    <ul class="nav nav-tabs">
+        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
+        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
+        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
+    </ul>
+    <h2></h2>
+
+    <div id="content">
+        <table class="table table-striped table-bordered">
+            <thead>
+            <tr>
+                <th class="kc-table-actions" colspan="5">
+                    <div class="pull-right">
+                        <select data-ng-model="query.max" data-ng-click="update()" class="btn btn-default">
+                            <option>5</option>
+                            <option>10</option>
+                            <option>50</option>
+                            <option>100</option>
+                        </select>
+                        <button class="btn btn-default" data-ng-click="filter = !filter">
+                            <span class="glyphicon glyphicon-plus" data-ng-show="!filter"></span>
+                            <span class="glyphicon glyphicon-minus" data-ng-show="filter"></span>
+                            Filter
+                        </button>
+                        <button class="btn btn-default btn-default" data-ng-click="update()">Update</button>
+                        <button class="btn btn-default btn-default" data-ng-click="reset()">Reset</button>
+                    </div>
+                    <form class="form-horizontal" data-ng-show="filter">
+                        <div class="form-group">
+      			            <label class="col-sm-2 control-label" for="adminEnabledEventOperations">Operation Types</label>
+                    	    <div class="col-sm-5">
+                                <input ui-select2="adminEnabledEventOperationsOptions" id="adminEnabledEventOperations" ng-model="query.operationTypes" data-placeholder="Select operations..."/>
+			                </div>
+			            </div>
+                        <div class="form-group">
+                            <label class="col-sm-2 control-label" for="resource">Resource Path</label>
+                            <div class="col-sm-4">
+                                <input class="form-control" type="text" id="resource" name="resource" data-ng-model="query.resourcePath">
+                            </div>
+                            <span tooltip-placement="right" tooltip="Filter by resource path. Supports wildcards '*' to match a single part of the path and '**' matches multiple parts. For example 'realms/*/clients/asbc' matches client with id asbc in any realm, while or 'realms/master/**' matches anything in the master realm." class="fa fa-info-circle"></span>
+                        </div>
+                        <div class="form-group">
+                            <label class="col-sm-2 control-label" for="dateFrom">Date (From)</label>
+                            <div class="col-sm-4">
+                                <input class="form-control" type="text" id="dateFrom" name="dateFrom" data-ng-model="query.dateFrom"  placeholder="yyyy-MM-dd">
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <label class="col-sm-2 control-label" for="dateTo">Date (To)</label>
+                            <div class="col-sm-4">
+                                <input class="form-control" type="text" id="dateTo" name="dateTo" data-ng-model="query.dateTo"  placeholder="yyyy-MM-dd">
+                            </div>
+                        </div>
+
+                        <fieldset>
+                            <legend><span class="text">Authentication Details</span></legend>
+
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label" for="realm">Realm</label>
+                                <div class="col-sm-4">
+                                    <input class="form-control" type="text" id="realm" name="realm" data-ng-model="query.authRealm">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label" for="client">Client</label>
+                                <div class="col-sm-4">
+                                    <input class="form-control" type="text" id="client" name="client" data-ng-model="query.authClient">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label" for="user">User</label>
+                                <div class="col-sm-4">
+                                    <input class="form-control" type="text" id="user" name="user" data-ng-model="query.authUser">
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="col-sm-2 control-label" for="ipAddress">IP Address</label>
+                                <div class="col-sm-4">
+                                    <input class="form-control" type="text" id="ipAddress" name="ipAddress" data-ng-model="query.authIpAddress">
+                                </div>
+                            </div>
+                        </fieldset>
+
+                    </form>
+                </th>
+            </tr>
+            <tr>
+                <th width="100px">Time</th>
+                <th width="180px">Operation Type</th>
+                <th width="180px">Resource Path</th>
+                <th>Details</th>
+            </tr>
+            </thead>
+            <tfoot>
+            <tr>
+            	<td colspan="7">
+                	<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-double-left"></i></button>
+                	<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0"><i data-ng-class="query.first == 0 && 'text-muted'" class="fa fa-angle-left"></i></button>
+                	<button data-ng-click="nextPage()" class="next" ng-disabled="events.length < query.max"><i data-ng-class="events.length < query.max && 'text-muted'" class="fa fa-angle-right"></i></button>
+            	</td>
+            </tr>
+            </tfoot>
+            <tbody>
+                <tr data-ng-repeat="event in events">
+                    <td>{{event.time|date:'shortDate'}}<br>{{event.time|date:'mediumTime'}}</td>
+                    <td data-ng-class="events-error">{{event.operationType}}</td>
+                    <td>{{event.resourcePath}}</td>
+                    <td>
+                        <button type="button" class="btn btn-default btn-xs" data-ng-click="viewAuth(event)">
+                            Auth
+                        </button>
+                        <button type="button" class="btn btn-default btn-xs" data-ng-click="viewRepresentation(event)" data-ng-show="event.representation">
+                            Representation
+                        </button>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
index 06cd18a..a0fe367 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
@@ -1,114 +1,114 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>
-        <span>Events Config</span>
-        <kc-tooltip>Displays configuration options to enable persistence of user and admin events.</kc-tooltip>
-    </h1>
-
-    <ul class="nav nav-tabs">
-        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
-        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
-        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
-    </ul>
-    <div id="content">
-        <h2>Events Config</h2>
-
-        <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageEvents">
-
-            <fieldset class="border-top">
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="eventsListeners" class="control-label">Event Listeners</label>
-
-                    <div class="col-md-6">
-                        <select ui-select2 ng-model="eventsConfig.eventsListeners" data-placeholder="Select an action..." multiple>
-                            <option ng-repeat="listener in eventListeners" value="{{listener}}">{{listener}}</option>
-                        </select>
-                    </div>
-
-                    <span tooltip-placement="right" tooltip="Configure what listeners receive events for the realm." class="fa fa-info-circle"></span>
-                </div>
-            </fieldset>
-
-            <fieldset>
-                <legend><span class="text">Login Events Settings</span></legend>
-
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="enabled">Save Events</label>
-                    <div class="col-md-6">
-                        <input ng-model="eventsConfig.eventsEnabled" name="enabled" id="enabled" onoffswitch />
-                    </div>
-                    <span tooltip-placement="right" tooltip="If enabled login events are saved to the database which makes events available to the admin and account management consoles." class="fa fa-info-circle"></span>
-                </div>
-
-                <div class="form-group" data-ng-show="eventsConfig.eventsEnabled">
-                    <label class="col-md-2 control-label" for="enabledEventTypes" class="control-label">Saved Types</label>
-
-                    <div class="col-md-6">
-                        <input ui-select2="eventSelectOptions" id="enabledEventTypes" ng-model="eventsConfig.enabledEventTypes" data-placeholder="Select event types..."/>
-                    </div>
-
-                    <span tooltip-placement="right" tooltip="Configure what event types are saved. By default events related to login and users modifying their accounts are persisted." class="fa fa-info-circle"></span>
-                </div>
-
-                <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.eventsEnabled">
-                    <label class="col-md-2 control-label" for="password">Clear Events</label>
-                    <div class="col-md-6">
-                        <button class="btn btn-danger" type="submit" data-ng-click="clearEvents()" >Clear Events</button>
-                    </div>
-                    <span tooltip-placement="right" tooltip="Deletes all events in the database." class="fa fa-info-circle"></span>
-                </div>
-                <div class="form-group input-select" data-ng-show="eventsConfig.eventsEnabled">
-                    <label class="col-md-2 control-label" for="expiration">Expiration</label>
-                    <div class="col-md-6">
-                        <input class="form-control" type="number" data-ng-model="eventsConfig.eventsExpiration" id="expiration" name="expiration" min="0"/>
-                    </div>
-                    <div class="col-md-2 select-kc">
-                        <select name="expirationUnit" data-ng-model="eventsConfig.expirationUnit" >
-                            <option>Minutes</option>
-                            <option>Hours</option>
-                            <option>Days</option>
-                        </select>
-                    <span tooltip-placement="right" tooltip="Sets the expiration for events. Expired events are periodically deleted from the database." class="fa fa-info-circle"></span>
-                    </div>
-                </div>
-            </fieldset>
-
-
-            <fieldset>
-                <legend><span class="text">Admin Events Settings</span></legend>
-
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="adminEventsEnabled">Save Events</label>
-                    <div class="col-md-6">
-                        <input ng-model="eventsConfig.adminEventsEnabled" name="adminEventsEnabled" id="adminEventsEnabled" onoffswitch />
-                    </div>
-
-                    <span tooltip-placement="right" tooltip="If enabled admin events are saved to the database which makes events available to the admin console." class="fa fa-info-circle"></span>
-                </div>
-
-                <div class="form-group" data-ng-show="eventsConfig.adminEventsEnabled">
-                    <label class="col-md-2 control-label" for="adminEventsDetailsEnabled">Include Representation</label>
-                    <div class="col-md-6">
-                        <input ng-model="eventsConfig.adminEventsDetailsEnabled" name="adminEventsDetailsEnabled" id="adminEventsDetailsEnabled" onoffswitch />
-                    </div>
-
-                    <span tooltip-placement="right" tooltip="Include JSON representation for create and update requests." class="fa fa-info-circle"></span>
-                </div>
-                
-                <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.adminEventsEnabled">
-                    <label class="col-md-2 control-label" for="password">Clear Admin Events</label>
-                    <div class="col-md-6">
-                        <button class="btn btn-danger" type="submit" data-ng-click="clearAdminEvents()" >Clear Admin Events</button>
-                    </div>
-                    <span tooltip-placement="right" tooltip="Deletes all admin events in the database." class="fa fa-info-circle"></span>
-                </div>
-                
-            </fieldset>
-
-                <div class="pull-right form-actions" data-ng-show="access.manageEvents">
-                <button data-kc-reset data-ng-show="changed">Clear changes</button>
-                <button data-kc-save data-ng-show="changed">Save</button>
-            </div>
-        </form>
-    </div>
-</div>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>
+        <span>Events Config</span>
+        <kc-tooltip>Displays configuration options to enable persistence of user and admin events.</kc-tooltip>
+    </h1>
+
+    <ul class="nav nav-tabs">
+        <li data-ng-class="(path[2] == 'events') && 'active'"><a href="#/realms/{{realm.realm}}/events">Login Events</a></li>
+        <li data-ng-class="(path[2] == 'admin-events') && 'active'"><a href="#/realms/{{realm.realm}}/admin-events">Admin Events</a></li>
+        <li data-ng-class="(path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events-settings">Config</a></li>
+    </ul>
+    <div id="content">
+        <h2>Events Config</h2>
+
+        <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageEvents">
+
+            <fieldset class="border-top">
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="eventsListeners" class="control-label">Event Listeners</label>
+
+                    <div class="col-md-6">
+                        <select ui-select2 ng-model="eventsConfig.eventsListeners" data-placeholder="Select an action..." multiple>
+                            <option ng-repeat="listener in eventListeners" value="{{listener}}">{{listener}}</option>
+                        </select>
+                    </div>
+
+                    <span tooltip-placement="right" tooltip="Configure what listeners receive events for the realm." class="fa fa-info-circle"></span>
+                </div>
+            </fieldset>
+
+            <fieldset>
+                <legend><span class="text">Login Events Settings</span></legend>
+
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="enabled">Save Events</label>
+                    <div class="col-md-6">
+                        <input ng-model="eventsConfig.eventsEnabled" name="enabled" id="enabled" onoffswitch />
+                    </div>
+                    <span tooltip-placement="right" tooltip="If enabled login events are saved to the database which makes events available to the admin and account management consoles." class="fa fa-info-circle"></span>
+                </div>
+
+                <div class="form-group" data-ng-show="eventsConfig.eventsEnabled">
+                    <label class="col-md-2 control-label" for="enabledEventTypes" class="control-label">Saved Types</label>
+
+                    <div class="col-md-6">
+                        <input ui-select2="eventSelectOptions" id="enabledEventTypes" ng-model="eventsConfig.enabledEventTypes" data-placeholder="Select event types..."/>
+                    </div>
+
+                    <span tooltip-placement="right" tooltip="Configure what event types are saved. By default events related to login and users modifying their accounts are persisted." class="fa fa-info-circle"></span>
+                </div>
+
+                <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.eventsEnabled">
+                    <label class="col-md-2 control-label" for="password">Clear Events</label>
+                    <div class="col-md-6">
+                        <button class="btn btn-danger" type="submit" data-ng-click="clearEvents()" >Clear Events</button>
+                    </div>
+                    <span tooltip-placement="right" tooltip="Deletes all events in the database." class="fa fa-info-circle"></span>
+                </div>
+                <div class="form-group input-select" data-ng-show="eventsConfig.eventsEnabled">
+                    <label class="col-md-2 control-label" for="expiration">Expiration</label>
+                    <div class="col-md-6">
+                        <input class="form-control" type="number" data-ng-model="eventsConfig.eventsExpiration" id="expiration" name="expiration" min="0"/>
+                    </div>
+                    <div class="col-md-2 select-kc">
+                        <select name="expirationUnit" data-ng-model="eventsConfig.expirationUnit" >
+                            <option>Minutes</option>
+                            <option>Hours</option>
+                            <option>Days</option>
+                        </select>
+                    <span tooltip-placement="right" tooltip="Sets the expiration for events. Expired events are periodically deleted from the database." class="fa fa-info-circle"></span>
+                    </div>
+                </div>
+            </fieldset>
+
+
+            <fieldset>
+                <legend><span class="text">Admin Events Settings</span></legend>
+
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="adminEventsEnabled">Save Events</label>
+                    <div class="col-md-6">
+                        <input ng-model="eventsConfig.adminEventsEnabled" name="adminEventsEnabled" id="adminEventsEnabled" onoffswitch />
+                    </div>
+
+                    <span tooltip-placement="right" tooltip="If enabled admin events are saved to the database which makes events available to the admin console." class="fa fa-info-circle"></span>
+                </div>
+
+                <div class="form-group" data-ng-show="eventsConfig.adminEventsEnabled">
+                    <label class="col-md-2 control-label" for="adminEventsDetailsEnabled">Include Representation</label>
+                    <div class="col-md-6">
+                        <input ng-model="eventsConfig.adminEventsDetailsEnabled" name="adminEventsDetailsEnabled" id="adminEventsDetailsEnabled" onoffswitch />
+                    </div>
+
+                    <span tooltip-placement="right" tooltip="Include JSON representation for create and update requests." class="fa fa-info-circle"></span>
+                </div>
+                
+                <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.adminEventsEnabled">
+                    <label class="col-md-2 control-label" for="password">Clear Admin Events</label>
+                    <div class="col-md-6">
+                        <button class="btn btn-danger" type="submit" data-ng-click="clearAdminEvents()" >Clear Admin Events</button>
+                    </div>
+                    <span tooltip-placement="right" tooltip="Deletes all admin events in the database." class="fa fa-info-circle"></span>
+                </div>
+                
+            </fieldset>
+
+                <div class="pull-right form-actions" data-ng-show="access.manageEvents">
+                <button data-kc-reset data-ng-show="changed">Clear changes</button>
+                <button data-kc-save data-ng-show="changed">Save</button>
+            </div>
+        </form>
+    </div>
+</div>
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
index 3d82adc..5f6c0a3 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
@@ -1,45 +1,45 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Identity Providers</h1>
-
-    <form name="realmForm" novalidate class="form-horizontal">
-        <fieldset>
-            <div>
-                <table class="table table-striped table-bordered">
-                    <caption class="hidden">Table of identity providers</caption>
-                    <thead>
-                    <tr>
-                        <th colspan="4" class="kc-table-actions">
-                            <div class="dropdown pull-right">
-                                <select class="form-control" ng-model="provider"
-                                        ng-options="p.name group by p.groupName for p in allProviders track by p.id"
-                                        data-ng-change="addProvider(provider); provider = null">
-                                    <option value="" disabled selected>Add provider...</option>
-                                </select>
-                            </div>
-                        </th>
-                    </tr>
-                    <tr ng-show="configuredProviders.length > 0">
-                        <th>Name</th>
-                        <th>Provider</th>
-                        <th>Enabled</th>
-                        <th width="15%">GUI order</th>
-                    </tr>
-                    </thead>
-                    <tbody ng-show="configuredProviders.length > 0">
-                    <tr ng-repeat="identityProvider in configuredProviders">
-                        <td>
-                            <a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a>
-                        </td>
-                        <td>{{identityProvider.providerId}}</td>
-                        <td>{{identityProvider.enabled}}</td>
-                        <td>{{identityProvider.config.guiOrder}}</td>
-                    </tr>
-                    </tbody>
-                </table>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Identity Providers</h1>
+
+    <form name="realmForm" novalidate class="form-horizontal">
+        <fieldset>
+            <div>
+                <table class="table table-striped table-bordered">
+                    <caption class="hidden">Table of identity providers</caption>
+                    <thead>
+                    <tr>
+                        <th colspan="4" class="kc-table-actions">
+                            <div class="dropdown pull-right">
+                                <select class="form-control" ng-model="provider"
+                                        ng-options="p.name group by p.groupName for p in allProviders track by p.id"
+                                        data-ng-change="addProvider(provider); provider = null">
+                                    <option value="" disabled selected>Add provider...</option>
+                                </select>
+                            </div>
+                        </th>
+                    </tr>
+                    <tr ng-show="configuredProviders.length > 0">
+                        <th>Name</th>
+                        <th>Provider</th>
+                        <th>Enabled</th>
+                        <th width="15%">GUI order</th>
+                    </tr>
+                    </thead>
+                    <tbody ng-show="configuredProviders.length > 0">
+                    <tr ng-repeat="identityProvider in configuredProviders">
+                        <td>
+                            <a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a>
+                        </td>
+                        <td>{{identityProvider.providerId}}</td>
+                        <td>{{identityProvider.enabled}}</td>
+                        <td>{{identityProvider.config.guiOrder}}</td>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-export.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-export.html
index 37302a2..c79b92b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-export.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-export.html
@@ -1,28 +1,28 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li>{{identityProvider.alias}}</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}</h1>
-    <h1 data-ng-show="create">Add OpenID Connect Identity Provider</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
-        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider">Export</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset class="border-top">
-            <div class="form-group">
-                <div class="col-sm-12">
-                    <a class="btn btn-primary" data-ng-click="download()" type="submit">Download</a>
-                    <textarea class="form-control" rows="20" kc-select-action="click">{{exported}}</textarea>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li>{{identityProvider.alias}}</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}</h1>
+    <h1 data-ng-show="create">Add OpenID Connect Identity Provider</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
+        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider">Export</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset class="border-top">
+            <div class="form-group">
+                <div class="col-sm-12">
+                    <a class="btn btn-primary" data-ng-click="download()" type="submit">Download</a>
+                    <textarea class="form-control" rows="20" kc-select-action="click">{{exported}}</textarea>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 5a18cc2..2fad5c9 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -1,228 +1,228 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li>{{identityProvider.alias}}</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
-    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add OpenID Connect Identity Provider</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
-        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
-                </div>
-                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="identifier"><span class="required">*</span> Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="identifier" type="text" ng-model="identityProvider.alias" data-ng-readonly="!newIdentityProvider" required>
-                </div>
-                <kc-tooltip>The alias unique identifies an identity provider and it is also used to build the redirect uri.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="enabled">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
-                </div>
-                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storeToken">Store Tokens</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">On</option>
-                            <option value="missing">On missing info</option>
-                            <option value="off">Off</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
-                </div>
-                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset>
-            <legend uncollapsed><span class="text">OpenID Connect Config</span> <kc-tooltip>OIDC SP and external IDP configuration.</kc-tooltip></legend>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="authorizationUrl"><span class="required">*</span> Authorization Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="authorizationUrl" type="text" ng-model="identityProvider.config.authorizationUrl" required>
-                </div>
-                <kc-tooltip>The Authorization Url.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="tokenUrl"><span class="required">*</span> Token Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="tokenUrl" type="text" ng-model="identityProvider.config.tokenUrl" required>
-                </div>
-                <kc-tooltip>The Token Url.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="userInfoUrl">Logout Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="logoutUrl" type="text" ng-model="identityProvider.config.logoutUrl">
-                </div>
-                <kc-tooltip>End session endpoint to use to logout user from external IDP.</kc-tooltip>
-            </div>
-                    <div class="form-group">
-                        <label class="col-sm-2 control-label" for="backchannelSupported">Backchannel Logout</label>
-                        <div class="col-sm-4">
-                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" value="'true'" onoffswitchvalue />
-                        </div>
-                        <span tooltip-placement="right" tooltip="Does the external IDP support backchannel logout?" class="fa fa-info-circle"></span>
-                    </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="userInfoUrl">User Info Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="userInfoUrl" type="text" ng-model="identityProvider.config.userInfoUrl">
-                </div>
-                <kc-tooltip>The User Info Url.  This is optional.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="clientId"><span class="required">*</span> Client ID</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
-                </div>
-                <kc-tooltip>The client or client identifier registered withing the identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="clientSecret"><span class="required">*</span> Client Secret</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="clientSecret" type="password" ng-model="identityProvider.config.clientSecret" ng-show="hidePassword" required>
-                    <input class="form-control" id="clientSecret" type="text" ng-model="identityProvider.config.clientSecret" ng-show="!hidePassword" required>
-                    <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
-                    <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
-                </div>
-                <kc-tooltip>The client or client secret registered withing the identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="issuer">Issuer </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="issuer" type="text" ng-model="identityProvider.config.issuer">
-                </div>
-                <kc-tooltip>The issuer identifier for the issuer of the response. If not provided, no validation will be performed.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="defaultScope">Default Scopes </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="defaultScope" type="text" ng-model="identityProvider.config.defaultScope">
-                </div>
-                <kc-tooltip>The scopes to be sent when asking for authorization. It can be a space-separated list of scopes. Defaults to 'openid'.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="prompt">Prompt</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="prompt" ng-model="identityProvider.config.prompt">
-                            <option value="">unspecified</option>
-                            <option value="none">none</option>
-                            <option>consent</option>
-                            <option>login</option>
-                            <option>select_account</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Specifies whether the Authorization Server prompts the End-User for reauthentication and consent.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="validateSignature">Validate Signatures</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.validateSignature" id="validateSignature" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip>Enable/disable signature validation of external IDP signatures.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="identityProvider.config.validateSignature == 'true'">
-                <label class="col-md-2 control-label" for="publicKeySignatureVerifier">Validating Public Key</label>
-                <div class="col-md-6">
-                    <textarea class="form-control" id="publicKeySignatureVerifier" ng-model="identityProvider.config.publicKeySignatureVerifier"/>
-                </div>
-                <kc-tooltip>The public key in PEM format that must be used to verify external IDP signatures.</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset data-ng-show="newIdentityProvider">
-            <legend uncollapsed><span class="text">Import External IDP Config</span> <kc-tooltip>Allows you to load external IDP metadata from a config file or to download it from a URL.</kc-tooltip></legend>
-            <div class="form-group" data-ng-show="newIdentityProvider">
-                <label class="col-md-2 control-label" for="fromUrl">Import From Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="fromUrl" type="text" ng-model="fromUrl.data">
-                </div>
-                <kc-tooltip>Import metadata from a remote IDP discovery descriptor.</kc-tooltip>
-                <div class="col-md-6" data-ng-show="importUrl">
-                    <button type="submit" data-ng-click="importFrom()" data-ng-show="importUrl" class="btn btn-primary">Import</button>
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="newIdentityProvider">
-                <label class="col-md-2 control-label">Import From File</label>
-                <kc-tooltip>Import metadata from a downloaded IDP discovery descriptor.</kc-tooltip>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
-                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
-                    </div>
-                <span class="kc-uploaded-file" data-ng-show="files.length > 0">
-                    {{files[0].name}}
-                </span>
-                </div>
-                <div class="col-md-6" data-ng-show="importFile">
-                    <button type="submit" data-ng-click="uploadFile()" data-ng-show="importFile" class="btn btn-primary">Import</button>
-                </div>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li>{{identityProvider.alias}}</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
+    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add OpenID Connect Identity Provider</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
+        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
+                </div>
+                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="identifier"><span class="required">*</span> Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="identifier" type="text" ng-model="identityProvider.alias" data-ng-readonly="!newIdentityProvider" required>
+                </div>
+                <kc-tooltip>The alias unique identifies an identity provider and it is also used to build the redirect uri.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="enabled">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
+                </div>
+                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storeToken">Store Tokens</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
+                <div class="col-md-2">
+                		<div>
+                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
+                            <option value="on">On</option>
+                            <option value="missing">On missing info</option>
+                            <option value="off">Off</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                </div>
+                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset>
+            <legend uncollapsed><span class="text">OpenID Connect Config</span> <kc-tooltip>OIDC SP and external IDP configuration.</kc-tooltip></legend>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="authorizationUrl"><span class="required">*</span> Authorization Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="authorizationUrl" type="text" ng-model="identityProvider.config.authorizationUrl" required>
+                </div>
+                <kc-tooltip>The Authorization Url.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="tokenUrl"><span class="required">*</span> Token Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="tokenUrl" type="text" ng-model="identityProvider.config.tokenUrl" required>
+                </div>
+                <kc-tooltip>The Token Url.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="userInfoUrl">Logout Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="logoutUrl" type="text" ng-model="identityProvider.config.logoutUrl">
+                </div>
+                <kc-tooltip>End session endpoint to use to logout user from external IDP.</kc-tooltip>
+            </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="backchannelSupported">Backchannel Logout</label>
+                        <div class="col-sm-4">
+                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" value="'true'" onoffswitchvalue />
+                        </div>
+                        <span tooltip-placement="right" tooltip="Does the external IDP support backchannel logout?" class="fa fa-info-circle"></span>
+                    </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="userInfoUrl">User Info Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="userInfoUrl" type="text" ng-model="identityProvider.config.userInfoUrl">
+                </div>
+                <kc-tooltip>The User Info Url.  This is optional.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="clientId"><span class="required">*</span> Client ID</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
+                </div>
+                <kc-tooltip>The client or client identifier registered withing the identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="clientSecret"><span class="required">*</span> Client Secret</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="clientSecret" type="password" ng-model="identityProvider.config.clientSecret" ng-show="hidePassword" required>
+                    <input class="form-control" id="clientSecret" type="text" ng-model="identityProvider.config.clientSecret" ng-show="!hidePassword" required>
+                    <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
+                    <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
+                </div>
+                <kc-tooltip>The client or client secret registered withing the identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="issuer">Issuer </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="issuer" type="text" ng-model="identityProvider.config.issuer">
+                </div>
+                <kc-tooltip>The issuer identifier for the issuer of the response. If not provided, no validation will be performed.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="defaultScope">Default Scopes </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="defaultScope" type="text" ng-model="identityProvider.config.defaultScope">
+                </div>
+                <kc-tooltip>The scopes to be sent when asking for authorization. It can be a space-separated list of scopes. Defaults to 'openid'.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="prompt">Prompt</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="prompt" ng-model="identityProvider.config.prompt">
+                            <option value="">unspecified</option>
+                            <option value="none">none</option>
+                            <option>consent</option>
+                            <option>login</option>
+                            <option>select_account</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Specifies whether the Authorization Server prompts the End-User for reauthentication and consent.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="validateSignature">Validate Signatures</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.validateSignature" id="validateSignature" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip>Enable/disable signature validation of external IDP signatures.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="identityProvider.config.validateSignature == 'true'">
+                <label class="col-md-2 control-label" for="publicKeySignatureVerifier">Validating Public Key</label>
+                <div class="col-md-6">
+                    <textarea class="form-control" id="publicKeySignatureVerifier" ng-model="identityProvider.config.publicKeySignatureVerifier"/>
+                </div>
+                <kc-tooltip>The public key in PEM format that must be used to verify external IDP signatures.</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset data-ng-show="newIdentityProvider">
+            <legend uncollapsed><span class="text">Import External IDP Config</span> <kc-tooltip>Allows you to load external IDP metadata from a config file or to download it from a URL.</kc-tooltip></legend>
+            <div class="form-group" data-ng-show="newIdentityProvider">
+                <label class="col-md-2 control-label" for="fromUrl">Import From Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="fromUrl" type="text" ng-model="fromUrl.data">
+                </div>
+                <kc-tooltip>Import metadata from a remote IDP discovery descriptor.</kc-tooltip>
+                <div class="col-md-6" data-ng-show="importUrl">
+                    <button type="submit" data-ng-click="importFrom()" data-ng-show="importUrl" class="btn btn-primary">Import</button>
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="newIdentityProvider">
+                <label class="col-md-2 control-label">Import From File</label>
+                <kc-tooltip>Import metadata from a downloaded IDP discovery descriptor.</kc-tooltip>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
+                    </div>
+                <span class="kc-uploaded-file" data-ng-show="files.length > 0">
+                    {{files[0].name}}
+                </span>
+                </div>
+                <div class="col-md-6" data-ng-show="importFile">
+                    <button type="submit" data-ng-click="uploadFile()" data-ng-show="importFile" class="btn btn-primary">Import</button>
+                </div>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 1077593..2af44a3 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -1,206 +1,206 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initSamlProvider()">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li>{{identityProvider.alias}}</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
-    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add SAML Identity Provider</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
-        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider && identityProvider.providerId == 'saml'">Export</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
-                <div class="col-sm-6">
-                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
-                </div>
-                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="identifier"><span class="required">*</span> Alias</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="identifier" type="text" ng-model="identityProvider.alias" data-ng-readonly="!newIdentityProvider" required>
-                </div>
-                <kc-tooltip>The alias unique identifies an identity provider and it is also used to build the redirect uri.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="enabled">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
-                </div>
-                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storeToken">Store Tokens</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">On</option>
-                            <option value="missing">On missing info</option>
-                            <option value="off">Off</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
-                </div>
-                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset>
-            <legend uncollapsed><span class="text">SAML Config</span> <kc-tooltip>SAML SP and external IDP configuration.</kc-tooltip></legend>
-
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="singleSignOnServiceUrl"><span class="required">*</span> Single Sign-On Service Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="singleSignOnServiceUrl" type="text" ng-model="identityProvider.config.singleSignOnServiceUrl" required>
-                </div>
-                <kc-tooltip>The Url that must be used to send authentication requests(SAML AuthnRequest).</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="singleSignOnServiceUrl">Single Logout Service Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="singleLogoutServiceUrl" type="text" ng-model="identityProvider.config.singleLogoutServiceUrl">
-                </div>
-                <kc-tooltip>The Url that must be used to send logout requests.</kc-tooltip>
-            </div>
-                    <div class="form-group">
-                        <label class="col-sm-2 control-label" for="backchannelSupported">Backchannel Logout</label>
-                        <div class="col-sm-4">
-                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" value="'true'" onoffswitchvalue />
-                        </div>
-                        <span tooltip-placement="right" tooltip="Does the external IDP support backchannel logout?" class="fa fa-info-circle"></span>
-                    </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="nameIDPolicyFormat">NameID Policy Format</label>
-                <div class="col-md-6">
-                    <select id="nameIDPolicyFormat" ng-model="identityProvider.config.nameIDPolicyFormat"
-                            ng-options="nameFormat.format as nameFormat.name for nameFormat in nameIdFormats">
-                     </select>
-                    <!-- <input class="form-control" id="nameIDPolicyFormat" type="text" ng-model="identityProvider.config.nameIDPolicyFormat"> -->
-                </div>
-                <kc-tooltip>Specifies the URI reference corresponding to a name identifier format. Defaults to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="postBindingResponse">HTTP-POST Binding Response</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.postBindingResponse" id="postBindingResponse" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip>Indicates whether to respond to requests using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="postBindingAuthnRequest">HTTP-POST Binding for AuthnRequest</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.postBindingAuthnRequest" id="postBindingAuthnRequest" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip>Indicates whether the AuthnRequest must be sent using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="wantAuthnRequestsSigned">Want AuthnRequests Signed</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.wantAuthnRequestsSigned" id="wantAuthnRequestsSigned" name="wantAuthnRequestsSigned" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip> Indicates whether the identity provider expects signed a AuthnRequest.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="forceAuthn">Force Authentication</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.forceAuthn" id="forceAuthn" name="forceAuthn" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip> Indicates whether the identity provider must authenticate the presenter directly rather than rely on a previous security context.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="validateSignature">Validate Signature</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.config.validateSignature" id="validateSignature" value="'true'" onoffswitchvalue />
-                </div>
-                <kc-tooltip>Enable/disable signature validation of SAML responses.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-show="identityProvider.config.validateSignature == 'true'">
-                <label class="col-md-2 control-label" for="signingCertificate">Validating X509 Certificate</label>
-                <div class="col-md-6">
-                    <textarea class="form-control" id="signingCertificate" ng-model="identityProvider.config.signingCertificate"/>
-                </div>
-                <kc-tooltip>The certificate in PEM format that must be used to check for signatures.</kc-tooltip>
-            </div>
-         </fieldset>
-        <fieldset data-ng-show="newIdentityProvider">
-            <legend uncollapsed><span class="text">Import External IDP Config</span> <kc-tooltip>Allows you to load external IDP metadata from a config file or to download it from a URL.</kc-tooltip></legend>
-            <div class="form-group" data-ng-show="newIdentityProvider">
-                <label class="col-md-2 control-label" for="fromUrl">Import From Url</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="fromUrl" type="text" ng-model="fromUrl.data">
-                </div>
-                <kc-tooltip>Import metadata from a remote IDP SAML entity descriptor.</kc-tooltip>
-                <div class="col-sm-4" data-ng-show="importUrl">
-                    <button type="submit" data-ng-click="importFrom()" data-ng-show="importUrl" class="btn btn-primary">Import</button>
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="newIdentityProvider">
-                <label class="col-md-2 control-label">Import From File</label>
-                <div class="col-md-6">
-                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
-                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
-                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
-                    </div>
-                <span class="kc-uploaded-file" data-ng-show="files.length > 0">
-                    {{files[0].name}}
-                </span>
-                </div>
-                <div class="col-sm-4" data-ng-show="importFile">
-                    <button type="submit" data-ng-click="uploadFile()" data-ng-show="importFile" class="btn btn-primary">Import</button>
-                </div>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initSamlProvider()">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li>{{identityProvider.alias}}</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
+    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add SAML Identity Provider</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
+        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider && identityProvider.providerId == 'saml'">Export</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
+                <div class="col-sm-6">
+                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
+                </div>
+                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="identifier"><span class="required">*</span> Alias</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="identifier" type="text" ng-model="identityProvider.alias" data-ng-readonly="!newIdentityProvider" required>
+                </div>
+                <kc-tooltip>The alias unique identifies an identity provider and it is also used to build the redirect uri.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="enabled">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
+                </div>
+                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storeToken">Store Tokens</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
+                <div class="col-md-2">
+                		<div>
+                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
+                            <option value="on">On</option>
+                            <option value="missing">On missing info</option>
+                            <option value="off">Off</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                </div>
+                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset>
+            <legend uncollapsed><span class="text">SAML Config</span> <kc-tooltip>SAML SP and external IDP configuration.</kc-tooltip></legend>
+
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="singleSignOnServiceUrl"><span class="required">*</span> Single Sign-On Service Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="singleSignOnServiceUrl" type="text" ng-model="identityProvider.config.singleSignOnServiceUrl" required>
+                </div>
+                <kc-tooltip>The Url that must be used to send authentication requests(SAML AuthnRequest).</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="singleSignOnServiceUrl">Single Logout Service Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="singleLogoutServiceUrl" type="text" ng-model="identityProvider.config.singleLogoutServiceUrl">
+                </div>
+                <kc-tooltip>The Url that must be used to send logout requests.</kc-tooltip>
+            </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="backchannelSupported">Backchannel Logout</label>
+                        <div class="col-sm-4">
+                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" value="'true'" onoffswitchvalue />
+                        </div>
+                        <span tooltip-placement="right" tooltip="Does the external IDP support backchannel logout?" class="fa fa-info-circle"></span>
+                    </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="nameIDPolicyFormat">NameID Policy Format</label>
+                <div class="col-md-6">
+                    <select id="nameIDPolicyFormat" ng-model="identityProvider.config.nameIDPolicyFormat"
+                            ng-options="nameFormat.format as nameFormat.name for nameFormat in nameIdFormats">
+                     </select>
+                    <!-- <input class="form-control" id="nameIDPolicyFormat" type="text" ng-model="identityProvider.config.nameIDPolicyFormat"> -->
+                </div>
+                <kc-tooltip>Specifies the URI reference corresponding to a name identifier format. Defaults to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="postBindingResponse">HTTP-POST Binding Response</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.postBindingResponse" id="postBindingResponse" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip>Indicates whether to respond to requests using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="postBindingAuthnRequest">HTTP-POST Binding for AuthnRequest</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.postBindingAuthnRequest" id="postBindingAuthnRequest" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip>Indicates whether the AuthnRequest must be sent using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="wantAuthnRequestsSigned">Want AuthnRequests Signed</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.wantAuthnRequestsSigned" id="wantAuthnRequestsSigned" name="wantAuthnRequestsSigned" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip> Indicates whether the identity provider expects signed a AuthnRequest.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="forceAuthn">Force Authentication</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.forceAuthn" id="forceAuthn" name="forceAuthn" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip> Indicates whether the identity provider must authenticate the presenter directly rather than rely on a previous security context.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="validateSignature">Validate Signature</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.config.validateSignature" id="validateSignature" value="'true'" onoffswitchvalue />
+                </div>
+                <kc-tooltip>Enable/disable signature validation of SAML responses.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="identityProvider.config.validateSignature == 'true'">
+                <label class="col-md-2 control-label" for="signingCertificate">Validating X509 Certificate</label>
+                <div class="col-md-6">
+                    <textarea class="form-control" id="signingCertificate" ng-model="identityProvider.config.signingCertificate"/>
+                </div>
+                <kc-tooltip>The certificate in PEM format that must be used to check for signatures.</kc-tooltip>
+            </div>
+         </fieldset>
+        <fieldset data-ng-show="newIdentityProvider">
+            <legend uncollapsed><span class="text">Import External IDP Config</span> <kc-tooltip>Allows you to load external IDP metadata from a config file or to download it from a URL.</kc-tooltip></legend>
+            <div class="form-group" data-ng-show="newIdentityProvider">
+                <label class="col-md-2 control-label" for="fromUrl">Import From Url</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="fromUrl" type="text" ng-model="fromUrl.data">
+                </div>
+                <kc-tooltip>Import metadata from a remote IDP SAML entity descriptor.</kc-tooltip>
+                <div class="col-sm-4" data-ng-show="importUrl">
+                    <button type="submit" data-ng-click="importFrom()" data-ng-show="importUrl" class="btn btn-primary">Import</button>
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="newIdentityProvider">
+                <label class="col-md-2 control-label">Import From File</label>
+                <div class="col-md-6">
+                    <div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
+                        <label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
+                        <input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
+                    </div>
+                <span class="kc-uploaded-file" data-ng-show="files.length > 0">
+                    {{files[0].name}}
+                </span>
+                </div>
+                <div class="col-sm-4" data-ng-show="importFile">
+                    <button type="submit" data-ng-click="uploadFile()" data-ng-show="importFile" class="btn btn-primary">Import</button>
+                </div>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 0b760cc..5cb50d2 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -1,118 +1,118 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
-        <li>{{identityProvider.alias}}</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
-    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add Social Identity Provider</h1>
-
-    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
-        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
-        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
-                <div class="col-sm-6">
-                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
-                </div>
-                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
-            </div>
-        </fieldset>
-        <fieldset>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="clientId"><span class="required">*</span> Client ID</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
-                </div>
-                <kc-tooltip>The client identifier registered withing the identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="clientSecret"><span class="required">*</span> Client Secret</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="clientSecret" type="password" ng-model="identityProvider.config.clientSecret" ng-show="hidePassword" required>
-                    <input class="form-control" id="clientSecret" type="text" ng-model="identityProvider.config.clientSecret" ng-show="!hidePassword" required>
-                    <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
-                    <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
-                </div>
-                <kc-tooltip>The client secret registered withing the identity provider.</kc-tooltip>
-            </div>
-            <div data-ng-include data-src="resourceUrl + '/partials/realm-identity-provider-' + identityProvider.providerId + '-ext.html'"></div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="defaultScope">Default Scopes </label>
-                <div class="col-md-6">
-                    <input class="form-control" id="defaultScope" type="text" ng-model="identityProvider.config.defaultScope">
-                </div>
-                <kc-tooltip>The scopes to be sent when asking for authorization. See documentation for possible values, separator and default value'.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="enabled">Store Tokens</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="enabled">Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">On</option>
-                            <option value="missing">On missing info</option>
-                            <option value="off">Off</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
-                <div class="col-md-6">
-                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
-                </div>
-                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
-                <div class="col-md-6">
-                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
-                </div>
-                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">Identity Providers</a></li>
+        <li>{{identityProvider.alias}}</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{identityProvider.alias|capitalize}}<i class="pficon pficon-delete clickable" 
+    	data-ng-hide="newIdentityProvider || changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add Social Identity Provider</h1>
+
+    <ul class="nav nav-tabs" data-ng-hide="newIdentityProvider">
+        <li class="active"><a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">Settings</a></li>
+        <li><a href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="redirectUri">Redirect URI</label>
+                <div class="col-sm-6">
+                    <input class="form-control" id="redirectUri" type="text" value="{{callbackUrl}}{{identityProvider.alias}}/endpoint" readonly kc-select-action="click">
+                </div>
+                <kc-tooltip>The redirect uri to use when configuring the identity provider</kc-tooltip>
+            </div>
+        </fieldset>
+        <fieldset>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="clientId"><span class="required">*</span> Client ID</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
+                </div>
+                <kc-tooltip>The client identifier registered withing the identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="clientSecret"><span class="required">*</span> Client Secret</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="clientSecret" type="password" ng-model="identityProvider.config.clientSecret" ng-show="hidePassword" required>
+                    <input class="form-control" id="clientSecret" type="text" ng-model="identityProvider.config.clientSecret" ng-show="!hidePassword" required>
+                    <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
+                    <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
+                </div>
+                <kc-tooltip>The client secret registered withing the identity provider.</kc-tooltip>
+            </div>
+            <div data-ng-include data-src="resourceUrl + '/partials/realm-identity-provider-' + identityProvider.providerId + '-ext.html'"></div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="defaultScope">Default Scopes </label>
+                <div class="col-md-6">
+                    <input class="form-control" id="defaultScope" type="text" ng-model="identityProvider.config.defaultScope">
+                </div>
+                <kc-tooltip>The scopes to be sent when asking for authorization. See documentation for possible values, separator and default value'.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="enabled">Store Tokens</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable if tokens must be stored after authenticating users.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="storedTokensReadable">Stored Tokens Readable</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.addReadTokenRoleOnCreate" id="storedTokensReadable" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable new users can read any stored tokens.  This assigns the broker.read-token role.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="enabled">Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.enabled" id="enabled" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
+                <div class="col-md-2">
+                		<div>
+                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
+                            <option value="on">On</option>
+                            <option value="missing">On missing info</option>
+                            <option value="off">Off</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="trustEmail">Trust email</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
+                <div class="col-md-6">
+                    <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch />
+                </div>
+                <kc-tooltip>Indicates if this provider should be tried by default for authentication even before displaying login screen</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                </div>
+                <kc-tooltip>Number defining order of the provider in GUI (eg. on Login page).</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-keys.html
index c89adf9..48de4ac 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-keys.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-keys.html
@@ -1,34 +1,34 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="publicKey">Public key</label>
-
-                <div class="col-md-10">
-                    <textarea type="text" id="publicKey" name="publicKey" class="form-control" rows="4"
-                              kc-select-action="click" readonly>{{realm.publicKey}}</textarea>
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="certificate">Certificate</label>
-
-                <div class="col-md-10">
-                    <textarea type="text" id="certificate" name="certificate" class="form-control" rows="8" kc-select-action="click" readonly>{{realm.certificate}}</textarea>
-                </div>
-            </div>
-        </fieldset>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button class="btn btn-danger" type="submit" data-ng-click="generate()">Generate new keys</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="publicKey">Public key</label>
+
+                <div class="col-md-10">
+                    <textarea type="text" id="publicKey" name="publicKey" class="form-control" rows="4"
+                              kc-select-action="click" readonly>{{realm.publicKey}}</textarea>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="certificate">Certificate</label>
+
+                <div class="col-md-10">
+                    <textarea type="text" id="certificate" name="certificate" class="form-control" rows="8" kc-select-action="click" readonly>{{realm.certificate}}</textarea>
+                </div>
+            </div>
+        </fieldset>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button class="btn btn-danger" type="submit" data-ng-click="generate()">Generate new keys</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-list.html
index da0a1fb..eba458a 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-list.html
@@ -1,20 +1,20 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <h1>Realms</h1>
-
-    <table class="datatable table table-striped table-bordered">
-        <thead>
-            <tr>
-                <th>Realm</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr data-ng-repeat="r in realms">
-                <td><a href="#/realms/{{r.realm}}">{{r.realm}}</a></td>
-            </tr>
-        </tbody>
-    </table>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <h1>Realms</h1>
+
+    <table class="datatable table table-striped table-bordered">
+        <thead>
+            <tr>
+                <th>Realm</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr data-ng-repeat="r in realms">
+                <td><a href="#/realms/{{r.realm}}">{{r.realm}}</a></td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-login-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-login-settings.html
index 024e0c1..10ac3ea 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-login-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-login-settings.html
@@ -1,75 +1,75 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label for="registrationAllowed" class="col-md-2 control-label">User registration</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.registrationAllowed" name="registrationAllowed" id="registrationAllowed" onoffswitch />
-                </div>
-                <kc-tooltip>Enable/disable the registration page. A link for registration will show on login page too.</kc-tooltip>
-            </div>
-            <div class="form-group" ng-show="realm.registrationAllowed">
-                <label for="registrationEmailAsUsername" class="col-md-2 control-label">Email as username</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.registrationEmailAsUsername" name="registrationEmailAsUsername" id="registrationEmailAsUsername" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled then username field is hidden from registration form and email is used as username for new user.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label for="editUsernameAllowed" class="col-md-2 control-label">Edit username</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.editUsernameAllowed" name="editUsernameAllowed" id="editUsernameAllowed" onoffswitch />
-                </div>
-                <kc-tooltip>If enabled, the username field is editable, readonly otherwise.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label for="resetPasswordAllowed" class="col-md-2 control-label">Forget password</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.resetPasswordAllowed" name="resetPasswordAllowed" id="resetPasswordAllowed" onoffswitch />
-                </div>
-                <kc-tooltip>Show a link on login page for user to click on when they have forgotten their credentials.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="rememberMe">Remember Me</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.rememberMe" name="rememberMe" id="rememberMe" onoffswitch />
-                </div>
-                <kc-tooltip>Show checkbox on login page to allow user to remain logged in between browser restarts until session expires.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label for="verifyEmail" class="col-md-2 control-label">Verify email</label>
-                <div class="col-md-6">
-                    <input ng-model="realm.verifyEmail" name="verifyEmail" id="verifyEmail" onoffswitch />
-                </div>
-                <kc-tooltip>Require the user to verify their email address the first time they login.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label for="sslRequired" class="col-md-2 control-label">Require SSL</label>
-                <div class="col-md-2">
-                    <div>
-                        <select id="sslRequired" ng-model="realm.sslRequired" class="form-control">
-                            <option value="all">all requests</option>
-                            <option value="external">external requests</option>
-                            <option value="none">none</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Is HTTPS required?  'None' means HTTPS is not required for any client IP address. 'External requests' means localhost and private IP addresses can access without HTTPS.  'All requests' means HTTPS is required for all IP addresses.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label for="registrationAllowed" class="col-md-2 control-label">User registration</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.registrationAllowed" name="registrationAllowed" id="registrationAllowed" onoffswitch />
+                </div>
+                <kc-tooltip>Enable/disable the registration page. A link for registration will show on login page too.</kc-tooltip>
+            </div>
+            <div class="form-group" ng-show="realm.registrationAllowed">
+                <label for="registrationEmailAsUsername" class="col-md-2 control-label">Email as username</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.registrationEmailAsUsername" name="registrationEmailAsUsername" id="registrationEmailAsUsername" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled then username field is hidden from registration form and email is used as username for new user.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label for="editUsernameAllowed" class="col-md-2 control-label">Edit username</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.editUsernameAllowed" name="editUsernameAllowed" id="editUsernameAllowed" onoffswitch />
+                </div>
+                <kc-tooltip>If enabled, the username field is editable, readonly otherwise.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label for="resetPasswordAllowed" class="col-md-2 control-label">Forget password</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.resetPasswordAllowed" name="resetPasswordAllowed" id="resetPasswordAllowed" onoffswitch />
+                </div>
+                <kc-tooltip>Show a link on login page for user to click on when they have forgotten their credentials.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="rememberMe">Remember Me</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.rememberMe" name="rememberMe" id="rememberMe" onoffswitch />
+                </div>
+                <kc-tooltip>Show checkbox on login page to allow user to remain logged in between browser restarts until session expires.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label for="verifyEmail" class="col-md-2 control-label">Verify email</label>
+                <div class="col-md-6">
+                    <input ng-model="realm.verifyEmail" name="verifyEmail" id="verifyEmail" onoffswitch />
+                </div>
+                <kc-tooltip>Require the user to verify their email address the first time they login.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label for="sslRequired" class="col-md-2 control-label">Require SSL</label>
+                <div class="col-md-2">
+                    <div>
+                        <select id="sslRequired" ng-model="realm.sslRequired" class="form-control">
+                            <option value="all">all requests</option>
+                            <option value="external">external requests</option>
+                            <option value="none">none</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Is HTTPS required?  'None' means HTTPS is not required for any client IP address. 'External requests' means localhost and private IP addresses can access without HTTPS.  'All requests' means HTTPS is required for all IP addresses.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-smtp.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-smtp.html
index 30ad48d..6e324e5 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-smtp.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-smtp.html
@@ -1,67 +1,67 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpHost"><span class="required">*</span> Host</label>
-            <div class="col-md-6">
-                <input class="form-control" id="smtpHost" type="text" ng-model="realm.smtpServer.host" placeholder="SMTP Host" required>
-            </div>
-        </div>
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpPort">Port</label>
-            <div class="col-md-6">
-                <input class="form-control" id="smtpPort" type="number" ng-model="realm.smtpServer.port" placeholder="SMTP Port (defaults to 25)">
-            </div>
-        </div>
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpFrom"><span class="required">*</span> From</label>
-            <div class="col-md-6">
-                <input class="form-control" id="smtpFrom" type="email" ng-model="realm.smtpServer.from" placeholder="Sender Email Address" required>
-            </div>
-        </div>
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpSSL">Enable SSL</label>
-            <div class="col-md-6">
-                <input ng-model="realm.smtpServer.ssl" name="smtpSSL" id="smtpSSL" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpStartTLS">Enable StartTLS</label>
-            <div class="col-md-6">
-                <input ng-model="realm.smtpServer.starttls" name="smtpStartTLS" id="smtpStartTLS" onoffswitch />
-            </div>
-        </div>
-
-        <div class="form-group clearfix">
-            <label class="col-md-2 control-label" for="smtpAuth">Enable Authentication</label>
-            <div class="col-md-6">
-                <input ng-model="realm.smtpServer.auth" name="smtpAuth" id="smtpAuth" onoffswitch />
-            </div>
-        </div>
-        <div class="form-group clearfix" data-ng-show="realm.smtpServer.auth">
-            <label class="col-md-2 control-label" for="smtpUsername"><span class="required">*</span> Username</span></label>
-            <div class="col-md-6">
-                <input class="form-control" id="smtpUsername" type="text" ng-model="realm.smtpServer.user" placeholder="Login Username" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
-            </div>
-        </div>
-        <div class="form-group clearfix" data-ng-show="realm.smtpServer.auth">
-            <label class="col-md-2 control-label" for="smtpPassword"><span class="required">*</span> Password</label>
-            <div class="col-md-6">
-                <input class="form-control" id="smtpPassword" type="password" ng-model="realm.smtpServer.password" placeholder="Login Password" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
-            </div>
-        </div>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button data-kc-save data-ng-show="changed">Save</button>
-                <button data-kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpHost"><span class="required">*</span> Host</label>
+            <div class="col-md-6">
+                <input class="form-control" id="smtpHost" type="text" ng-model="realm.smtpServer.host" placeholder="SMTP Host" required>
+            </div>
+        </div>
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpPort">Port</label>
+            <div class="col-md-6">
+                <input class="form-control" id="smtpPort" type="number" ng-model="realm.smtpServer.port" placeholder="SMTP Port (defaults to 25)">
+            </div>
+        </div>
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpFrom"><span class="required">*</span> From</label>
+            <div class="col-md-6">
+                <input class="form-control" id="smtpFrom" type="email" ng-model="realm.smtpServer.from" placeholder="Sender Email Address" required>
+            </div>
+        </div>
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpSSL">Enable SSL</label>
+            <div class="col-md-6">
+                <input ng-model="realm.smtpServer.ssl" name="smtpSSL" id="smtpSSL" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpStartTLS">Enable StartTLS</label>
+            <div class="col-md-6">
+                <input ng-model="realm.smtpServer.starttls" name="smtpStartTLS" id="smtpStartTLS" onoffswitch />
+            </div>
+        </div>
+
+        <div class="form-group clearfix">
+            <label class="col-md-2 control-label" for="smtpAuth">Enable Authentication</label>
+            <div class="col-md-6">
+                <input ng-model="realm.smtpServer.auth" name="smtpAuth" id="smtpAuth" onoffswitch />
+            </div>
+        </div>
+        <div class="form-group clearfix" data-ng-show="realm.smtpServer.auth">
+            <label class="col-md-2 control-label" for="smtpUsername"><span class="required">*</span> Username</span></label>
+            <div class="col-md-6">
+                <input class="form-control" id="smtpUsername" type="text" ng-model="realm.smtpServer.user" placeholder="Login Username" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
+            </div>
+        </div>
+        <div class="form-group clearfix" data-ng-show="realm.smtpServer.auth">
+            <label class="col-md-2 control-label" for="smtpPassword"><span class="required">*</span> Password</label>
+            <div class="col-md-6">
+                <input class="form-control" id="smtpPassword" type="password" ng-model="realm.smtpServer.password" placeholder="Login Password" ng-disabled="!realm.smtpServer.auth" ng-required="realm.smtpServer.auth">
+            </div>
+        </div>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button data-kc-save data-ng-show="changed">Save</button>
+                <button data-kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
index 5c51bba..e3fddc2 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
@@ -1,99 +1,99 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="loginTheme">Login Theme</label>
-                <div class="col-md-3">
-                    <div>
-                        <select class="form-control" id="loginTheme"
-                                ng-model="realm.loginTheme"
-                                ng-options="o as o for o in serverInfo.themes.login">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Select theme for login, TOTP, grant, registration, and forgot password pages.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="accountTheme">Account Theme</label>
-                <div class="col-md-3">
-                    <div>
-                        <select class="form-control" id="accountTheme"
-                                ng-model="realm.accountTheme"
-                                ng-options="o as o for o in serverInfo.themes.account">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Select theme for user account management pages.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="adminTheme">Admin Console Theme</label>
-                <div class="col-md-3">
-                    <div>
-                        <select class="form-control" id="adminTheme"
-                                ng-model="realm.adminTheme"
-                                ng-options="o as o for o in serverInfo.themes.admin">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Select theme for admin console.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="emailTheme">Email Theme</label>
-                <div class="col-md-3">
-                    <div>
-                        <select class="form-control" id="emailTheme"
-                                ng-model="realm.emailTheme"
-                                ng-options="o as o for o in serverInfo.themes.email">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>Select theme for emails that are sent by the server.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="internationalizationEnabled">Internationalization Enabled</label>
-                <div class="col-md-3">
-                    <input ng-model="realm.internationalizationEnabled" name="internationalizationEnabled" id="internationalizationEnabled" onoffswitch />
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="realm.internationalizationEnabled">
-                <label class="col-md-2 control-label" for="supportedLocales" class="control-label two-lines">Supported Locales</label>
-
-                <div class="col-md-6">
-                    <input id="supportedLocales" type="text" ui-select2="supportedLocalesOptions" ng-model="realm.supportedLocales" placeholder="Type a locale and enter" ng-required="realm.internationalizationEnabled" ng-disabled="!realm.internationalizationEnabled">
-                </div>
-            </div>
-            <div class="form-group" data-ng-show="realm.internationalizationEnabled">
-                <label class="col-md-2 control-label" for="defaultLocale">Default Locale</label>
-                <div class="col-md-3">
-                    <div>
-                        <select class="form-control" id="defaultLocale"
-                                ng-model="realm.defaultLocale"
-                                ng-options="o as o for o in realm.supportedLocales"
-                                ng-required="realm.internationalizationEnabled"
-                                ng-disabled="!realm.internationalizationEnabled">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-            </div>
-        </fieldset>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="loginTheme">Login Theme</label>
+                <div class="col-md-3">
+                    <div>
+                        <select class="form-control" id="loginTheme"
+                                ng-model="realm.loginTheme"
+                                ng-options="o as o for o in serverInfo.themes.login">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Select theme for login, TOTP, grant, registration, and forgot password pages.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="accountTheme">Account Theme</label>
+                <div class="col-md-3">
+                    <div>
+                        <select class="form-control" id="accountTheme"
+                                ng-model="realm.accountTheme"
+                                ng-options="o as o for o in serverInfo.themes.account">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Select theme for user account management pages.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="adminTheme">Admin Console Theme</label>
+                <div class="col-md-3">
+                    <div>
+                        <select class="form-control" id="adminTheme"
+                                ng-model="realm.adminTheme"
+                                ng-options="o as o for o in serverInfo.themes.admin">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Select theme for admin console.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="emailTheme">Email Theme</label>
+                <div class="col-md-3">
+                    <div>
+                        <select class="form-control" id="emailTheme"
+                                ng-model="realm.emailTheme"
+                                ng-options="o as o for o in serverInfo.themes.email">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>Select theme for emails that are sent by the server.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="internationalizationEnabled">Internationalization Enabled</label>
+                <div class="col-md-3">
+                    <input ng-model="realm.internationalizationEnabled" name="internationalizationEnabled" id="internationalizationEnabled" onoffswitch />
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="realm.internationalizationEnabled">
+                <label class="col-md-2 control-label" for="supportedLocales" class="control-label two-lines">Supported Locales</label>
+
+                <div class="col-md-6">
+                    <input id="supportedLocales" type="text" ui-select2="supportedLocalesOptions" ng-model="realm.supportedLocales" placeholder="Type a locale and enter" ng-required="realm.internationalizationEnabled" ng-disabled="!realm.internationalizationEnabled">
+                </div>
+            </div>
+            <div class="form-group" data-ng-show="realm.internationalizationEnabled">
+                <label class="col-md-2 control-label" for="defaultLocale">Default Locale</label>
+                <div class="col-md-3">
+                    <div>
+                        <select class="form-control" id="defaultLocale"
+                                ng-model="realm.defaultLocale"
+                                ng-options="o as o for o in realm.supportedLocales"
+                                ng-required="realm.internationalizationEnabled"
+                                ng-disabled="!realm.internationalizationEnabled">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+
+        <div class="form-group" data-ng-show="access.manageRealm">
+            <div class="col-md-10 col-md-offset-2">
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
index c23fa66..7f4aae9 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
@@ -1,126 +1,126 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Settings</h1>
-
-    <kc-tabs-realm></kc-tabs-realm>
-
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="ssoSessionIdleTimeout">SSO Session Idle Timeout</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1"
-                                   max="31536000" data-ng-model="realm.ssoSessionIdleTimeout"
-                                   id="ssoSessionIdleTimeout" name="ssoSessionIdleTimeout"/>
-                            <select class="form-control" name="ssoSessionIdleTimeoutUnit" data-ng-model="realm.ssoSessionIdleTimeoutUnit" >
-                                <option data-ng-selected="!realm.ssoSessionIdleTimeoutUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Time a session is allowed to be idle before it expires.  Tokens and browser sessions are invalidated when a session is expired.</kc-tooltip>
-            </div>
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="ssoSessionMaxLifespan">SSO Session Max Lifespan</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1"
-                                   max="31536000" data-ng-model="realm.ssoSessionMaxLifespan"
-                                   id="ssoSessionMaxLifespan" name="ssoSessionMaxLifespan"/>
-                            <select class="form-control" name="ssoSessionMaxLifespanUnit" data-ng-model="realm.ssoSessionMaxLifespanUnit" >
-                                <option data-ng-selected="!realm.ssoSessionMaxLifespanUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Max time before a session is expired.  Tokens and browser sessions are invalidated when a session is expired.</kc-tooltip>
-            </div>
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="accessTokenLifespan">Access Token Lifespan</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1"
-                                   max="31536000" data-ng-model="realm.accessTokenLifespan"
-                                   id="accessTokenLifespan" name="accessTokenLifespan"/>
-                            <select class="form-control" name="accessTokenLifespanUnit" data-ng-model="realm.accessTokenLifespanUnit" >
-                                <option data-ng-selected="!realm.accessTokenLifespanUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Max time before an access token is expired.  This value is recommended to be short relative to the SSO timeout.</kc-tooltip>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="accessCodeLifespan">Client login timeout</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespan" id="accessCodeLifespan" name="accessCodeLifespan">
-                            <select class="form-control" name="accessCodeLifespanUnit" data-ng-model="realm.accessCodeLifespanUnit">
-                                <option data-ng-selected="!realm.accessCodeLifespanUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Max time an client has to finish the access token protocol.  This should normally be 1 minute.</kc-tooltip>                </div>
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="accessCodeLifespanLogin" class="two-lines">Login lifespan</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespanLogin" id="accessCodeLifespanLogin" name="accessCodeLifespanLogin">
-                            <select class="form-control" name="accessCodeLifespanLoginUnit" data-ng-model="realm.accessCodeLifespanLoginUnit">
-                                <option data-ng-selected="!realm.accessCodeLifespanLoginUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Max time a user has to complete a login.  This is recommended to be relatively long.  30 minutes or more.</kc-tooltip>
-            </div>
-            <div class="form-group input-select">
-                <label class="col-md-2 control-label" for="accessCodeLifespanUserAction" class="two-lines">Login user action lifespan</label>
-                <div class="col-sm-5">
-                    <div class="row">
-                        <div class="col-md-6 form-inline">
-                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespanUserAction" id="accessCodeLifespanUserAction" name="accessCodeLifespanUserAction">
-                            <select class="form-control" name="accessCodeLifespanUserActionUnit" data-ng-model="realm.accessCodeLifespanUserActionUnit">
-                                <option data-ng-selected="!realm.accessCodeLifespanUserActionUnit">Seconds</option>
-                                <option>Minutes</option>
-                                <option>Hours</option>
-                                <option>Days</option>
-                            </select>
-                        </div>
-                    </div>
-                </div>
-                <kc-tooltip>Max time a user has to complete login related actions like update password or configure totp.  This is recommended to be relatively long.  5 minutes or more.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Settings</h1>
+
+    <kc-tabs-realm></kc-tabs-realm>
+
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="ssoSessionIdleTimeout">SSO Session Idle Timeout</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1"
+                                   max="31536000" data-ng-model="realm.ssoSessionIdleTimeout"
+                                   id="ssoSessionIdleTimeout" name="ssoSessionIdleTimeout"/>
+                            <select class="form-control" name="ssoSessionIdleTimeoutUnit" data-ng-model="realm.ssoSessionIdleTimeoutUnit" >
+                                <option data-ng-selected="!realm.ssoSessionIdleTimeoutUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Time a session is allowed to be idle before it expires.  Tokens and browser sessions are invalidated when a session is expired.</kc-tooltip>
+            </div>
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="ssoSessionMaxLifespan">SSO Session Max Lifespan</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1"
+                                   max="31536000" data-ng-model="realm.ssoSessionMaxLifespan"
+                                   id="ssoSessionMaxLifespan" name="ssoSessionMaxLifespan"/>
+                            <select class="form-control" name="ssoSessionMaxLifespanUnit" data-ng-model="realm.ssoSessionMaxLifespanUnit" >
+                                <option data-ng-selected="!realm.ssoSessionMaxLifespanUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Max time before a session is expired.  Tokens and browser sessions are invalidated when a session is expired.</kc-tooltip>
+            </div>
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="accessTokenLifespan">Access Token Lifespan</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1"
+                                   max="31536000" data-ng-model="realm.accessTokenLifespan"
+                                   id="accessTokenLifespan" name="accessTokenLifespan"/>
+                            <select class="form-control" name="accessTokenLifespanUnit" data-ng-model="realm.accessTokenLifespanUnit" >
+                                <option data-ng-selected="!realm.accessTokenLifespanUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Max time before an access token is expired.  This value is recommended to be short relative to the SSO timeout.</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="accessCodeLifespan">Client login timeout</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespan" id="accessCodeLifespan" name="accessCodeLifespan">
+                            <select class="form-control" name="accessCodeLifespanUnit" data-ng-model="realm.accessCodeLifespanUnit">
+                                <option data-ng-selected="!realm.accessCodeLifespanUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Max time an client has to finish the access token protocol.  This should normally be 1 minute.</kc-tooltip>                </div>
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="accessCodeLifespanLogin" class="two-lines">Login lifespan</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespanLogin" id="accessCodeLifespanLogin" name="accessCodeLifespanLogin">
+                            <select class="form-control" name="accessCodeLifespanLoginUnit" data-ng-model="realm.accessCodeLifespanLoginUnit">
+                                <option data-ng-selected="!realm.accessCodeLifespanLoginUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Max time a user has to complete a login.  This is recommended to be relatively long.  30 minutes or more.</kc-tooltip>
+            </div>
+            <div class="form-group input-select">
+                <label class="col-md-2 control-label" for="accessCodeLifespanUserAction" class="two-lines">Login user action lifespan</label>
+                <div class="col-sm-5">
+                    <div class="row">
+                        <div class="col-md-6 form-inline">
+                            <input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespanUserAction" id="accessCodeLifespanUserAction" name="accessCodeLifespanUserAction">
+                            <select class="form-control" name="accessCodeLifespanUserActionUnit" data-ng-model="realm.accessCodeLifespanUserActionUnit">
+                                <option data-ng-selected="!realm.accessCodeLifespanUserActionUnit">Seconds</option>
+                                <option>Minutes</option>
+                                <option>Hours</option>
+                                <option>Days</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <kc-tooltip>Max time a user has to complete login related actions like update password or configure totp.  This is recommended to be relatively long.  5 minutes or more.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
index bdde0c5..b7cd948 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html
@@ -1,27 +1,27 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Authentication</h1>
-
-    <kc-tabs-authentication></kc-tabs-authentication>
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr data-ng-hide="requiredActions.length == 0">
-            <th>Required Action</th>
-            <th>Enabled</th>
-            <th>Default Action <i class="fa fa-question-circle text-muted" tooltip="If enabled, any new user will have this required action assigned to it."></i></th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="requiredAction in requiredActions" data-ng-show="requiredActions.length > 0">
-            <td>{{requiredAction.name}}</td>
-            <td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)"></td>
-            <td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)"></td>
-        </tr>
-        <tr data-ng-show="requiredActions.length == 0">
-            <td>No required actions configured</td>
-        </tr>
-        </tbody>
-    </table>
-
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Authentication</h1>
+
+    <kc-tabs-authentication></kc-tabs-authentication>
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr data-ng-hide="requiredActions.length == 0">
+            <th>Required Action</th>
+            <th>Enabled</th>
+            <th>Default Action <i class="fa fa-question-circle text-muted" tooltip="If enabled, any new user will have this required action assigned to it."></i></th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="requiredAction in requiredActions" data-ng-show="requiredActions.length > 0">
+            <td>{{requiredAction.name}}</td>
+            <td><input type="checkbox" ng-model="requiredAction.enabled" ng-change="updateRequiredAction(requiredAction)"></td>
+            <td><input type="checkbox" ng-model="requiredAction.defaultAction" ng-change="updateRequiredAction(requiredAction)"></td>
+        </tr>
+        <tr data-ng-show="requiredActions.length == 0">
+            <td>No required actions configured</td>
+        </tr>
+        </tbody>
+    </table>
+
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
index 9bf9b69..e3a52cf 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
@@ -1,131 +1,131 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
-        <li data-ng-hide="create">{{role.name}}</li>
-        <li data-ng-show="create">Add Role</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{role.name|capitalize}} <i id="removeRole" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add Role</h1>
-
-    <form class="form-horizontal clearfix" name="realmForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset>
-            <legend><span class="text">Role</span></legend>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="name"><span class="required" data-ng-show="create">*</span> Role name</label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="name" name="name" data-ng-model="role.name" autofocus
-                           required data-ng-readonly="!create">
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="description">Description </label>
-
-                <div class="col-md-6">
-                    <textarea class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
-                </div>
-            </div>
-            <div class="form-group" data-ng-hide="create">
-                <label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
-                <div class="col-md-6">
-                    <input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch />
-                </div>
-                <kc-tooltip>When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
-            </div>
-        </div>
-
-        <fieldset data-ng-show="!create && (compositeSwitch || role.composite)">
-            <legend uncollapsed class="collapsible"><span class="text">Composite Roles</span> </legend>
-            <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
-
-                <div class="col-md-10">
-                    <div class="row">
-                        <div class="col-md-4">
-                            <label class="control-label">Available Roles</label>
-                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
-                            <select id="available" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmRoles"
-                                    ng-options="r.name for r in realmRoles | orderBy:'name'">
-                            </select>
-                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-4">
-                            <label class="control-label">Associated Roles</label>
-                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
-                            <select id="assigned" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedRealmMappings"
-                                    ng-options="r.name for r in realmMappings | orderBy:'name'">
-                            </select>
-                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">
-                    <span>Client Roles</span>
-                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
-                </label>
-
-                <div class="col-md-10">
-                    <div class="row" data-ng-hide="compositeClient">
-                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
-                    </div>
-                    <div class="row" data-ng-show="compositeClient">
-                        <div class="col-md-4">
-                            <label class="control-label" for="available-client">Available Roles</label>
-                            <kc-tooltip>Roles from this client that you can associate to this composite role.</kc-tooltip>
-                            <select id="available-client" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedClientRoles"
-                                    ng-options="r.name for r in clientRoles | orderBy:'name'">
-                            </select>
-                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
-                                Add selected <i class="fa fa-angle-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-4">
-                            <label class="control-label" for="assigned-client">Associated Roles</label>
-                            <kc-tooltip>Client roles associated with this composite role.</kc-tooltip>
-                            <select id="assigned-client" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedClientMappings"
-                                    ng-options="r.name for r in clientMappings | orderBy:'name'">
-                            </select>
-                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
-                                <i class="fa fa-angle-left"></i> Remove selected
-                            </button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </fieldset>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
+        <li data-ng-hide="create">{{role.name}}</li>
+        <li data-ng-show="create">Add Role</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{role.name|capitalize}} <i id="removeRole" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
+    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add Role</h1>
+
+    <form class="form-horizontal clearfix" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset>
+            <legend><span class="text">Role</span></legend>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="name"><span class="required" data-ng-show="create">*</span> Role name</label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="name" name="name" data-ng-model="role.name" autofocus
+                           required data-ng-readonly="!create">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="description">Description </label>
+
+                <div class="col-md-6">
+                    <textarea class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
+                </div>
+            </div>
+            <div class="form-group" data-ng-hide="create">
+                <label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
+                <div class="col-md-6">
+                    <input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch />
+                </div>
+                <kc-tooltip>When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()" data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageRealm">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-reset data-ng-show="changed">Cancel</button>
+            </div>
+        </div>
+
+        <fieldset data-ng-show="!create && (compositeSwitch || role.composite)">
+            <legend uncollapsed class="collapsible"><span class="text">Composite Roles</span> </legend>
+            <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
+
+                <div class="col-md-10">
+                    <div class="row">
+                        <div class="col-md-4">
+                            <label class="control-label">Available Roles</label>
+                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
+                            <select id="available" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmRoles"
+                                    ng-options="r.name for r in realmRoles | orderBy:'name'">
+                            </select>
+                            <button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-4">
+                            <label class="control-label">Associated Roles</label>
+                            <kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
+                            <select id="assigned" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedRealmMappings"
+                                    ng-options="r.name for r in realmMappings | orderBy:'name'">
+                            </select>
+                            <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">
+                    <span>Client Roles</span>
+                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
+                </label>
+
+                <div class="col-md-10">
+                    <div class="row" data-ng-hide="compositeClient">
+                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
+                    </div>
+                    <div class="row" data-ng-show="compositeClient">
+                        <div class="col-md-4">
+                            <label class="control-label" for="available-client">Available Roles</label>
+                            <kc-tooltip>Roles from this client that you can associate to this composite role.</kc-tooltip>
+                            <select id="available-client" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles | orderBy:'name'">
+                            </select>
+                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
+                                Add selected <i class="fa fa-angle-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-4">
+                            <label class="control-label" for="assigned-client">Associated Roles</label>
+                            <kc-tooltip>Client roles associated with this composite role.</kc-tooltip>
+                            <select id="assigned-client" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings | orderBy:'name'">
+                            </select>
+                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
+                                <i class="fa fa-angle-left"></i> Remove selected
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
index 7c6b059..9a97f56 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
@@ -1,49 +1,49 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Roles</h1>
-
-    <ul class="nav nav-tabs">
-        <li class="active"><a href="#/realms/{{realm.realm}}/roles">Realm Roles</a></li>
-        <li><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
-    </ul>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="3">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." 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 class="pull-right" data-ng-show="access.manageRealm">
-                        <a id="createRole" class="btn btn-default" href="#/create/role/{{realm.realm}}">Add Role</a>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-show="roles && roles.length > 0">
-            <th>Role Name</th>
-            <th>Composite</th>
-            <th>Description</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>{{role.composite}}</td>
-            <td>{{role.description}}</td>
-        </tr>
-        <tr data-ng-show="(roles | filter:{name: searchQuery}).length == 0">
-            <td class="text-muted" colspan="3" data-ng-show="searchQuery">No results</td>
-            <td class="text-muted" colspan="3" data-ng-hide="searchQuery">No realm roles available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Roles</h1>
+
+    <ul class="nav nav-tabs">
+        <li class="active"><a href="#/realms/{{realm.realm}}/roles">Realm Roles</a></li>
+        <li><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
+    </ul>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="3">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." 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 class="pull-right" data-ng-show="access.manageRealm">
+                        <a id="createRole" class="btn btn-default" href="#/create/role/{{realm.realm}}">Add Role</a>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-show="roles && roles.length > 0">
+            <th>Role Name</th>
+            <th>Composite</th>
+            <th>Description</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>{{role.composite}}</td>
+            <td>{{role.description}}</td>
+        </tr>
+        <tr data-ng-show="(roles | filter:{name: searchQuery}).length == 0">
+            <td class="text-muted" colspan="3" data-ng-show="searchQuery">No results</td>
+            <td class="text-muted" colspan="3" data-ng-hide="searchQuery">No realm roles available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
index e82edf5..d12b304 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
@@ -1,103 +1,103 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
-        <li>{{user.username}}</li>
-    </ol>
-
-    <h1>{{user.username|capitalize}}</h1>
-
-    <kc-tabs-user></kc-tabs-user>
-
-    <form class="form-horizontal" name="realmForm" novalidate>
-        <div class="form-group" kc-read-only="!access.manageUsers">
-            <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
-
-            <div class="col-md-10">
-                <div class="row">
-                    <div class="col-md-3">
-                        <label class="control-label" for="available">Available Roles</label>
-                        <select id="available" class="form-control" multiple size="5"
-                                ng-multiple="true"
-                                ng-model="selectedRealmRoles"
-                                ng-options="r.name for r in realmRoles">
-                        </select>
-                        <button ng-disabled="selectedRealmRoles.length == 0" ng-disabled="c.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
-                            Add selected <i class="fa fa-angle-right"></i>
-                        </button>
-                        <kc-tooltip>Realm roles that can be assigned to the user.</kc-tooltip>
-                    </div>
-                    <div class="col-md-3">
-                        <label class="control-label" for="assigned">Assigned Roles</label>
-                        <kc-tooltip>Realm roles mapped to the user</kc-tooltip>
-                        <select id="assigned" class="form-control" multiple size=5
-                                ng-multiple="true"
-                                ng-model="selectedRealmMappings"
-                                ng-options="r.name for r in realmMappings">
-                        </select>
-                        <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
-                            <i class="fa fa-angle-double-left"></i> Remove selected
-                        </button>
-                    </div>
-                    <div class="col-md-3">
-                        <label class="control-label" for="realm-composite">Effective Roles</label>
-                        <kc-tooltip>All realm role mappings.  Some roles here might be inherited from a mapped composite role.</kc-tooltip>
-                        <select id="realm-composite" class="form-control" multiple size=5
-                                disabled="true"
-                                ng-model="dummymodel"
-                                ng-options="r.name for r in realmComposite">
-                        </select>
-                    </div>
-                </div>
-            </div>
-        </div>
-
-        <div class="form-group">
-                <label class="col-md-2 control-label" class="control-label">
-                    <span>Client Roles</span>
-                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
-                </label>
-                <div class="col-md-10" kc-read-only="!access.manageUsers">
-                    <div class="row" data-ng-hide="client">
-                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
-                    </div>
-                    <div class="row" data-ng-show="client">
-                        <div class="col-md-3">
-                            <label class="control-label" for="available-client">Available Roles</label>
-                            <kc-tooltip>Assignable roles from this client.</kc-tooltip>
-                            <select id="available-client" class="form-control" multiple size="5"
-                                    ng-multiple="true"
-                                    ng-model="selectedClientRoles"
-                                    ng-options="r.name for r in clientRoles">
-                            </select>
-                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
-                                Add selected <i class="fa fa-angle-double-right"></i>
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="assigned-client">Assigned Roles</label>
-                            <kc-tooltip>Role mappings for this client.</kc-tooltip>
-                            <select id="assigned-client" class="form-control" multiple size=5
-                                    ng-multiple="true"
-                                    ng-model="selectedClientMappings"
-                                    ng-options="r.name for r in clientMappings">
-                            </select>
-                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
-                                <i class="fa fa-angle-double-left"></i> Remove selected
-                            </button>
-                        </div>
-                        <div class="col-md-3">
-                            <label class="control-label" for="client-composite">Effective Roles <span tooltip-placement="right" tooltip="Role mappings for this client.  Some roles here might be inherited from a mapped composite role." class="fa fa-info-circle"></span></label>
-                            <select id="client-composite" class="form-control" multiple size=5
-                                    disabled="true"
-                                    ng-model="dummymodel"
-                                    ng-options="r.name for r in clientComposite">
-                            </select>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+        <li>{{user.username}}</li>
+    </ol>
+
+    <h1>{{user.username|capitalize}}</h1>
+
+    <kc-tabs-user></kc-tabs-user>
+
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <div class="form-group" kc-read-only="!access.manageUsers">
+            <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
+
+            <div class="col-md-10">
+                <div class="row">
+                    <div class="col-md-3">
+                        <label class="control-label" for="available">Available Roles</label>
+                        <select id="available" class="form-control" multiple size="5"
+                                ng-multiple="true"
+                                ng-model="selectedRealmRoles"
+                                ng-options="r.name for r in realmRoles">
+                        </select>
+                        <button ng-disabled="selectedRealmRoles.length == 0" ng-disabled="c.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
+                            Add selected <i class="fa fa-angle-right"></i>
+                        </button>
+                        <kc-tooltip>Realm roles that can be assigned to the user.</kc-tooltip>
+                    </div>
+                    <div class="col-md-3">
+                        <label class="control-label" for="assigned">Assigned Roles</label>
+                        <kc-tooltip>Realm roles mapped to the user</kc-tooltip>
+                        <select id="assigned" class="form-control" multiple size=5
+                                ng-multiple="true"
+                                ng-model="selectedRealmMappings"
+                                ng-options="r.name for r in realmMappings">
+                        </select>
+                        <button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
+                            <i class="fa fa-angle-double-left"></i> Remove selected
+                        </button>
+                    </div>
+                    <div class="col-md-3">
+                        <label class="control-label" for="realm-composite">Effective Roles</label>
+                        <kc-tooltip>All realm role mappings.  Some roles here might be inherited from a mapped composite role.</kc-tooltip>
+                        <select id="realm-composite" class="form-control" multiple size=5
+                                disabled="true"
+                                ng-model="dummymodel"
+                                ng-options="r.name for r in realmComposite">
+                        </select>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="form-group">
+                <label class="col-md-2 control-label" class="control-label">
+                    <span>Client Roles</span>
+                    <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
+                </label>
+                <div class="col-md-10" kc-read-only="!access.manageUsers">
+                    <div class="row" data-ng-hide="client">
+                        <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
+                    </div>
+                    <div class="row" data-ng-show="client">
+                        <div class="col-md-3">
+                            <label class="control-label" for="available-client">Available Roles</label>
+                            <kc-tooltip>Assignable roles from this client.</kc-tooltip>
+                            <select id="available-client" class="form-control" multiple size="5"
+                                    ng-multiple="true"
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles">
+                            </select>
+                            <button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
+                                Add selected <i class="fa fa-angle-double-right"></i>
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="assigned-client">Assigned Roles</label>
+                            <kc-tooltip>Role mappings for this client.</kc-tooltip>
+                            <select id="assigned-client" class="form-control" multiple size=5
+                                    ng-multiple="true"
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings">
+                            </select>
+                            <button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
+                                <i class="fa fa-angle-double-left"></i> Remove selected
+                            </button>
+                        </div>
+                        <div class="col-md-3">
+                            <label class="control-label" for="client-composite">Effective Roles <span tooltip-placement="right" tooltip="Role mappings for this client.  Some roles here might be inherited from a mapped composite role." class="fa fa-info-circle"></span></label>
+                            <select id="client-composite" class="form-control" multiple size=5
+                                    disabled="true"
+                                    ng-model="dummymodel"
+                                    ng-options="r.name for r in clientComposite">
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
index c0d6600..34c9a84 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
@@ -1,66 +1,66 @@
-<div class="col-md-12">
-    <h1>Server Info</h1>
-
-    <table class="table table-striped table-bordered">
-        <tr>
-            <td>Version</td>
-            <td>{{serverInfo.version}}</td>
-        </tr>
-        <tr>
-            <td>Server Time</td>
-            <td>{{serverInfo.serverTime}} (<a data-ng-click="serverInfoUpdate()">update</a>)</td>
-        </tr>
-    </table>
-
-    <fieldset>
-        <legend collapsed>Providers</legend>
-
-        <div class="form-group">
-            <h3>Public SPIs</h3>
-            <kc-tooltip>For public SPIs there are built-in providers, but it's also supported to write your own custom providers.</kc-tooltip>
-
-            <table class="table table-striped table-bordered">
-                <thead>
-                <tr>
-                    <th>SPI</th>
-                    <th>Providers</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr data-ng-repeat="spi in (serverInfo.providers | filter:{internal:false} | orderBy:'name')">
-                    <td>{{spi.name}}</td>
-                    <td>
-                        <div data-ng-repeat="provider in (spi.implementations | orderBy:'toString()')">
-                            {{provider}}
-                        </div>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-
-        <div class="form-group">
-            <h3>Internal SPIs</h3>
-            <kc-tooltip>For internal SPIs there are only built-in providers. It's not recommended to write your own custom providers as internal SPIs may change or be removed without notice.</kc-tooltip>
-
-            <table class="table table-striped table-bordered">
-                <thead>
-                <tr>
-                    <th>SPI</th>
-                    <th>Providers</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr data-ng-repeat="spi in (serverInfo.providers | filter:{internal:true} | orderBy:'name')">
-                    <td>{{spi.name}}</td>
-                    <td>
-                        <div data-ng-repeat="provider in (spi.implementations | orderBy:'toString()')">
-                            {{provider}}
-                        </div>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-    </fieldset>
+<div class="col-md-12">
+    <h1>Server Info</h1>
+
+    <table class="table table-striped table-bordered">
+        <tr>
+            <td>Version</td>
+            <td>{{serverInfo.version}}</td>
+        </tr>
+        <tr>
+            <td>Server Time</td>
+            <td>{{serverInfo.serverTime}} (<a data-ng-click="serverInfoUpdate()">update</a>)</td>
+        </tr>
+    </table>
+
+    <fieldset>
+        <legend collapsed>Providers</legend>
+
+        <div class="form-group">
+            <h3>Public SPIs</h3>
+            <kc-tooltip>For public SPIs there are built-in providers, but it's also supported to write your own custom providers.</kc-tooltip>
+
+            <table class="table table-striped table-bordered">
+                <thead>
+                <tr>
+                    <th>SPI</th>
+                    <th>Providers</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr data-ng-repeat="spi in (serverInfo.providers | filter:{internal:false} | orderBy:'name')">
+                    <td>{{spi.name}}</td>
+                    <td>
+                        <div data-ng-repeat="provider in (spi.implementations | orderBy:'toString()')">
+                            {{provider}}
+                        </div>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+
+        <div class="form-group">
+            <h3>Internal SPIs</h3>
+            <kc-tooltip>For internal SPIs there are only built-in providers. It's not recommended to write your own custom providers as internal SPIs may change or be removed without notice.</kc-tooltip>
+
+            <table class="table table-striped table-bordered">
+                <thead>
+                <tr>
+                    <th>SPI</th>
+                    <th>Providers</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr data-ng-repeat="spi in (serverInfo.providers | filter:{internal:true} | orderBy:'name')">
+                    <td>{{spi.name}}</td>
+                    <td>
+                        <div data-ng-repeat="provider in (spi.implementations | orderBy:'toString()')">
+                            {{provider}}
+                        </div>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </fieldset>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
index 4426f4b..5410f09 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
@@ -1,32 +1,32 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Sessions</h1>
-
-    <ul class="nav nav-tabs">
-        <li class="active"><a href="#/realms/{{realm.realm}}/sessions/realm">Realm Sessions</a></li>
-        <li><a href="#/realms/{{realm.realm}}/sessions/revocation">Revocation</a></li>
-    </ul>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="3">
-                <div class="pull-right">
-                    <a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">Logout All</a>
-                </div>
-            </th>
-        </tr>
-        <tr>
-            <th>Client</th>
-            <th>Active Sessions</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr data-ng-repeat="data in stats">
-            <td><a href="#/realms/{{realm.realm}}/clients/{{data.id}}/sessions">{{data.clientId}}</a></td>
-            <td>{{data.active}}</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Sessions</h1>
+
+    <ul class="nav nav-tabs">
+        <li class="active"><a href="#/realms/{{realm.realm}}/sessions/realm">Realm Sessions</a></li>
+        <li><a href="#/realms/{{realm.realm}}/sessions/revocation">Revocation</a></li>
+    </ul>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr>
+            <th class="kc-table-actions" colspan="3">
+                <div class="pull-right">
+                    <a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">Logout All</a>
+                </div>
+            </th>
+        </tr>
+        <tr>
+            <th>Client</th>
+            <th>Active Sessions</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr data-ng-repeat="data in stats">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{data.id}}/sessions">{{data.clientId}}</a></td>
+            <td>{{data.active}}</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
index d16b22f..50b4c18 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
@@ -1,30 +1,30 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Sessions</h1>
-
-    <ul class="nav nav-tabs">
-        <li><a href="#/realms/{{realm.realm}}/sessions/realm">Realm Sessions</a></li>
-        <li class="active"><a href="#/realms/{{realm.realm}}/sessions/revocation">Revocation</a></li>
-    </ul>
-
-    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="notBefore">Not Before</label>
-                <div class="col-md-6">
-                    <input ng-disabled="true" class="form-control" type="text" id="notBefore" name="notBefore" data-ng-model="notBefore" autofocus>
-                </div>
-                <kc-tooltip>Revoke any tokens issued before this date.</kc-tooltip>
-            </div>
-        </fieldset>
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
-                <button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">Set To Now</button>
-                <button type="submit" data-ng-click="clear()" class="btn btn-default">Clear</button>
-                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip="For every client that has an admin URL, notify them of the new revocation policy." tooltip-placement="bottom">Push</button>
-            </div>
-        </div>
-    </form>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Sessions</h1>
+
+    <ul class="nav nav-tabs">
+        <li><a href="#/realms/{{realm.realm}}/sessions/realm">Realm Sessions</a></li>
+        <li class="active"><a href="#/realms/{{realm.realm}}/sessions/revocation">Revocation</a></li>
+    </ul>
+
+    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="notBefore">Not Before</label>
+                <div class="col-md-6">
+                    <input ng-disabled="true" class="form-control" type="text" id="notBefore" name="notBefore" data-ng-model="notBefore" autofocus>
+                </div>
+                <kc-tooltip>Revoke any tokens issued before this date.</kc-tooltip>
+            </div>
+        </fieldset>
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+                <button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">Set To Now</button>
+                <button type="submit" data-ng-click="clear()" class="btn btn-default">Clear</button>
+                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip="For every client that has an admin URL, notify them of the new revocation policy." tooltip-placement="bottom">Push</button>
+            </div>
+        </div>
+    </form>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-attribute-entry.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-attribute-entry.html
index 121acd8..373c91c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-attribute-entry.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-attribute-entry.html
@@ -1,38 +1,38 @@
-<fieldset>
-    <legend collapsed><span class="text">Contact Information</span>  <kc-tooltip>Expand this section to configure user's contact information.</kc-tooltip></legend>
-    <div class="form-group clearfix block">
-        <label class="col-md-2 control-label" for="street">Street</label>
-        <div class="col-md-6">
-            <input ng-model="user.attributes.street" class="form-control" type="text" name="street" id="street" />
-        </div>
-        <kc-tooltip>Street address.</kc-tooltip>
-    </div>
-    <div class="form-group clearfix block">
-        <label class="col-md-2 control-label" for="locality">City or Locality</label>
-        <div class="col-md-6">
-            <input ng-model="user.attributes.locality" class="form-control" type="text" name="locality" id="locality" />
-        </div>
-        <kc-tooltip>City or locality.</kc-tooltip>
-    </div>
-    <div class="form-group clearfix block">
-        <label class="col-md-2 control-label" for="region">State, Province, or Region</label>
-        <div class="col-md-6">
-            <input ng-model="user.attributes.region" class="form-control" type="text" name="region" id="region" />
-        </div>
-        <kc-tooltip>State, province, prefecture, or region.</kc-tooltip>
-    </div>
-    <div class="form-group clearfix block">
-        <label class="col-md-2 control-label" for="postal_code">Zip or Postal code</label>
-        <div class="col-md-6">
-            <input ng-model="user.attributes.postal_code" class="form-control" type="text" name="postal_code" id="postal_code" />
-        </div>
-        <kc-tooltip>Zip code or postal code.</kc-tooltip>
-    </div>
-    <div class="form-group clearfix block">
-        <label class="col-md-2 control-label" for="country">Country</label>
-        <div class="col-md-6">
-            <input ng-model="user.attributes.country" class="form-control" type="text" name="country" id="country" />
-        </div>
-        <kc-tooltip>Country name.</kc-tooltip>
-    </div>
+<fieldset>
+    <legend collapsed><span class="text">Contact Information</span>  <kc-tooltip>Expand this section to configure user's contact information.</kc-tooltip></legend>
+    <div class="form-group clearfix block">
+        <label class="col-md-2 control-label" for="street">Street</label>
+        <div class="col-md-6">
+            <input ng-model="user.attributes.street" class="form-control" type="text" name="street" id="street" />
+        </div>
+        <kc-tooltip>Street address.</kc-tooltip>
+    </div>
+    <div class="form-group clearfix block">
+        <label class="col-md-2 control-label" for="locality">City or Locality</label>
+        <div class="col-md-6">
+            <input ng-model="user.attributes.locality" class="form-control" type="text" name="locality" id="locality" />
+        </div>
+        <kc-tooltip>City or locality.</kc-tooltip>
+    </div>
+    <div class="form-group clearfix block">
+        <label class="col-md-2 control-label" for="region">State, Province, or Region</label>
+        <div class="col-md-6">
+            <input ng-model="user.attributes.region" class="form-control" type="text" name="region" id="region" />
+        </div>
+        <kc-tooltip>State, province, prefecture, or region.</kc-tooltip>
+    </div>
+    <div class="form-group clearfix block">
+        <label class="col-md-2 control-label" for="postal_code">Zip or Postal code</label>
+        <div class="col-md-6">
+            <input ng-model="user.attributes.postal_code" class="form-control" type="text" name="postal_code" id="postal_code" />
+        </div>
+        <kc-tooltip>Zip code or postal code.</kc-tooltip>
+    </div>
+    <div class="form-group clearfix block">
+        <label class="col-md-2 control-label" for="country">Country</label>
+        <div class="col-md-6">
+            <input ng-model="user.attributes.country" class="form-control" type="text" name="country" id="country" />
+        </div>
+        <kc-tooltip>Country name.</kc-tooltip>
+    </div>
 </fieldset>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-credentials.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-credentials.html
index 7c12f48..574dd49 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-credentials.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-credentials.html
@@ -1,60 +1,60 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
-        <li>{{user.username}}</li>
-    </ol>
-
-    <h1>{{user.username|capitalize}}</h1>
-
-    <kc-tabs-user></kc-tabs-user>
-
-    <form class="form-horizontal" name="userForm" novalidate>
-            <fieldset class="border-top">
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="password">New password <span class="required" data-ng-show="create">*</span></label>
-                    <div class="col-md-6">
-                        <input class="form-control" type="password" id="password" name="password" data-ng-model="password" required>
-                    </div>
-                </div>
-
-                <div class="form-group">
-                    <label class="col-md-2 control-label" for="confirmPassword">Password confirmation <span class="required" data-ng-show="create">*</span></label>
-                    <div class="col-md-6">
-                        <input class="form-control" type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword" required>
-                    </div>
-                </div>
-
-                <div class="form-group clearfix block">
-                    <label class="col-md-2 control-label" for="temporaryPassword">Temporary</label>
-                    <div class="col-sm-6">
-                        <input ng-model="temporaryPassword" name="temporaryPassword" id="temporaryPassword" onoffswitch />
-                    </div>
-                    <kc-tooltip>If enabled user is required to change password on next login</kc-tooltip>
-                </div>
-
-                <div class="form-group">
-                    <div class="col-md-10 col-md-offset-2" data-ng-show="password && confirmPassword">
-                        <button class="btn btn-danger" type="submit" data-ng-click="resetPassword(true)">Reset Password</button>
-                    </div>
-                </div>
-            </fieldset>
-
-            <fieldset class="border-top" data-ng-show="user.email || user.totp">
-                <div class="form-group" data-ng-show="user.email">
-                    <label class="col-md-2 control-label" for="password">Reset password email</label>
-                    <div class="col-sm-5">
-                        <button class="btn btn-danger" type="submit" data-ng-click="resetPasswordEmail()" tooltip="Send an email to user with a link to reset their password" tooltip-placement="right">Send Email</button>
-                    </div>
-                </div>
-
-                <div class="form-group" data-ng-show="user.totp">
-                    <label class="col-md-2 control-label">Remove totp</label>
-                    <div class="col-sm-5" data-ng-show="user.totp">
-                        <button class="btn btn-danger"  type="submit" data-ng-click="removeTotp()" tooltip="Remove one time password generator for user." tooltip-placement="right">Remove TOTP</button>
-                    </div>
-                </div>
-            </fieldset>
-        </form>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+        <li>{{user.username}}</li>
+    </ol>
+
+    <h1>{{user.username|capitalize}}</h1>
+
+    <kc-tabs-user></kc-tabs-user>
+
+    <form class="form-horizontal" name="userForm" novalidate>
+            <fieldset class="border-top">
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="password">New password <span class="required" data-ng-show="create">*</span></label>
+                    <div class="col-md-6">
+                        <input class="form-control" type="password" id="password" name="password" data-ng-model="password" required>
+                    </div>
+                </div>
+
+                <div class="form-group">
+                    <label class="col-md-2 control-label" for="confirmPassword">Password confirmation <span class="required" data-ng-show="create">*</span></label>
+                    <div class="col-md-6">
+                        <input class="form-control" type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword" required>
+                    </div>
+                </div>
+
+                <div class="form-group clearfix block">
+                    <label class="col-md-2 control-label" for="temporaryPassword">Temporary</label>
+                    <div class="col-sm-6">
+                        <input ng-model="temporaryPassword" name="temporaryPassword" id="temporaryPassword" onoffswitch />
+                    </div>
+                    <kc-tooltip>If enabled user is required to change password on next login</kc-tooltip>
+                </div>
+
+                <div class="form-group">
+                    <div class="col-md-10 col-md-offset-2" data-ng-show="password && confirmPassword">
+                        <button class="btn btn-danger" type="submit" data-ng-click="resetPassword(true)">Reset Password</button>
+                    </div>
+                </div>
+            </fieldset>
+
+            <fieldset class="border-top" data-ng-show="user.email || user.totp">
+                <div class="form-group" data-ng-show="user.email">
+                    <label class="col-md-2 control-label" for="password">Reset password email</label>
+                    <div class="col-sm-5">
+                        <button class="btn btn-danger" type="submit" data-ng-click="resetPasswordEmail()" tooltip="Send an email to user with a link to reset their password" tooltip-placement="right">Send Email</button>
+                    </div>
+                </div>
+
+                <div class="form-group" data-ng-show="user.totp">
+                    <label class="col-md-2 control-label">Remove totp</label>
+                    <div class="col-sm-5" data-ng-show="user.totp">
+                        <button class="btn btn-danger"  type="submit" data-ng-click="removeTotp()" tooltip="Remove one time password generator for user." tooltip-placement="right">Remove TOTP</button>
+                    </div>
+                </div>
+            </fieldset>
+        </form>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
index 1015522..f3e76f4 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
@@ -1,129 +1,129 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
-        <li data-ng-hide="create">{{user.username}}</li>
-        <li data-ng-show="create">Add User</li>
-    </ol>
-
-    <h1 data-ng-hide="create">{{user.username|capitalize}}<i id="removeUser" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers && !changed"
-    	data-ng-click="remove()"></i></h1>
-    <h1 data-ng-show="create">Add User</h1>
-
-    <kc-tabs-user></kc-tabs-user>
-
-    <form class="form-horizontal" name="userForm" novalidate kc-read-only="!access.manageUsers">
-
-        <fieldset class="border-top">
-            <div class="form-group">
-                <label class="col-md-2 control-label"for="id">ID</label>
-                <div class="col-md-6">
-                    <input class="form-control" type="text" id="id" name="id" data-ng-model="user.id" autofocus data-ng-readonly="true">
-                </div>
-            </div>
-            
-            <div class="form-group">
-                <label class="col-md-2 control-label"for="id">Created at</label>
-                <div class="col-md-6">
-                    {{user.createdTimestamp|date:'shortDate'}}&nbsp;{{user.createdTimestamp|date:'mediumTime'}}
-                </div>
-            </div>
-
-            <div class="form-group">
-                <label class="col-md-2 control-label"for="username">Username <span class="required" data-ng-show="create">*</span></label>
-                <div class="col-md-6">
-                    <!-- Characters >,<,/,\ are forbidden in username -->
-                    <input class="form-control" type="text" id="username" name="username" data-ng-model="user.username" autofocus
-                           required ng-pattern="/^[^\<\>\\\/]*$/" data-ng-readonly="!editUsername">
-                </div>
-            </div>
-
-
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="email">Email</label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="email" name="email" id="email"
-                           data-ng-model="user.email">
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="firstName">First Name</label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" name="firstName" id="firstName"
-                           data-ng-model="user.firstName">
-                </div>
-            </div>
-            <div class="form-group">
-                <label class="col-md-2 control-label" for="lastName">Last Name</label>
-
-                <div class="col-md-6">
-                    <input class="form-control" type="text" name="lastName" id="lastName"
-                           data-ng-model="user.lastName">
-                </div>
-            </div>
-
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="userEnabled">User Enabled</label>
-                <div class="col-md-6">
-                    <input ng-model="user.enabled" name="userEnabled" id="userEnabled" ng-disabled="!access.manageUsers" onoffswitch />
-                </div>
-                <kc-tooltip>A disabled user cannot login.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix block" data-ng-show="!create && user.federationLink">
-                <label class="col-md-2 control-label" for="userEnabled">Federation Link</label>
-                <div class="col-md-6">
-                    <a href="{{federationLink}}">{{federationLinkName}}</a>
-                </div>
-            </div>
-            <div class="form-group clearfix block">
-                <label class="col-md-2 control-label" for="emailVerified">Email verified</label>
-                <div class="col-md-6">
-                    <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" ng-disabled="!access.manageUsers" onoffswitch />
-                </div>
-                <kc-tooltip>Has the user's email been verified?</kc-tooltip>
-            </div>
-            <div class="form-group clearfix">
-                <label class="col-md-2 control-label" for="reqActions">Required User Actions</label>
-
-                <div class="col-md-6">
-                    <select ui-select2 id="reqActions" ng-model="user.requiredActions" data-placeholder="Select an action..." multiple>
-                        <option ng-repeat="action in userReqActionList" value="{{action.alias}}">{{action.name}}</option>
-                    </select>
-                </div>
-                <kc-tooltip>Require an action when the user logs in. 'Verify email' sends an email to the user to verify their email address.  'Update profile' requires user to enter in new personal information.  'Update password' requires user to enter in a new password.  'Configure TOTP' requires setup of a mobile password generator.</kc-tooltip>
-            </div>
-            <div class="form-group clearfix" data-ng-if="realm.internationalizationEnabled">
-                <label class="col-md-2 control-label" for="locale">Locale</label>
-                <div class="col-md-6">
-                    <div>
-                        <select class="form-control" id="locale"
-                                ng-model="user.attributes.locale"
-                                ng-options="o as o for o in realm.supportedLocales">
-                            <option value="" disabled selected>Select one...</option>
-                        </select>
-                    </div>
-                </div>
-            </div>
-        </fieldset>
-
-        <div data-ng-include data-src="resourceUrl + '/partials/user-attribute-entry.html'"></div>
-
-
-        <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
-                <button kc-save data-ng-show="changed">Save</button>
-                <button kc-cancel data-ng-click="cancel()">Cancel</button>
-            </div>
-
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
-                <button kc-save  data-ng-show="access.manageUsers && changed">Save</button>
-                <button kc-reset data-ng-show="access.manageUsers && changed">Cancel</button>
-                <button data-ng-show="access.impersonation" class="btn btn-default" data-ng-click="impersonate()" tooltip="Login as this user.  If user is in same realm as you, your current login session will be logged out before you are logged in as this user.">Impersonate</button>
-            </div>
-        </div>
-
-    </form>
-</div>
-
-<kc-menu></kc-menu>
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+        <li data-ng-hide="create">{{user.username}}</li>
+        <li data-ng-show="create">Add User</li>
+    </ol>
+
+    <h1 data-ng-hide="create">{{user.username|capitalize}}<i id="removeUser" class="pficon pficon-delete clickable" data-ng-show="!create && access.manageUsers && !changed"
+    	data-ng-click="remove()"></i></h1>
+    <h1 data-ng-show="create">Add User</h1>
+
+    <kc-tabs-user></kc-tabs-user>
+
+    <form class="form-horizontal" name="userForm" novalidate kc-read-only="!access.manageUsers">
+
+        <fieldset class="border-top">
+            <div class="form-group">
+                <label class="col-md-2 control-label"for="id">ID</label>
+                <div class="col-md-6">
+                    <input class="form-control" type="text" id="id" name="id" data-ng-model="user.id" autofocus data-ng-readonly="true">
+                </div>
+            </div>
+            
+            <div class="form-group">
+                <label class="col-md-2 control-label"for="id">Created at</label>
+                <div class="col-md-6">
+                    {{user.createdTimestamp|date:'shortDate'}}&nbsp;{{user.createdTimestamp|date:'mediumTime'}}
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label class="col-md-2 control-label"for="username">Username <span class="required" data-ng-show="create">*</span></label>
+                <div class="col-md-6">
+                    <!-- Characters >,<,/,\ are forbidden in username -->
+                    <input class="form-control" type="text" id="username" name="username" data-ng-model="user.username" autofocus
+                           required ng-pattern="/^[^\<\>\\\/]*$/" data-ng-readonly="!editUsername">
+                </div>
+            </div>
+
+
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="email">Email</label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="email" name="email" id="email"
+                           data-ng-model="user.email">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="firstName">First Name</label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" name="firstName" id="firstName"
+                           data-ng-model="user.firstName">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="lastName">Last Name</label>
+
+                <div class="col-md-6">
+                    <input class="form-control" type="text" name="lastName" id="lastName"
+                           data-ng-model="user.lastName">
+                </div>
+            </div>
+
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="userEnabled">User Enabled</label>
+                <div class="col-md-6">
+                    <input ng-model="user.enabled" name="userEnabled" id="userEnabled" ng-disabled="!access.manageUsers" onoffswitch />
+                </div>
+                <kc-tooltip>A disabled user cannot login.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="!create && user.federationLink">
+                <label class="col-md-2 control-label" for="userEnabled">Federation Link</label>
+                <div class="col-md-6">
+                    <a href="{{federationLink}}">{{federationLinkName}}</a>
+                </div>
+            </div>
+            <div class="form-group clearfix block">
+                <label class="col-md-2 control-label" for="emailVerified">Email verified</label>
+                <div class="col-md-6">
+                    <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" ng-disabled="!access.manageUsers" onoffswitch />
+                </div>
+                <kc-tooltip>Has the user's email been verified?</kc-tooltip>
+            </div>
+            <div class="form-group clearfix">
+                <label class="col-md-2 control-label" for="reqActions">Required User Actions</label>
+
+                <div class="col-md-6">
+                    <select ui-select2 id="reqActions" ng-model="user.requiredActions" data-placeholder="Select an action..." multiple>
+                        <option ng-repeat="action in userReqActionList" value="{{action.alias}}">{{action.name}}</option>
+                    </select>
+                </div>
+                <kc-tooltip>Require an action when the user logs in. 'Verify email' sends an email to the user to verify their email address.  'Update profile' requires user to enter in new personal information.  'Update password' requires user to enter in a new password.  'Configure TOTP' requires setup of a mobile password generator.</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-if="realm.internationalizationEnabled">
+                <label class="col-md-2 control-label" for="locale">Locale</label>
+                <div class="col-md-6">
+                    <div>
+                        <select class="form-control" id="locale"
+                                ng-model="user.attributes.locale"
+                                ng-options="o as o for o in realm.supportedLocales">
+                            <option value="" disabled selected>Select one...</option>
+                        </select>
+                    </div>
+                </div>
+            </div>
+        </fieldset>
+
+        <div data-ng-include data-src="resourceUrl + '/partials/user-attribute-entry.html'"></div>
+
+
+        <div class="form-group">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageUsers">
+                <button kc-save data-ng-show="changed">Save</button>
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+            </div>
+
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
+                <button kc-save  data-ng-show="access.manageUsers && changed">Save</button>
+                <button kc-reset data-ng-show="access.manageUsers && changed">Cancel</button>
+                <button data-ng-show="access.impersonation" class="btn btn-default" data-ng-click="impersonate()" tooltip="Login as this user.  If user is in same realm as you, your current login session will be logged out before you are logged in as this user.">Impersonate</button>
+            </div>
+        </div>
+
+    </form>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html
index dfc8c45..e25615d 100644
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html
@@ -1,45 +1,45 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
-        <li>{{user.username}}</li>
-    </ol>
-
-    <h1>{{user.username|capitalize}}</h1>
-
-    <kc-tabs-user></kc-tabs-user>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-            <tr>
-                <th class="kc-table-actions" colspan="4">
-                    <div class="form-inline">
-                        <div class="pull-right" data-ng-show="hasAnyProvidersToCreate()">
-                            <a class="btn btn-primary" href="#/create/federated-identity/{{realm.realm}}/{{user.id}}">Create</a>
-                        </div>
-                    </div>
-                </th>
-            </tr>
-            <tr data-ng-hide="federatedIdentities.length == 0">
-                <th>Identity Provider Alias</th>
-                <th>Provider user ID</th>
-                <th>Provider username</th>
-                <th>Action</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr data-ng-repeat="identity in federatedIdentities">
-                <td>{{identity.identityProvider}}</td>
-                <td>{{identity.userId}}</td>
-                <td>{{identity.userName}}</td>
-                <td class="actions">
-                    <div class="action-div"><i class="pficon pficon-delete" ng-click="removeProviderLink(identity)" tooltip-placement="right" tooltip="Remove Provider Link"></i></div>
-                </td>
-            </tr>
-            <tr data-ng-show="federatedIdentities.length == 0">
-                <td>No identity provider links available</td>
-            </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+        <li>{{user.username}}</li>
+    </ol>
+
+    <h1>{{user.username|capitalize}}</h1>
+
+    <kc-tabs-user></kc-tabs-user>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+            <tr>
+                <th class="kc-table-actions" colspan="4">
+                    <div class="form-inline">
+                        <div class="pull-right" data-ng-show="hasAnyProvidersToCreate()">
+                            <a class="btn btn-primary" href="#/create/federated-identity/{{realm.realm}}/{{user.id}}">Create</a>
+                        </div>
+                    </div>
+                </th>
+            </tr>
+            <tr data-ng-hide="federatedIdentities.length == 0">
+                <th>Identity Provider Alias</th>
+                <th>Provider user ID</th>
+                <th>Provider username</th>
+                <th>Action</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr data-ng-repeat="identity in federatedIdentities">
+                <td>{{identity.identityProvider}}</td>
+                <td>{{identity.userId}}</td>
+                <td>{{identity.userName}}</td>
+                <td class="actions">
+                    <div class="action-div"><i class="pficon pficon-delete" ng-click="removeProviderLink(identity)" tooltip-placement="right" tooltip="Remove Provider Link"></i></div>
+                </td>
+            </tr>
+            <tr data-ng-show="federatedIdentities.length == 0">
+                <td>No identity provider links available</td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federation.html
index 2162127..047b345 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federation.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federation.html
@@ -1,40 +1,40 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>
-        <span>User Federation</span>
-    </h1>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr ng-show="providers.length > 0 && access.manageUsers">
-            <th colspan="3" class="kc-table-actions">
-                <div class="pull-right">
-                    <div>
-                        <select class="form-control" ng-model="selectedProvider"
-                                ng-options="p.id for p in providers"
-                                data-ng-change="addProvider(selectedProvider); selectedProvider = null">
-                            <option value="" disabled selected>Add provider...</option>
-                        </select>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-show="instances && instances.length > 0">
-            <th>ID</th>
-            <th>Provider Name</th>
-            <th>Priority</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-repeat="instance in instances">
-            <td><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">{{instance.displayName}}</a></td>
-            <td>{{instance.providerName|capitalize}}</td>
-            <td>{{instance.priority}}</td>
-         </tr>
-        <tr data-ng-show="!instances || instances.length == 0">
-            <td class="text-muted">No user federation providers configured</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>
+        <span>User Federation</span>
+    </h1>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr ng-show="providers.length > 0 && access.manageUsers">
+            <th colspan="3" class="kc-table-actions">
+                <div class="pull-right">
+                    <div>
+                        <select class="form-control" ng-model="selectedProvider"
+                                ng-options="p.id for p in providers"
+                                data-ng-change="addProvider(selectedProvider); selectedProvider = null">
+                            <option value="" disabled selected>Add provider...</option>
+                        </select>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr data-ng-show="instances && instances.length > 0">
+            <th>ID</th>
+            <th>Provider Name</th>
+            <th>Priority</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="instance in instances">
+            <td><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">{{instance.displayName}}</a></td>
+            <td>{{instance.providerName|capitalize}}</td>
+            <td>{{instance.priority}}</td>
+         </tr>
+        <tr data-ng-show="!instances || instances.length == 0">
+            <td class="text-muted">No user federation providers configured</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
index fb47296..67332fa 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
@@ -1,64 +1,64 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <h1>Users</h1>
-
-    <table class="table table-striped table-bordered">
-        <caption data-ng-show="users" class="hidden">Table of realm users</caption>
-        <thead>
-        <tr>
-            <th colspan="{{access.impersonation == true ? '5' : '4'}}">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="Search..." data-ng-model="query.search" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('userSearch').click()">
-                            <div class="input-group-addon">
-                                    <i class="fa fa-search" id="userSearch" data-ng-click="firstPage()"></i>
-                            </div>
-                        </div>
-                    </div>
-                    <button id="viewAllUsers" class="btn btn-default" ng-click="query.search = null; firstPage()">View all users</button>
-
-                    <div class="pull-right" data-ng-show="access.manageUsers">
-                        <a id="createUser" class="btn btn-default" href="#/create/user/{{realm.realm}}">Add User</a>
-                    </div>
-                </div>
-            </th>
-        </tr>
-        <tr>
-        <tr data-ng-show="searchLoaded && users.length > 0">
-            <th>Username</th>
-            <th>Last Name</th>
-            <th>First Name</th>
-            <th>Email</th>
-            <th data-ng-show="access.impersonation"></th>
-        </tr>
-        </tr>
-        </thead>
-        <tfoot data-ng-show="users && (users.length >= query.max || query.first > 0)">
-        <tr>
-            <td colspan="7">
-                <div class="table-nav">
-                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
-                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
-                    <button data-ng-click="nextPage()" class="next" ng-disabled="users.length < query.max">Next page</button>
-                </div>
-            </td>
-        </tr>
-        </tfoot>
-        <tbody>
-        <tr ng-repeat="user in users">
-            <td><a href="#/realms/{{realm.realm}}/users/{{user.id}}">{{user.username}}</a></td>
-            <td>{{user.lastName}}</td>
-            <td>{{user.firstName}}</td>
-            <td>{{user.email}}</td>
-            <td data-ng-show="access.impersonation"><button class="btn btn-default" data-ng-click="impersonate(user.id)" tooltip="Login as this user.  If user is in same realm as you, your current login session will be logged out before you are logged in as this user.">Impersonate</button></td>
-        </tr>
-        <tr data-ng-show="!users || users.length == 0">
-            <td class="text-muted" data-ng-show="!users">Please enter a search, or click on view all users</td>
-            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch != null">No results</td>
-            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch == null">No users available</td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <h1>Users</h1>
+
+    <table class="table table-striped table-bordered">
+        <caption data-ng-show="users" class="hidden">Table of realm users</caption>
+        <thead>
+        <tr>
+            <th colspan="{{access.impersonation == true ? '5' : '4'}}">
+                <div class="form-inline">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <input type="text" placeholder="Search..." data-ng-model="query.search" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('userSearch').click()">
+                            <div class="input-group-addon">
+                                    <i class="fa fa-search" id="userSearch" data-ng-click="firstPage()"></i>
+                            </div>
+                        </div>
+                    </div>
+                    <button id="viewAllUsers" class="btn btn-default" ng-click="query.search = null; firstPage()">View all users</button>
+
+                    <div class="pull-right" data-ng-show="access.manageUsers">
+                        <a id="createUser" class="btn btn-default" href="#/create/user/{{realm.realm}}">Add User</a>
+                    </div>
+                </div>
+            </th>
+        </tr>
+        <tr>
+        <tr data-ng-show="searchLoaded && users.length > 0">
+            <th>Username</th>
+            <th>Last Name</th>
+            <th>First Name</th>
+            <th>Email</th>
+            <th data-ng-show="access.impersonation"></th>
+        </tr>
+        </tr>
+        </thead>
+        <tfoot data-ng-show="users && (users.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="users.length < query.max">Next page</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
+        <tbody>
+        <tr ng-repeat="user in users">
+            <td><a href="#/realms/{{realm.realm}}/users/{{user.id}}">{{user.username}}</a></td>
+            <td>{{user.lastName}}</td>
+            <td>{{user.firstName}}</td>
+            <td>{{user.email}}</td>
+            <td data-ng-show="access.impersonation"><button class="btn btn-default" data-ng-click="impersonate(user.id)" tooltip="Login as this user.  If user is in same realm as you, your current login session will be logged out before you are logged in as this user.">Impersonate</button></td>
+        </tr>
+        <tr data-ng-show="!users || users.length == 0">
+            <td class="text-muted" data-ng-show="!users">Please enter a search, or click on view all users</td>
+            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch != null">No results</td>
+            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch == null">No users available</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
 <kc-menu></kc-menu>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
index dfca549..8aa0cc7 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
@@ -1,45 +1,45 @@
-    <div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
-    <ol class="breadcrumb">
-        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
-        <li>{{user.username}}</li>
-    </ol>
-
-    <h1>{{user.username|capitalize}}</h1>
-
-    <kc-tabs-user></kc-tabs-user>
-
-    <table class="table table-striped table-bordered">
-        <thead>
-        <tr data-ng-show="access.manageUsers">
-            <th class="kc-table-actions" colspan="6">
-                <div class="pull-right" data-ng-show="access.manageUsers">
-                    <a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">Logout All Sessions</a>
-                </div>
-            </th>
-        </tr>
-        <tr>
-            <th>IP Address</th>
-            <th>Started</th>
-            <th>Last Access</th>
-            <th>Clients</th>
-            <th data-ng-show="access.manageUsers">Action</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr data-ng-repeat="session in sessions">
-            <td>{{session.ipAddress}}</td>
-            <td>{{session.start | date:'medium'}}</td>
-            <td>{{session.lastAccess | date:'medium'}}</td>
-            <td>
-                <div data-ng-repeat="(id, clientId) in session.clients">
-                    <a href="#/realms/{{realm.realm}}/clients/{{id}}">{{clientId}}</a>
-                </div>
-            </ul>
-            </td>
-            <td data-ng-show="access.manageUsers"><a  href="" ng-click="logoutSession(session.id)">logout</a> </td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
-<kc-menu></kc-menu>
+    <div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+        <li>{{user.username}}</li>
+    </ol>
+
+    <h1>{{user.username|capitalize}}</h1>
+
+    <kc-tabs-user></kc-tabs-user>
+
+    <table class="table table-striped table-bordered">
+        <thead>
+        <tr data-ng-show="access.manageUsers">
+            <th class="kc-table-actions" colspan="6">
+                <div class="pull-right" data-ng-show="access.manageUsers">
+                    <a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">Logout All Sessions</a>
+                </div>
+            </th>
+        </tr>
+        <tr>
+            <th>IP Address</th>
+            <th>Started</th>
+            <th>Last Access</th>
+            <th>Clients</th>
+            <th data-ng-show="access.manageUsers">Action</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr data-ng-repeat="session in sessions">
+            <td>{{session.ipAddress}}</td>
+            <td>{{session.start | date:'medium'}}</td>
+            <td>{{session.lastAccess | date:'medium'}}</td>
+            <td>
+                <div data-ng-repeat="(id, clientId) in session.clients">
+                    <a href="#/realms/{{realm.realm}}/clients/{{id}}">{{clientId}}</a>
+                </div>
+            </ul>
+            </td>
+            <td data-ng-show="access.manageUsers"><a  href="" ng-click="logoutSession(session.id)">logout</a> </td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
index d53dd3c..ed6aa8f 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
@@ -1,48 +1,48 @@
-<div kc-sidebar-resize class="col-sm-3 col-md-2 col-sm-pull-9 col-md-pull-10 sidebar-pf sidebar-pf-left" data-ng-controller="RealmDropdownCtrl">
-
-    <div class="realm-selector">
-      <h2 data-ng-show="current.realm">{{current.realm.realm|capitalize}} <i class="fa fa-angle-down"></i></h2>
-      <h2 data-ng-hide="current.realm">Select realm <i class="fa fa-angle-down"></i></h2>
-      <div class="realm-dropmenu">
-        <!-- if it has more than 5 it generates a scroll bar -->
-        <ul>
-            <li data-ng-repeat="realm in current.realms | orderBy:'realm'" data-ng-if="realm.realm != current.realm.realm">
-                <a href="" ng-click="changeRealm(realm.realm)">{{realm.realm|capitalize}}</a>
-            </li>
-        </ul>
-        <div class="realm-add" data-ng-show="auth.user && access.createRealm">
-          <a href="#/create/realm" class="btn btn-sm btn-block btn-primary">Add Realm</a>
-        </div>
-      </div>
-    </div>
-
-    <div class="nav-category" data-ng-show="current.realm">
-        <h2>Configure</h2>
-        <ul class="nav nav-pills nav-stacked">
-            <li data-ng-show="access.viewRealm" data-ng-class="((!path[2]
-    || path[2] == 'required-credentials'
-    || path[2] == 'login-settings'
-    || path[2] == 'theme-settings'
-    || path[2] == 'token-settings'
-    || path[2] == 'cache-settings'
-    || path[2] == 'defense'
-    || path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'clients') && 'active'">
-                <a href="#/realms/{{realm.realm}}"><span class="pficon pficon-settings"></span> Settings</a>
-            </li>
-            <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'clients' || path[1] == 'client' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients"><i class="fa fa-cubes"></i> Clients</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || path[2] == 'default-roles' || (path[1] == 'role' && path[3] != 'clients')) && 'active'"><a href="#/realms/{{realm.realm}}/roles"><i class="fa fa-tasks"></i> Roles</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> Identity Providers</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'user-federation' || path[2] == 'user-federation') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> User Federation</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'authentication' || path[2] == 'authentication') && 'active'"><a href="#/realms/{{realm.realm}}/authentication/flows"><i class="fa fa-lock"></i> Authentication</a></li>
-        </ul>
-    </div>
-
-    <div class="nav-category" data-ng-show="current.realm">
-        <h2>Manage</h2>
-        <ul class="nav nav-pills nav-stacked">
-            <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users"><span class="pficon pficon-users"></span> Users</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm"><i class="fa fa-clock-o"></i> Sessions</a></li>
-            <li data-ng-show="access.viewEvents" data-ng-class="(path[2] == 'events' || path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events"><i class="fa fa-calendar"></i> Events</a></li>
-        </ul>
-    </div>
+<div kc-sidebar-resize class="col-sm-3 col-md-2 col-sm-pull-9 col-md-pull-10 sidebar-pf sidebar-pf-left" data-ng-controller="RealmDropdownCtrl">
+
+    <div class="realm-selector">
+      <h2 data-ng-show="current.realm">{{current.realm.realm|capitalize}} <i class="fa fa-angle-down"></i></h2>
+      <h2 data-ng-hide="current.realm">Select realm <i class="fa fa-angle-down"></i></h2>
+      <div class="realm-dropmenu">
+        <!-- if it has more than 5 it generates a scroll bar -->
+        <ul>
+            <li data-ng-repeat="realm in current.realms | orderBy:'realm'" data-ng-if="realm.realm != current.realm.realm">
+                <a href="" ng-click="changeRealm(realm.realm)">{{realm.realm|capitalize}}</a>
+            </li>
+        </ul>
+        <div class="realm-add" data-ng-show="auth.user && access.createRealm">
+          <a href="#/create/realm" class="btn btn-sm btn-block btn-primary">Add Realm</a>
+        </div>
+      </div>
+    </div>
+
+    <div class="nav-category" data-ng-show="current.realm">
+        <h2>Configure</h2>
+        <ul class="nav nav-pills nav-stacked">
+            <li data-ng-show="access.viewRealm" data-ng-class="((!path[2]
+    || path[2] == 'required-credentials'
+    || path[2] == 'login-settings'
+    || path[2] == 'theme-settings'
+    || path[2] == 'token-settings'
+    || path[2] == 'cache-settings'
+    || path[2] == 'defense'
+    || path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'clients') && 'active'">
+                <a href="#/realms/{{realm.realm}}"><span class="pficon pficon-settings"></span> Settings</a>
+            </li>
+            <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'clients' || path[1] == 'client' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients"><i class="fa fa-cubes"></i> Clients</a></li>
+            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || path[2] == 'default-roles' || (path[1] == 'role' && path[3] != 'clients')) && 'active'"><a href="#/realms/{{realm.realm}}/roles"><i class="fa fa-tasks"></i> Roles</a></li>
+            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> Identity Providers</a></li>
+            <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'user-federation' || path[2] == 'user-federation') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> User Federation</a></li>
+            <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'authentication' || path[2] == 'authentication') && 'active'"><a href="#/realms/{{realm.realm}}/authentication/flows"><i class="fa fa-lock"></i> Authentication</a></li>
+        </ul>
+    </div>
+
+    <div class="nav-category" data-ng-show="current.realm">
+        <h2>Manage</h2>
+        <ul class="nav nav-pills nav-stacked">
+            <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users"><span class="pficon pficon-users"></span> Users</a></li>
+            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm"><i class="fa fa-clock-o"></i> Sessions</a></li>
+            <li data-ng-show="access.viewEvents" data-ng-class="(path[2] == 'events' || path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events"><i class="fa fa-calendar"></i> Events</a></li>
+        </ul>
+    </div>
 </div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
index 9268939..98c206e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
@@ -1,28 +1,28 @@
-<div data-ng-repeat="option in properties" class="form-group">
-    <label class="col-md-2 control-label">{{option.label}}</label>
-
-    <div class="col-sm-6" data-ng-hide="option.type == 'boolean' || option.type == 'List' || option.type == 'Role' || option.type == 'ClientList'">
-        <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
-    </div>
-    <div class="col-sm-6" data-ng-show="option.type == 'boolean'">
-        <input ng-model="config[ option.name ]" value="'true'" name="option.name" id="option.name" onoffswitchmodel />
-    </div>
-    <div class="col-sm-6" data-ng-show="option.type == 'List'">
-        <select ng-model="config[ option.name ]" ng-options="data for data in option.defaultValue">
-            <option value="" selected> Select one... </option>
-        </select>
-    </div>
-    <div class="col-sm-6" data-ng-show="option.type == 'Role'">
-        <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
-    </div>
-    <div class="col-sm-4" data-ng-show="option.type == 'Role'">
-        <button type="submit" data-ng-click="openRoleSelector(option.name)" class="btn btn-default" tooltip="Enter role in the textbox to the left, or click this button to browse and select the role you want">Select Role</button>
-    </div>
-    <div class="col-sm-4" data-ng-show="option.type == 'ClientList'">
-        <select ng-model="config[ option.name ]" ng-options="client.clientId as client.clientId for client in clients">
-            <option value="" selected> Select one... </option>
-        </select>
-    </div>
-
-    <kc-tooltip>{{option.helpText}}</kc-tooltip>
-</div>
+<div data-ng-repeat="option in properties" class="form-group">
+    <label class="col-md-2 control-label">{{option.label}}</label>
+
+    <div class="col-sm-6" data-ng-hide="option.type == 'boolean' || option.type == 'List' || option.type == 'Role' || option.type == 'ClientList'">
+        <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
+    </div>
+    <div class="col-sm-6" data-ng-show="option.type == 'boolean'">
+        <input ng-model="config[ option.name ]" value="'true'" name="option.name" id="option.name" onoffswitchmodel />
+    </div>
+    <div class="col-sm-6" data-ng-show="option.type == 'List'">
+        <select ng-model="config[ option.name ]" ng-options="data for data in option.defaultValue">
+            <option value="" selected> Select one... </option>
+        </select>
+    </div>
+    <div class="col-sm-6" data-ng-show="option.type == 'Role'">
+        <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
+    </div>
+    <div class="col-sm-4" data-ng-show="option.type == 'Role'">
+        <button type="submit" data-ng-click="openRoleSelector(option.name)" class="btn btn-default" tooltip="Enter role in the textbox to the left, or click this button to browse and select the role you want">Select Role</button>
+    </div>
+    <div class="col-sm-4" data-ng-show="option.type == 'ClientList'">
+        <select ng-model="config[ option.name ]" ng-options="client.clientId as client.clientId for client in clients">
+            <option value="" selected> Select one... </option>
+        </select>
+    </div>
+
+    <kc-tooltip>{{option.helpText}}</kc-tooltip>
+</div>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
index 1f8cd86..e3a3456 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/login.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
@@ -1,76 +1,76 @@
-<#import "template.ftl" as layout>
-<@layout.registrationLayout displayInfo=social.displayInfo; section>
-    <#if section = "title">
-        ${msg("loginTitle",(realm.name!''))}
-    <#elseif section = "header">
-        ${msg("loginTitleHtml",(realm.name!''))}
-    <#elseif section = "form">
-        <#if realm.password>
-            <form id="kc-form-login" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
-                <div class="${properties.kcFormGroupClass!}">
-                    <div class="${properties.kcLabelWrapperClass!}">
-                        <label for="username" class="${properties.kcLabelClass!}"><#if !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
-                    </div>
-
-                    <div class="${properties.kcInputWrapperClass!}">
-                        <input id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')?html}" type="text" autofocus />
-                    </div>
-                </div>
-
-                <div class="${properties.kcFormGroupClass!}">
-                    <div class="${properties.kcLabelWrapperClass!}">
-                        <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
-                    </div>
-
-                    <div class="${properties.kcInputWrapperClass!}">
-                        <input id="password" class="${properties.kcInputClass!}" name="password" type="password" />
-                    </div>
-                </div>
-
-                <div class="${properties.kcFormGroupClass!}">
-                    <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
-                        <#if realm.rememberMe>
-                            <div class="checkbox">
-                                <label>
-                                    <#if login.rememberMe??>
-                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3" checked> ${msg("rememberMe")}
-                                    <#else>
-                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3"> ${msg("rememberMe")}
-                                    </#if>
-                                </label>
-                            </div>
-                        </#if>
-                        <div class="${properties.kcFormOptionsWrapperClass!}">
-                            <#if realm.resetPasswordAllowed>
-                                <span><a href="${url.loginPasswordResetUrl}">${msg("doForgotPassword")}</a></span>
-                            </#if>
-                        </div>
-                    </div>
-
-                    <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
-                        <div class="${properties.kcFormButtonsWrapperClass!}">
-                            <input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
-                            <input class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="cancel" id="kc-cancel" type="submit" value="${msg("doCancel")}"/>
-                        </div>
-                     </div>
-                </div>
-            </form>
-        </#if>
-    <#elseif section = "info" >
-        <#if realm.password && realm.registrationAllowed>
-            <div id="kc-registration">
-                <span>${msg("noAccount")} <a href="${url.registrationUrl}">${msg("doRegister")}</a></span>
-            </div>
-        </#if>
-
-        <#if realm.password && social.providers??>
-            <div id="kc-social-providers">
-                <ul>
-                    <#list social.providers as p>
-                        <li><a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}"> <span class="text">${p.alias}</span></a></li>
-                    </#list>
-                </ul>
-            </div>
-        </#if>
-    </#if>
-</@layout.registrationLayout>
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=social.displayInfo; section>
+    <#if section = "title">
+        ${msg("loginTitle",(realm.name!''))}
+    <#elseif section = "header">
+        ${msg("loginTitleHtml",(realm.name!''))}
+    <#elseif section = "form">
+        <#if realm.password>
+            <form id="kc-form-login" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
+                <div class="${properties.kcFormGroupClass!}">
+                    <div class="${properties.kcLabelWrapperClass!}">
+                        <label for="username" class="${properties.kcLabelClass!}"><#if !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
+                    </div>
+
+                    <div class="${properties.kcInputWrapperClass!}">
+                        <input id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')?html}" type="text" autofocus />
+                    </div>
+                </div>
+
+                <div class="${properties.kcFormGroupClass!}">
+                    <div class="${properties.kcLabelWrapperClass!}">
+                        <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
+                    </div>
+
+                    <div class="${properties.kcInputWrapperClass!}">
+                        <input id="password" class="${properties.kcInputClass!}" name="password" type="password" />
+                    </div>
+                </div>
+
+                <div class="${properties.kcFormGroupClass!}">
+                    <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                        <#if realm.rememberMe>
+                            <div class="checkbox">
+                                <label>
+                                    <#if login.rememberMe??>
+                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3" checked> ${msg("rememberMe")}
+                                    <#else>
+                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3"> ${msg("rememberMe")}
+                                    </#if>
+                                </label>
+                            </div>
+                        </#if>
+                        <div class="${properties.kcFormOptionsWrapperClass!}">
+                            <#if realm.resetPasswordAllowed>
+                                <span><a href="${url.loginPasswordResetUrl}">${msg("doForgotPassword")}</a></span>
+                            </#if>
+                        </div>
+                    </div>
+
+                    <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                        <div class="${properties.kcFormButtonsWrapperClass!}">
+                            <input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
+                            <input class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="cancel" id="kc-cancel" type="submit" value="${msg("doCancel")}"/>
+                        </div>
+                     </div>
+                </div>
+            </form>
+        </#if>
+    <#elseif section = "info" >
+        <#if realm.password && realm.registrationAllowed>
+            <div id="kc-registration">
+                <span>${msg("noAccount")} <a href="${url.registrationUrl}">${msg("doRegister")}</a></span>
+            </div>
+        </#if>
+
+        <#if realm.password && social.providers??>
+            <div id="kc-social-providers">
+                <ul>
+                    <#list social.providers as p>
+                        <li><a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}"> <span class="text">${p.alias}</span></a></li>
+                    </#list>
+                </ul>
+            </div>
+        </#if>
+    </#if>
+</@layout.registrationLayout>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/register.ftl b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
index cf7bd1d..4ccd0bc 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/register.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
@@ -1,131 +1,131 @@
-<#import "template.ftl" as layout>
-<@layout.registrationLayout; section>
-    <#if section = "title">
-        ${msg("registerWithTitle",(realm.name!''))}
-    <#elseif section = "header">
-         ${msg("registerWithTitleHtml",(realm.name!''))}
-    <#elseif section = "form">
-        <form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.registrationAction}" method="post">
-          <#if !realm.registrationEmailAsUsername>
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('username',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" id="username" class="${properties.kcInputClass!}" name="username" value="${(register.formData.username!'')?html}" />
-                </div>
-            </div>
-          </#if>
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('firstName',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" id="firstName" class="${properties.kcInputClass!}" name="firstName" value="${(register.formData.firstName!'')?html}" />
-                </div>
-            </div>
-
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('lastName',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" id="lastName" class="${properties.kcInputClass!}" name="lastName" value="${(register.formData.lastName!'')?html}" />
-                </div>
-            </div>
-
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('email',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" id="email" class="${properties.kcInputClass!}" name="email" value="${(register.formData.email!'')?html}" />
-                </div>
-            </div>
-
-            <#if passwordRequired>
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('password',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="password" id="password" class="${properties.kcInputClass!}" name="password" />
-                </div>
-            </div>
-
-            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('password-confirm',properties.kcFormGroupErrorClass!)}">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="password-confirm" class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
-                </div>
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="password" id="password-confirm" class="${properties.kcInputClass!}" name="password-confirm" />
-                </div>
-            </div>
-            </#if>
-            <div class="form-group">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="user.attributes.street" class="${properties.kcLabelClass!}">${msg("street")}</label>
-                </div>
-
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.street" name="user.attributes.street"/>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="user.attributes.locality" class="${properties.kcLabelClass!}">${msg("locality")}</label>
-                </div>
-
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.locality" name="user.attributes.locality"/>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="user.attributes.region" class="${properties.kcLabelClass!}">${msg("region")}</label>
-                </div>
-
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.region" name="user.attributes.region"/>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="user.attributes.postal_code" class="${properties.kcLabelClass!}">${msg("postal_code")}</label>
-                </div>
-
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.postal_code" name="user.attributes.postal_code"/>
-                </div>
-            </div>
-            <div class="form-group">
-                <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="user.attributes.country" class="${properties.kcLabelClass!}">${msg("country")}</label>
-                </div>
-
-                <div class="${properties.kcInputWrapperClass!}">
-                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.country" name="user.attributes.country"/>
-                </div>
-            </div>
-            <#if recaptchaRequired??>
-            <div class="form-group">
-                <div class="${properties.kcInputWrapperClass!}">
-                    <div class="g-recaptcha" data-size="compact" data-sitekey="${recaptchaSiteKey}"></div>
-                </div>
-            </div>
-            </#if>
-
-            <div class="${properties.kcFormGroupClass!}">
-                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
-                    <div class="${properties.kcFormOptionsWrapperClass!}">
-                        <span><a href="${url.loginUrl}">${msg("backToLogin")}</a></span>
-                    </div>
-                </div>
-
-                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
-                    <input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doRegister")}"/>
-                </div>
-            </div>
-        </form>
-    </#if>
+<#import "template.ftl" as layout>
+<@layout.registrationLayout; section>
+    <#if section = "title">
+        ${msg("registerWithTitle",(realm.name!''))}
+    <#elseif section = "header">
+         ${msg("registerWithTitleHtml",(realm.name!''))}
+    <#elseif section = "form">
+        <form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.registrationAction}" method="post">
+          <#if !realm.registrationEmailAsUsername>
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('username',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="username" class="${properties.kcInputClass!}" name="username" value="${(register.formData.username!'')?html}" />
+                </div>
+            </div>
+          </#if>
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('firstName',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="firstName" class="${properties.kcInputClass!}" name="firstName" value="${(register.formData.firstName!'')?html}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('lastName',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="lastName" class="${properties.kcInputClass!}" name="lastName" value="${(register.formData.lastName!'')?html}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('email',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="email" class="${properties.kcInputClass!}" name="email" value="${(register.formData.email!'')?html}" />
+                </div>
+            </div>
+
+            <#if passwordRequired>
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('password',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password" class="${properties.kcInputClass!}" name="password" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!} ${messagesPerField.printIfExists('password-confirm',properties.kcFormGroupErrorClass!)}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password-confirm" class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password-confirm" class="${properties.kcInputClass!}" name="password-confirm" />
+                </div>
+            </div>
+            </#if>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.street" class="${properties.kcLabelClass!}">${msg("street")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.street" name="user.attributes.street"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.locality" class="${properties.kcLabelClass!}">${msg("locality")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.locality" name="user.attributes.locality"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.region" class="${properties.kcLabelClass!}">${msg("region")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.region" name="user.attributes.region"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.postal_code" class="${properties.kcLabelClass!}">${msg("postal_code")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.postal_code" name="user.attributes.postal_code"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.country" class="${properties.kcLabelClass!}">${msg("country")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.country" name="user.attributes.country"/>
+                </div>
+            </div>
+            <#if recaptchaRequired??>
+            <div class="form-group">
+                <div class="${properties.kcInputWrapperClass!}">
+                    <div class="g-recaptcha" data-size="compact" data-sitekey="${recaptchaSiteKey}"></div>
+                </div>
+            </div>
+            </#if>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                        <span><a href="${url.loginUrl}">${msg("backToLogin")}</a></span>
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doRegister")}"/>
+                </div>
+            </div>
+        </form>
+    </#if>
 </@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/img/keyclok-logo.svg b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/img/keyclok-logo.svg
index e253b15..80bb95a 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/img/keyclok-logo.svg
+++ b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/img/keyclok-logo.svg
@@ -1,194 +1,194 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="-145.2 359 325.4 77.2" enable-background="new -145.2 359 325.4 77.2" xml:space="preserve">
-<g>
-	<g>
-		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-			M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
-			c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
-			c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"
-			/>
-		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-			M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
-			c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
-			v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5
-			c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
-	</g>
-	
-		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-227.7191" y1="2220.7964" x2="-165.056" y2="2220.7964" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#FDFDFD"/>
-		<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
-		<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
-		<stop  offset="1" style="stop-color:#CFD1D1"/>
-	</linearGradient>
-	<path fill="url(#SVGID_1_)" d="M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1
-		c-14-2.9-10.9,6-8.3,14c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6
-		c-0.5-1-0.2-2.4,0.6-3.1c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1
-		C-81.9,398.7-80.7,395-79.1,393.1z"/>
-	
-		<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="192.3203" y1="1507.8835" x2="184.0467" y2="1507.8835" gradientTransform="matrix(1 0 0 1 -302 -1102)">
-		<stop  offset="0" style="stop-color:#E6E6E6"/>
-		<stop  offset="1" style="stop-color:#B2B3B3"/>
-	</linearGradient>
-	<path fill="url(#SVGID_2_)" d="M-115,391.3c0,5,0.7,22.8,4.5,30.4l-8.7-0.2v-31.5L-115,391.3z"/>
-	
-		<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-200.8627" y1="2227.3811" x2="-193.8624" y2="2207.8804" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#F6F6F6"/>
-		<stop  offset="1" style="stop-color:#B2B3B3"/>
-	</linearGradient>
-	<path fill="url(#SVGID_3_)" d="M-134.6,403.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
-		c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-18.5,7.5-15.4-5.3-21.4-9.5
-		c-3.2-2.2-7.7-2.1-11.2-0.8c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,390.8-136.7,391.9-134.6,403.1z"/>
-	<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="-117.4" y1="421.8" x2="-117.4" y2="390.6"/>
-	<g opacity="0.75">
-		<path fill="#FFFFFF" d="M-110.3,389c2.7,0,4.9,0.7,6.8,2.3c5.5,4.6,10.6,6.8,15.6,6.8c1.5,0,2.9-0.2,4.4-0.6
-			c-0.3,0.9-0.6,1.6-0.7,2.1c-0.4,1.4-1.6,1.8-4.4,2.4c-1.5,0.3-3.1,0.7-4.7,1.5c-1.6,0.8-2.5,2.3-2.5,3.9c0,1.5,0.9,2.8,2.4,3.5
-			c1.2,0.5,1.5,1.1,1.5,1.4c0,0.3-0.3,0.5-0.5,0.6c-0.6,0.3-1.2,0.4-2.1,0.4c-0.2,0-0.3,0-0.5,0c-0.2,0-0.4,0-0.5,0
-			c-1.6,0-3.4,0.2-5.2,1.7c-1.5,1.3-2,3.7-1.1,5.6c0.1,0.3,0.1,0.4,0.1,0.4c-0.1,0.1-0.8,0.6-2.6,0.6c-1.8,0-4.1-0.4-6.7-1.2
-			c-2-0.6-4.5-0.9-7.5-0.9c-3.8,0-8.4,0.6-12.6,1.5c-0.4,0.1-0.9,0.1-1.5,0.1c-1.9,0-4.2-0.5-5.7-1.6c1.7,0,3.3-0.9,4.4-2.4
-			c1.3-1.8,3.2-6.3,0.2-15.3l-0.1-0.2c-1.3-3.9-2.9-8.8-1.5-10.7c0.5-0.7,1.6-1.1,3.4-1.1c1.2,0,2.6,0.2,4.3,0.5
-			c1.8,0.4,3.6,0.6,5.4,0.6c1.9,0,3.7-0.2,5.1-0.7C-115.4,389.7-112.9,389-110.3,389 M-110.3,387c-2.7,0-5.2,0.6-7.3,1.3
-			c-1.3,0.4-2.9,0.6-4.6,0.6c-1.6,0-3.4-0.2-5-0.5c-1.9-0.4-3.4-0.6-4.7-0.6c-8.5,0-5.9,7.7-3.6,14.6c3.4,10.4,0.3,15.1-2.7,15.1
-			c-1.2,0-2.5-0.8-3.3-2.3c-1.5,5.6,4.8,7.9,9,7.9c0.7,0,1.4-0.1,2-0.2c3.7-0.8,8.1-1.5,12.2-1.5c2.5,0,4.9,0.2,6.9,0.8
-			c3,0.9,5.5,1.3,7.3,1.3c4,0,5.3-1.8,4.2-3.9c-0.5-1-0.2-2.4,0.6-3.1c1.4-1.2,2.7-1.3,3.9-1.3c0.3,0,0.7,0,1,0c1,0,2-0.1,3.1-0.7
-			c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1c0.4-1.5,1.7-5.2,3.3-7.1c-2.9,2-5.9,3-8.9,3
-			c-4.5,0-9.2-2.2-14.3-6.4C-104.7,387.7-107.6,387-110.3,387L-110.3,387z M-79.1,393.1L-79.1,393.1L-79.1,393.1z"/>
-	</g>
-	<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-		M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
-		c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
-		c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"/>
-	<path fill="#034672" d="M-134.6,402.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
-		c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-13.1,4.8-14.1-5.5-20.1-9.7
-		c-3.2-2.2-9-1.9-12.5-0.6c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,389.8-136.7,390.9-134.6,402.1z"/>
-	<path fill="#FFFFFF" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1
-		c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7
-		c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7
-		c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
-	
-		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-217.9037" y1="2215.0122" x2="-187.068" y2="2207.345" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#B8D7E9"/>
-		<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-		<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
-		<stop  offset="1" style="stop-color:#DFEEF9"/>
-	</linearGradient>
-	<path fill="url(#SVGID_4_)" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9v69.3l4.8-4.9v-34.2
-		c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
-		C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
-	
-		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-214.9444" y1="2190.8406" x2="-206.3191" y2="2233.0925" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#F1F9FE"/>
-		<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-		<stop  offset="1" style="stop-color:#E4F3FD"/>
-	</linearGradient>
-	<path fill="url(#SVGID_5_)" d="M-122.3,362.5c-2.1,0-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
-		c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
-		v37.2l2.7,2.8h1.2l0.9-0.9L-122.3,362.5L-122.3,362.5z"/>
-	<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M-122.6,362.5c1.9,0.9,3.4,2,4.2,2.4
-		c0.8,0.5,4,2.5,5.1,3.1c0.8,0.5,3.7,2,3.7,6.3c0,1.3,0,2.8,0,3.8c0,2.8-1.6,5-4.5,6.4c-1,0.5-1.8,1.4-1.8,3.6v1.2"/>
-	<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1
-		c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4
-		c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2
-		c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
-		C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
-	<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-107.5,392.7"/>
-	<g>
-		
-			<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-106.4885" y1="2203.667" x2="-106.4885" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_6_)" d="M-14.5,407.6h-11.6c0.3,2.3,1,3.9,2.1,4.7s2.9,1.2,5.5,1.2c3.4,0,7.4-0.2,12-0.7l0.9,6
-			c-3.3,1.6-8,2.4-14,2.4c-6,0-10.3-1.3-12.9-3.9c-2.6-2.6-3.8-6.9-3.8-12.9c0-6.3,1.2-10.7,3.7-13.2c2.5-2.5,6.7-3.8,12.6-3.8
-			c5.3,0,9.2,0.9,11.6,2.8c2.4,1.8,3.6,4.7,3.6,8.4c0,3-0.8,5.2-2.3,6.7C-8.5,406.8-11,407.6-14.5,407.6z M-26.3,401.8h9.1
-			c1.2,0,2-0.3,2.4-0.8c0.4-0.6,0.6-1.4,0.6-2.5c0-1.5-0.4-2.6-1.2-3.2c-0.8-0.6-2.2-0.9-4.3-0.9c-2.5,0-4.2,0.5-5.1,1.5
-			C-25.6,396.9-26.1,398.8-26.3,401.8z"/>
-		
-			<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-72.864" y1="2203.667" x2="-72.864" y2="2254.5503" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_7_)" d="M31,388.3l-11.4,32.6c-0.6,1.7-1.4,3.3-2.2,4.8c-0.9,1.5-2,2.9-3.4,4.3c-1.4,1.4-3.1,2.4-5.2,3
-			c-2.1,0.7-4.4,0.8-6.9,0.5L1,427.8c2.6-0.7,4.6-1.6,6.1-2.7c1.5-1.1,2.6-2.6,3.5-4.5l0.1-0.3H8.9c-1.6,0-2.6-0.8-3.1-2.3
-			l-10.5-29.8H5.6l6,20.8c0.4,1.5,0.7,3.1,1,4.8h0.8c0.1-0.5,0.3-1.3,0.7-2.4s0.5-1.9,0.7-2.4l5.9-20.8L31,388.3L31,388.3z"/>
-		
-			<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-41.775" y1="2203.667" x2="-41.775" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_8_)" d="M57.6,412.8l0.9,6.3c-3.3,1.4-7.5,2.1-12.4,2.1c-5.9,0-10.1-1.3-12.5-3.8
-			c-2.4-2.5-3.6-6.9-3.6-13.1c0-6.2,1.2-10.6,3.6-13.1c2.4-2.5,6.6-3.8,12.6-3.8c4.9,0,8.8,0.7,11.9,2l-1,6
-			c-4.7-0.1-7.8-0.1-9.2-0.1c-3,0-5,0.6-6.1,1.9c-1.1,1.3-1.7,3.6-1.7,7.2c0,3.5,0.6,5.9,1.7,7.2c1.1,1.3,3.1,1.9,6.1,1.9
-			C51.6,413.4,54.9,413.2,57.6,412.8z"/>
-		
-			<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="8.9715" y1="2203.667" x2="8.9715" y2="2254.553" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_9_)" d="M95,387.4c6,0,10.2,1.3,12.7,3.9c2.5,2.6,3.7,7,3.7,13.1c0,6.2-1.2,10.5-3.7,13.1
-			c-2.5,2.5-6.7,3.8-12.7,3.8c-6,0-10.3-1.3-12.8-3.8c-2.5-2.5-3.7-6.9-3.7-13.1c0-6.2,1.2-10.6,3.7-13.2
-			C84.7,388.7,89,387.4,95,387.4z M95,394.6c-2.6,0-4.3,0.6-5.1,2c-0.9,1.3-1.3,3.9-1.3,7.8c0,3.8,0.4,6.4,1.3,7.7
-			c0.9,1.3,2.6,2,5.1,2c2.5,0,4.2-0.7,5.1-2c0.9-1.3,1.3-3.9,1.3-7.7c0-3.9-0.4-6.5-1.3-7.8C99.2,395.3,97.5,394.6,95,394.6z"/>
-		
-			<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="42.879" y1="2203.667" x2="42.879" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_10_)" d="M115.9,395.5l-0.9-6.5c5.8-1,11.4-1.6,16.7-1.6c4.3,0,7.5,0.9,9.6,2.6c2,1.8,3.1,4.8,3.1,9.2v21.2
-			h-7.6l-1-4.9c-3.2,3.8-7.2,5.7-11.9,5.7c-3.1,0-5.6-0.8-7.6-2.4s-2.9-3.9-2.9-6.8v-3.3c0-2.6,0.9-4.6,2.6-6
-			c1.7-1.4,4.1-2.1,7.2-2.1h11.5v-1.4c0-1.6-0.4-2.8-1.1-3.3c-0.7-0.6-2.1-0.8-4.1-0.8C125.9,394.9,121.4,395.1,115.9,395.5z
-			 M122.9,409.4v1.2c0,2.2,1.3,3.3,3.8,3.3c2.6,0,5.3-1,8-3.1v-4.5H126C124,406.4,122.9,407.4,122.9,409.4z"/>
-		
-			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-136.063" y1="2203.667" x2="-136.063" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_11_)" d="M-43.5,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1H-46l-7.9,11.2h-3
-			c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9H-34L-43.5,406.1z"/>
-		
-			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-16.68" y1="2203.667" x2="-16.68" y2="2254.551" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_12_)" d="M76.7,413.2h-2.6c-2.4,0-3.6-1.1-3.6-3.3v-35.1h-3l-6.6,9.4v28.2c0,2.8,0.8,5,2.5,6.5
-			c1.6,1.5,3.9,2.3,6.8,2.3c3.5,0,6-0.4,7.7-1.3L76.7,413.2z"/>
-		
-			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="78.107" y1="2203.667" x2="78.107" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_13_)" d="M170.7,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1h-10.8l-7.9,11.2h-3
-			c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9h10.8L170.7,406.1z"/>
-	</g>
-	
-		<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-208.281" y1="2186.001" x2="-208.281" y2="2196.1689" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#00639A"/>
-		<stop  offset="0.2355" style="stop-color:#00578A"/>
-		<stop  offset="0.507" style="stop-color:#004D7B"/>
-		<stop  offset="0.7167" style="stop-color:#004773"/>
-		<stop  offset="1" style="stop-color:#00446E"/>
-	</linearGradient>
-	<polygon fill="url(#SVGID_14_)" points="-122.3,372.4 -131.3,370.4 -132.3,374.1 -122.3,379.2 -112.2,374.1 -113.2,370.4 	"/>
-	<polyline opacity="0.2" enable-background="new    " points="-122.3,379.2 -112.2,374.1 -113.2,370.4 -122.3,372.4 	"/>
-	<path fill="#034672" d="M-127.2,391.9c3.4,1.3,6.7,1.5,9.8,0.4l-0.3-2.2c-2.6,0.8-6.3,0.7-9.5,0.1L-127.2,391.9z"/>
-	<path fill="#034672" d="M-122.6,391.5c-0.4,2.8,1.9,4.7,1.9,7.6C-116.8,394.8-121.7,393.3-122.6,391.5z"/>
-	<path fill="#034672" d="M-122.6,391.7c-0.1,3.2-0.4,5.6-1.7,7.2C-126.8,394.2-123.7,392.6-122.6,391.7z"/>
-	<circle fill="#034672" cx="-122.6" cy="391.7" r="1.6"/>
-	
-		<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-197.511" y1="2237.772" x2="-197.511" y2="2237.772" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
-		<stop  offset="0" style="stop-color:#F6F6F6"/>
-		<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
-		<stop  offset="1" style="stop-color:#DADADA"/>
-	</linearGradient>
-	<path fill="url(#SVGID_15_)" d="M-111.5,422.3"/>
-</g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="-145.2 359 325.4 77.2" enable-background="new -145.2 359 325.4 77.2" xml:space="preserve">
+<g>
+	<g>
+		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+			M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
+			c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
+			c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"
+			/>
+		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+			M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
+			c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
+			v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5
+			c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
+	</g>
+	
+		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-227.7191" y1="2220.7964" x2="-165.056" y2="2220.7964" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#FDFDFD"/>
+		<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
+		<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
+		<stop  offset="1" style="stop-color:#CFD1D1"/>
+	</linearGradient>
+	<path fill="url(#SVGID_1_)" d="M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1
+		c-14-2.9-10.9,6-8.3,14c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6
+		c-0.5-1-0.2-2.4,0.6-3.1c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1
+		C-81.9,398.7-80.7,395-79.1,393.1z"/>
+	
+		<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="192.3203" y1="1507.8835" x2="184.0467" y2="1507.8835" gradientTransform="matrix(1 0 0 1 -302 -1102)">
+		<stop  offset="0" style="stop-color:#E6E6E6"/>
+		<stop  offset="1" style="stop-color:#B2B3B3"/>
+	</linearGradient>
+	<path fill="url(#SVGID_2_)" d="M-115,391.3c0,5,0.7,22.8,4.5,30.4l-8.7-0.2v-31.5L-115,391.3z"/>
+	
+		<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-200.8627" y1="2227.3811" x2="-193.8624" y2="2207.8804" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#F6F6F6"/>
+		<stop  offset="1" style="stop-color:#B2B3B3"/>
+	</linearGradient>
+	<path fill="url(#SVGID_3_)" d="M-134.6,403.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
+		c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-18.5,7.5-15.4-5.3-21.4-9.5
+		c-3.2-2.2-7.7-2.1-11.2-0.8c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,390.8-136.7,391.9-134.6,403.1z"/>
+	<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="-117.4" y1="421.8" x2="-117.4" y2="390.6"/>
+	<g opacity="0.75">
+		<path fill="#FFFFFF" d="M-110.3,389c2.7,0,4.9,0.7,6.8,2.3c5.5,4.6,10.6,6.8,15.6,6.8c1.5,0,2.9-0.2,4.4-0.6
+			c-0.3,0.9-0.6,1.6-0.7,2.1c-0.4,1.4-1.6,1.8-4.4,2.4c-1.5,0.3-3.1,0.7-4.7,1.5c-1.6,0.8-2.5,2.3-2.5,3.9c0,1.5,0.9,2.8,2.4,3.5
+			c1.2,0.5,1.5,1.1,1.5,1.4c0,0.3-0.3,0.5-0.5,0.6c-0.6,0.3-1.2,0.4-2.1,0.4c-0.2,0-0.3,0-0.5,0c-0.2,0-0.4,0-0.5,0
+			c-1.6,0-3.4,0.2-5.2,1.7c-1.5,1.3-2,3.7-1.1,5.6c0.1,0.3,0.1,0.4,0.1,0.4c-0.1,0.1-0.8,0.6-2.6,0.6c-1.8,0-4.1-0.4-6.7-1.2
+			c-2-0.6-4.5-0.9-7.5-0.9c-3.8,0-8.4,0.6-12.6,1.5c-0.4,0.1-0.9,0.1-1.5,0.1c-1.9,0-4.2-0.5-5.7-1.6c1.7,0,3.3-0.9,4.4-2.4
+			c1.3-1.8,3.2-6.3,0.2-15.3l-0.1-0.2c-1.3-3.9-2.9-8.8-1.5-10.7c0.5-0.7,1.6-1.1,3.4-1.1c1.2,0,2.6,0.2,4.3,0.5
+			c1.8,0.4,3.6,0.6,5.4,0.6c1.9,0,3.7-0.2,5.1-0.7C-115.4,389.7-112.9,389-110.3,389 M-110.3,387c-2.7,0-5.2,0.6-7.3,1.3
+			c-1.3,0.4-2.9,0.6-4.6,0.6c-1.6,0-3.4-0.2-5-0.5c-1.9-0.4-3.4-0.6-4.7-0.6c-8.5,0-5.9,7.7-3.6,14.6c3.4,10.4,0.3,15.1-2.7,15.1
+			c-1.2,0-2.5-0.8-3.3-2.3c-1.5,5.6,4.8,7.9,9,7.9c0.7,0,1.4-0.1,2-0.2c3.7-0.8,8.1-1.5,12.2-1.5c2.5,0,4.9,0.2,6.9,0.8
+			c3,0.9,5.5,1.3,7.3,1.3c4,0,5.3-1.8,4.2-3.9c-0.5-1-0.2-2.4,0.6-3.1c1.4-1.2,2.7-1.3,3.9-1.3c0.3,0,0.7,0,1,0c1,0,2-0.1,3.1-0.7
+			c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1c0.4-1.5,1.7-5.2,3.3-7.1c-2.9,2-5.9,3-8.9,3
+			c-4.5,0-9.2-2.2-14.3-6.4C-104.7,387.7-107.6,387-110.3,387L-110.3,387z M-79.1,393.1L-79.1,393.1L-79.1,393.1z"/>
+	</g>
+	<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+		M-79.1,393.1c-7.2,5-14.7,3.7-23.2-3.4c-4.9-4.1-11.2-2.8-15.4-1.5c-2.6,0.8-6.3,0.7-9.5,0.1c-14-2.9-10.9,6-8.3,14
+		c4.8,14.6-3.2,18-6,12.8c-1.8,6.6,7.1,8.6,10.9,7.7c6-1.4,14.1-2.2,19-0.6c9.5,2.9,13.1,0.5,11.5-2.6c-0.5-1-0.2-2.4,0.6-3.1
+		c2.8-2.4,5.3-0.4,8-1.9c2.1-1.2,2.1-3.9-1.2-5.5c-1.7-0.8-1.6-2.9,0.2-3.8c3.7-2,8.8-1,10-5.1C-81.9,398.7-80.7,395-79.1,393.1z"/>
+	<path fill="#034672" d="M-134.6,402.1c-2.8-7.5-6.5-16.6,7.5-13.7c3.2,0.7,6.9,0.7,9.5-0.1c4.3-1.3,10-2.4,14.5,1.5
+		c8.9,7.7,16.9,8.3,24.1,3.3c-1.6,1.9-3.1,5.6-3.3,7.1c-0.2,1.3-1.1,1.9-2.4,2.4c-13.1,4.8-14.1-5.5-20.1-9.7
+		c-3.2-2.2-9-1.9-12.5-0.6c-3.2,1.2-6.4,0.9-9.8-0.4C-132.9,389.8-136.7,390.9-134.6,402.1z"/>
+	<path fill="#FFFFFF" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1
+		c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7
+		c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7
+		c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
+	
+		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-217.9037" y1="2215.0122" x2="-187.068" y2="2207.345" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#B8D7E9"/>
+		<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+		<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
+		<stop  offset="1" style="stop-color:#DFEEF9"/>
+	</linearGradient>
+	<path fill="url(#SVGID_4_)" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1c-0.8-0.5-2.7-1.9-4.8-1.9v69.3l4.8-4.9v-34.2
+		c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
+		C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
+	
+		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-214.9444" y1="2190.8406" x2="-206.3191" y2="2233.0925" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#F1F9FE"/>
+		<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+		<stop  offset="1" style="stop-color:#E4F3FD"/>
+	</linearGradient>
+	<path fill="url(#SVGID_5_)" d="M-122.3,362.5c-2.1,0-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3
+		c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1
+		v37.2l2.7,2.8h1.2l0.9-0.9L-122.3,362.5L-122.3,362.5z"/>
+	<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M-122.6,362.5c1.9,0.9,3.4,2,4.2,2.4
+		c0.8,0.5,4,2.5,5.1,3.1c0.8,0.5,3.7,2,3.7,6.3c0,1.3,0,2.8,0,3.8c0,2.8-1.6,5-4.5,6.4c-1,0.5-1.8,1.4-1.8,3.6v1.2"/>
+	<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-112.4,367.4c-1.1-0.6-4.3-2.6-5.1-3.1
+		c-0.8-0.5-2.7-1.9-4.8-1.9s-4,1.4-4.8,1.9c-0.8,0.5-4,2.5-5.1,3.1c-0.8,0.5-3.7,2-3.7,6.3c0,1.3,0,3.6,0,4.5c0,2.8,1.6,5,4.5,6.4
+		c1,0.5,1.8,1.3,1.8,3.5c0,0.9,0.4,1.2,0.9,1.2h0.7c0.6,0,1,0.2,1,1.3c0,0.6,0,2.1,0,2.1v37.2l2.7,2.8h1.2l5.7-5.8v-34.2
+		c0,0,0-1.5,0-2.1c0-1,0.3-1.3,1-1.3h0.7c0.6,0,0.9-0.2,0.9-1.2c0-2.1,0.8-3,1.8-3.5c2.9-1.5,4.5-3.6,4.5-6.4c0-1,0-3.2,0-4.5
+		C-108.7,369.5-111.6,367.9-112.4,367.4z"/>
+	<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M-107.5,392.7"/>
+	<g>
+		
+			<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-106.4885" y1="2203.667" x2="-106.4885" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_6_)" d="M-14.5,407.6h-11.6c0.3,2.3,1,3.9,2.1,4.7s2.9,1.2,5.5,1.2c3.4,0,7.4-0.2,12-0.7l0.9,6
+			c-3.3,1.6-8,2.4-14,2.4c-6,0-10.3-1.3-12.9-3.9c-2.6-2.6-3.8-6.9-3.8-12.9c0-6.3,1.2-10.7,3.7-13.2c2.5-2.5,6.7-3.8,12.6-3.8
+			c5.3,0,9.2,0.9,11.6,2.8c2.4,1.8,3.6,4.7,3.6,8.4c0,3-0.8,5.2-2.3,6.7C-8.5,406.8-11,407.6-14.5,407.6z M-26.3,401.8h9.1
+			c1.2,0,2-0.3,2.4-0.8c0.4-0.6,0.6-1.4,0.6-2.5c0-1.5-0.4-2.6-1.2-3.2c-0.8-0.6-2.2-0.9-4.3-0.9c-2.5,0-4.2,0.5-5.1,1.5
+			C-25.6,396.9-26.1,398.8-26.3,401.8z"/>
+		
+			<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-72.864" y1="2203.667" x2="-72.864" y2="2254.5503" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_7_)" d="M31,388.3l-11.4,32.6c-0.6,1.7-1.4,3.3-2.2,4.8c-0.9,1.5-2,2.9-3.4,4.3c-1.4,1.4-3.1,2.4-5.2,3
+			c-2.1,0.7-4.4,0.8-6.9,0.5L1,427.8c2.6-0.7,4.6-1.6,6.1-2.7c1.5-1.1,2.6-2.6,3.5-4.5l0.1-0.3H8.9c-1.6,0-2.6-0.8-3.1-2.3
+			l-10.5-29.8H5.6l6,20.8c0.4,1.5,0.7,3.1,1,4.8h0.8c0.1-0.5,0.3-1.3,0.7-2.4s0.5-1.9,0.7-2.4l5.9-20.8L31,388.3L31,388.3z"/>
+		
+			<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-41.775" y1="2203.667" x2="-41.775" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_8_)" d="M57.6,412.8l0.9,6.3c-3.3,1.4-7.5,2.1-12.4,2.1c-5.9,0-10.1-1.3-12.5-3.8
+			c-2.4-2.5-3.6-6.9-3.6-13.1c0-6.2,1.2-10.6,3.6-13.1c2.4-2.5,6.6-3.8,12.6-3.8c4.9,0,8.8,0.7,11.9,2l-1,6
+			c-4.7-0.1-7.8-0.1-9.2-0.1c-3,0-5,0.6-6.1,1.9c-1.1,1.3-1.7,3.6-1.7,7.2c0,3.5,0.6,5.9,1.7,7.2c1.1,1.3,3.1,1.9,6.1,1.9
+			C51.6,413.4,54.9,413.2,57.6,412.8z"/>
+		
+			<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="8.9715" y1="2203.667" x2="8.9715" y2="2254.553" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_9_)" d="M95,387.4c6,0,10.2,1.3,12.7,3.9c2.5,2.6,3.7,7,3.7,13.1c0,6.2-1.2,10.5-3.7,13.1
+			c-2.5,2.5-6.7,3.8-12.7,3.8c-6,0-10.3-1.3-12.8-3.8c-2.5-2.5-3.7-6.9-3.7-13.1c0-6.2,1.2-10.6,3.7-13.2
+			C84.7,388.7,89,387.4,95,387.4z M95,394.6c-2.6,0-4.3,0.6-5.1,2c-0.9,1.3-1.3,3.9-1.3,7.8c0,3.8,0.4,6.4,1.3,7.7
+			c0.9,1.3,2.6,2,5.1,2c2.5,0,4.2-0.7,5.1-2c0.9-1.3,1.3-3.9,1.3-7.7c0-3.9-0.4-6.5-1.3-7.8C99.2,395.3,97.5,394.6,95,394.6z"/>
+		
+			<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="42.879" y1="2203.667" x2="42.879" y2="2254.552" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_10_)" d="M115.9,395.5l-0.9-6.5c5.8-1,11.4-1.6,16.7-1.6c4.3,0,7.5,0.9,9.6,2.6c2,1.8,3.1,4.8,3.1,9.2v21.2
+			h-7.6l-1-4.9c-3.2,3.8-7.2,5.7-11.9,5.7c-3.1,0-5.6-0.8-7.6-2.4s-2.9-3.9-2.9-6.8v-3.3c0-2.6,0.9-4.6,2.6-6
+			c1.7-1.4,4.1-2.1,7.2-2.1h11.5v-1.4c0-1.6-0.4-2.8-1.1-3.3c-0.7-0.6-2.1-0.8-4.1-0.8C125.9,394.9,121.4,395.1,115.9,395.5z
+			 M122.9,409.4v1.2c0,2.2,1.3,3.3,3.8,3.3c2.6,0,5.3-1,8-3.1v-4.5H126C124,406.4,122.9,407.4,122.9,409.4z"/>
+		
+			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-136.063" y1="2203.667" x2="-136.063" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_11_)" d="M-43.5,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1H-46l-7.9,11.2h-3
+			c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9H-34L-43.5,406.1z"/>
+		
+			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-16.68" y1="2203.667" x2="-16.68" y2="2254.551" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_12_)" d="M76.7,413.2h-2.6c-2.4,0-3.6-1.1-3.6-3.3v-35.1h-3l-6.6,9.4v28.2c0,2.8,0.8,5,2.5,6.5
+			c1.6,1.5,3.9,2.3,6.8,2.3c3.5,0,6-0.4,7.7-1.3L76.7,413.2z"/>
+		
+			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="78.107" y1="2203.667" x2="78.107" y2="2254.5491" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_13_)" d="M170.7,406.1c-0.9-1.6-1.9-2.7-3-3.5v-0.1c1.3-0.9,2.3-1.9,3-3.1l8.3-11.1h-10.8l-7.9,11.2h-3
+			c0.3-1.8,0.5-3.7,0.5-5.9v-18.8h-3l-6.7,9.5v36.1h9.6v-10.1c0-1.3-0.2-2.9-0.5-4.8h3.1l9,14.9h10.8L170.7,406.1z"/>
+	</g>
+	
+		<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-208.281" y1="2186.001" x2="-208.281" y2="2196.1689" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#00639A"/>
+		<stop  offset="0.2355" style="stop-color:#00578A"/>
+		<stop  offset="0.507" style="stop-color:#004D7B"/>
+		<stop  offset="0.7167" style="stop-color:#004773"/>
+		<stop  offset="1" style="stop-color:#00446E"/>
+	</linearGradient>
+	<polygon fill="url(#SVGID_14_)" points="-122.3,372.4 -131.3,370.4 -132.3,374.1 -122.3,379.2 -112.2,374.1 -113.2,370.4 	"/>
+	<polyline opacity="0.2" enable-background="new    " points="-122.3,379.2 -112.2,374.1 -113.2,370.4 -122.3,372.4 	"/>
+	<path fill="#034672" d="M-127.2,391.9c3.4,1.3,6.7,1.5,9.8,0.4l-0.3-2.2c-2.6,0.8-6.3,0.7-9.5,0.1L-127.2,391.9z"/>
+	<path fill="#034672" d="M-122.6,391.5c-0.4,2.8,1.9,4.7,1.9,7.6C-116.8,394.8-121.7,393.3-122.6,391.5z"/>
+	<path fill="#034672" d="M-122.6,391.7c-0.1,3.2-0.4,5.6-1.7,7.2C-126.8,394.2-123.7,392.6-122.6,391.7z"/>
+	<circle fill="#034672" cx="-122.6" cy="391.7" r="1.6"/>
+	
+		<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-197.511" y1="2237.772" x2="-197.511" y2="2237.772" gradientTransform="matrix(1 0 0 1 86 -1815.5)">
+		<stop  offset="0" style="stop-color:#F6F6F6"/>
+		<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
+		<stop  offset="1" style="stop-color:#DADADA"/>
+	</linearGradient>
+	<path fill="url(#SVGID_15_)" d="M-111.5,422.3"/>
+</g>
+</svg>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter-config.js b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter-config.js
index 5147ab3..212dd14 100755
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter-config.js
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter-config.js
@@ -1,4 +1,4 @@
-/**
+/**
  * Configuration for jstd scenario adapter 
  */
 var jstdScenarioAdapter = {
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/bootstrap-select/README.md b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/bootstrap-select/README.md
index 3d6cdbc..872e1c6 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/bootstrap-select/README.md
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/bootstrap-select/README.md
@@ -1,61 +1,61 @@
-bootstrap-select
-================
-
-A custom select / multiselect for Bootstrap using button dropdown, designed to behave like regular Bootstrap selects;
-
-## Demo and Documentation
-
-See a Bootstrap 2.3.2 example [here](http://silviomoreto.github.com/bootstrap-select/). <br/>
-See a Bootstrap 3.0.2 example [here](http://silviomoreto.github.com/bootstrap-select/3) (work-in-progress).
-
-## Authors
-
-[Silvio Moreto](http://github.com/silviomoreto),
-[Ana Carolina](http://github.com/anacarolinats),
-[caseyjhol](https://github.com/caseyjhol), and
-[Matt Bryson](https://github.com/mattbryson).
-
-## Usage
-
-Create your `<select>` with the `.selectpicker` class.
-
-    <select class="selectpicker">
-      <option>Mustard</option>
-      <option>Ketchup</option>
-      <option>Barbecue</option>
-    </select>
-    
-Enable Bootstrap-Select via JavaScript:
-
-    $('.selectpicker').selectpicker();
-
-Or just
-
-    $('select').selectpicker();
-
-Checkout the [documentation](http://silviomoreto.github.com/bootstrap-select/) for further information.
-
-## CDN
-
-* https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.3.5/bootstrap-select.min.js
-* https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.3.5/bootstrap-select.min.css
-
-## Bugs and feature requests
-
-Anyone and everyone is welcome to contribute. Please take a moment to
-review the [guidelines for contributing](CONTRIBUTING.md). Make sure you're using the latest version of bootstrap-select before submitting an issue.
-
-* [Bug reports](CONTRIBUTING.md#bugs)
-* [Feature requests](CONTRIBUTING.md#features)
-
-## Copyright and license
-
-Copyright (C) 2013 bootstrap-select
-
-Licensed under the MIT license.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+bootstrap-select
+================
+
+A custom select / multiselect for Bootstrap using button dropdown, designed to behave like regular Bootstrap selects;
+
+## Demo and Documentation
+
+See a Bootstrap 2.3.2 example [here](http://silviomoreto.github.com/bootstrap-select/). <br/>
+See a Bootstrap 3.0.2 example [here](http://silviomoreto.github.com/bootstrap-select/3) (work-in-progress).
+
+## Authors
+
+[Silvio Moreto](http://github.com/silviomoreto),
+[Ana Carolina](http://github.com/anacarolinats),
+[caseyjhol](https://github.com/caseyjhol), and
+[Matt Bryson](https://github.com/mattbryson).
+
+## Usage
+
+Create your `<select>` with the `.selectpicker` class.
+
+    <select class="selectpicker">
+      <option>Mustard</option>
+      <option>Ketchup</option>
+      <option>Barbecue</option>
+    </select>
+    
+Enable Bootstrap-Select via JavaScript:
+
+    $('.selectpicker').selectpicker();
+
+Or just
+
+    $('select').selectpicker();
+
+Checkout the [documentation](http://silviomoreto.github.com/bootstrap-select/) for further information.
+
+## CDN
+
+* https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.3.5/bootstrap-select.min.js
+* https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.3.5/bootstrap-select.min.css
+
+## Bugs and feature requests
+
+Anyone and everyone is welcome to contribute. Please take a moment to
+review the [guidelines for contributing](CONTRIBUTING.md). Make sure you're using the latest version of bootstrap-select before submitting an issue.
+
+* [Bug reports](CONTRIBUTING.md#bugs)
+* [Feature requests](CONTRIBUTING.md#features)
+
+## Copyright and license
+
+Copyright (C) 2013 bootstrap-select
+
+Licensed under the MIT license.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/README-zh-Hans.html b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/README-zh-Hans.html
index 69bf7ae..b92e3c0 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/README-zh-Hans.html
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/README-zh-Hans.html
@@ -58,7 +58,7 @@ public:
 }</pre>
     </table>
 
-    
+    
     <h2>常见问题</h2>
     <h3 id="langs">它是为什么语言工作的?</h3>
     <p><tt>prettify.js中的注释是权威的,但是它的语法分析程序可以在很多语言中使用</tt>,包括 C ,
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/desert.css b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/desert.css
index 3723668..b2b73cd 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/desert.css
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/desert.css
@@ -1,34 +1,34 @@
-/* desert scheme ported from vim to google prettify */
-pre.prettyprint { display: block; background-color: #333 }
-pre .nocode { background-color: none; color: #000 }
-pre .str { color: #ffa0a0 } /* string  - pink */
-pre .kwd { color: #f0e68c; font-weight: bold }
-pre .com { color: #87ceeb } /* comment - skyblue */
-pre .typ { color: #98fb98 } /* type    - lightgreen */
-pre .lit { color: #cd5c5c } /* literal - darkred */
-pre .pun { color: #fff }    /* punctuation */
-pre .pln { color: #fff }    /* plaintext */
-pre .tag { color: #f0e68c; font-weight: bold } /* html/xml tag    - lightyellow */
-pre .atn { color: #bdb76b; font-weight: bold } /* attribute name  - khaki */
-pre .atv { color: #ffa0a0 } /* attribute value - pink */
-pre .dec { color: #98fb98 } /* decimal         - lightgreen */
-
-/* Specify class=linenums on a pre to get line numbering */
-ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE } /* IE indents via margin-left */
-li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
-/* Alternate shading for lines */
-li.L1,li.L3,li.L5,li.L7,li.L9 { }
-
-@media print {
-  pre.prettyprint { background-color: none }
-  pre .str, code .str { color: #060 }
-  pre .kwd, code .kwd { color: #006; font-weight: bold }
-  pre .com, code .com { color: #600; font-style: italic }
-  pre .typ, code .typ { color: #404; font-weight: bold }
-  pre .lit, code .lit { color: #044 }
-  pre .pun, code .pun { color: #440 }
-  pre .pln, code .pln { color: #000 }
-  pre .tag, code .tag { color: #006; font-weight: bold }
-  pre .atn, code .atn { color: #404 }
-  pre .atv, code .atv { color: #060 }
-}
+/* desert scheme ported from vim to google prettify */
+pre.prettyprint { display: block; background-color: #333 }
+pre .nocode { background-color: none; color: #000 }
+pre .str { color: #ffa0a0 } /* string  - pink */
+pre .kwd { color: #f0e68c; font-weight: bold }
+pre .com { color: #87ceeb } /* comment - skyblue */
+pre .typ { color: #98fb98 } /* type    - lightgreen */
+pre .lit { color: #cd5c5c } /* literal - darkred */
+pre .pun { color: #fff }    /* punctuation */
+pre .pln { color: #fff }    /* plaintext */
+pre .tag { color: #f0e68c; font-weight: bold } /* html/xml tag    - lightyellow */
+pre .atn { color: #bdb76b; font-weight: bold } /* attribute name  - khaki */
+pre .atv { color: #ffa0a0 } /* attribute value - pink */
+pre .dec { color: #98fb98 } /* decimal         - lightgreen */
+
+/* Specify class=linenums on a pre to get line numbering */
+ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE } /* IE indents via margin-left */
+li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,li.L3,li.L5,li.L7,li.L9 { }
+
+@media print {
+  pre.prettyprint { background-color: none }
+  pre .str, code .str { color: #060 }
+  pre .kwd, code .kwd { color: #006; font-weight: bold }
+  pre .com, code .com { color: #600; font-style: italic }
+  pre .typ, code .typ { color: #404; font-weight: bold }
+  pre .lit, code .lit { color: #044 }
+  pre .pun, code .pun { color: #440 }
+  pre .pln, code .pln { color: #000 }
+  pre .tag, code .tag { color: #006; font-weight: bold }
+  pre .atn, code .atn { color: #404 }
+  pre .atv, code .atv { color: #060 }
+}
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/sons-of-obsidian.css b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/sons-of-obsidian.css
index 7d24f3b..8553db6 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/sons-of-obsidian.css
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/components/google-code-prettify/styles/sons-of-obsidian.css
@@ -1,118 +1,118 @@
-/*
- * Derived from einaros's Sons of Obsidian theme at
- * http://studiostyl.es/schemes/son-of-obsidian by
- * Alex Ford of CodeTunnel:
- * http://CodeTunnel.com/blog/post/71/google-code-prettify-obsidian-theme
- */
-
-.str
-{
-    color: #EC7600;
-}
-.kwd
-{
-    color: #93C763;
-}
-.com
-{
-    color: #66747B;
-}
-.typ
-{
-    color: #678CB1;
-}
-.lit
-{
-    color: #FACD22;
-}
-.pun
-{
-    color: #F1F2F3;
-}
-.pln
-{
-    color: #F1F2F3;
-}
-.tag
-{
-    color: #8AC763;
-}
-.atn
-{
-    color: #E0E2E4;
-}
-.atv
-{
-    color: #EC7600;
-}
-.dec
-{
-    color: purple;
-}
-pre.prettyprint
-{
-    border: 0px solid #888;
-}
-ol.linenums
-{
-    margin-top: 0;
-    margin-bottom: 0;
-}
-.prettyprint {
-    background: #000;
-}
-li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9
-{
-    color: #555;
-    list-style-type: decimal;
-}
-li.L1, li.L3, li.L5, li.L7, li.L9 {
-    background: #111;
-}
-@media print
-{
-    .str
-    {
-        color: #060;
-    }
-    .kwd
-    {
-        color: #006;
-        font-weight: bold;
-    }
-    .com
-    {
-        color: #600;
-        font-style: italic;
-    }
-    .typ
-    {
-        color: #404;
-        font-weight: bold;
-    }
-    .lit
-    {
-        color: #044;
-    }
-    .pun
-    {
-        color: #440;
-    }
-    .pln
-    {
-        color: #000;
-    }
-    .tag
-    {
-        color: #006;
-        font-weight: bold;
-    }
-    .atn
-    {
-        color: #404;
-    }
-    .atv
-    {
-        color: #060;
-    }
-}
+/*
+ * Derived from einaros's Sons of Obsidian theme at
+ * http://studiostyl.es/schemes/son-of-obsidian by
+ * Alex Ford of CodeTunnel:
+ * http://CodeTunnel.com/blog/post/71/google-code-prettify-obsidian-theme
+ */
+
+.str
+{
+    color: #EC7600;
+}
+.kwd
+{
+    color: #93C763;
+}
+.com
+{
+    color: #66747B;
+}
+.typ
+{
+    color: #678CB1;
+}
+.lit
+{
+    color: #FACD22;
+}
+.pun
+{
+    color: #F1F2F3;
+}
+.pln
+{
+    color: #F1F2F3;
+}
+.tag
+{
+    color: #8AC763;
+}
+.atn
+{
+    color: #E0E2E4;
+}
+.atv
+{
+    color: #EC7600;
+}
+.dec
+{
+    color: purple;
+}
+pre.prettyprint
+{
+    border: 0px solid #888;
+}
+ol.linenums
+{
+    margin-top: 0;
+    margin-bottom: 0;
+}
+.prettyprint {
+    background: #000;
+}
+li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9
+{
+    color: #555;
+    list-style-type: decimal;
+}
+li.L1, li.L3, li.L5, li.L7, li.L9 {
+    background: #111;
+}
+@media print
+{
+    .str
+    {
+        color: #060;
+    }
+    .kwd
+    {
+        color: #006;
+        font-weight: bold;
+    }
+    .com
+    {
+        color: #600;
+        font-style: italic;
+    }
+    .typ
+    {
+        color: #404;
+        font-weight: bold;
+    }
+    .lit
+    {
+        color: #044;
+    }
+    .pun
+    {
+        color: #440;
+    }
+    .pln
+    {
+        color: #000;
+    }
+    .tag
+    {
+        color: #006;
+        font-weight: bold;
+    }
+    .atn
+    {
+        color: #404;
+    }
+    .atv
+    {
+        color: #060;
+    }
+}
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/brand.svg b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/brand.svg
index aeb9611..81cfe50 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/brand.svg
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/brand.svg
@@ -1,87 +1,87 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="270px" height="10px" viewBox="0 0 270 10" enable-background="new 0 0 270 10" xml:space="preserve">
-<g>
-	<g>
-		<path fill="#FFFFFF" d="M121.965,9.413h-4.883V0.656h4.883v0.903h-3.862V4.38h3.63v0.898h-3.63V8.5h3.862V9.413z"/>
-		<path fill="#FFFFFF" d="M130.988,9.413h-1.158l-4.789-7.352h-0.046c0.062,0.864,0.095,1.655,0.095,2.374v4.978h-0.94V0.656h1.15
-			l4.774,7.317h0.045c-0.006-0.107-0.022-0.453-0.051-1.041c-0.028-0.582-0.039-0.998-0.028-1.254V0.656h0.951v8.753h-0.003V9.413
-			L130.988,9.413z"/>
-		<path fill="#FFFFFF" d="M136.339,9.413h-1.018V1.561h-2.771V0.656h6.564v0.903h-2.771v7.852h-0.002v0.002H136.339z"/>
-		<path fill="#FFFFFF" d="M145.554,9.413h-4.877V0.656h4.877v0.903h-3.859V4.38h3.631v0.898h-3.631V8.5h3.859V9.413z"/>
-		<path fill="#FFFFFF" d="M148.761,5.769v3.641h-1.018V0.656h2.402c1.074,0,1.865,0.204,2.379,0.614
-			c0.514,0.412,0.771,1.032,0.771,1.858c0,1.156-0.586,1.94-1.764,2.349l2.383,3.934h-1.207l-2.121-3.645h-1.826V5.769
-			L148.761,5.769z M148.761,4.897h1.396c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285
-			c0-0.582-0.17-0.997-0.512-1.254c-0.34-0.255-0.889-0.381-1.643-0.381h-1.324v3.349h-0.004V4.897z"/>
-		<path fill="#FFFFFF" d="M161.124,3.209c0,0.884-0.301,1.567-0.904,2.046c-0.605,0.477-1.475,0.714-2.6,0.714h-1.031v3.444h-1.016
-			V0.656h2.27C160.03,0.656,161.124,1.504,161.124,3.209z M156.589,5.092h0.92c0.898,0,1.555-0.146,1.959-0.435
-			c0.4-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.568-1.295c-0.381-0.279-0.973-0.423-1.773-0.423h-1.139v3.557H156.589z
-			"/>
-		<path fill="#FFFFFF" d="M164.22,5.769v3.641h-1.02V0.656h2.402c1.074,0,1.865,0.204,2.383,0.614
-			c0.512,0.412,0.771,1.032,0.771,1.858c0,1.156-0.588,1.94-1.762,2.349l2.379,3.934h-1.205l-2.119-3.645h-1.826v0.002H164.22z
-			 M164.22,4.897h1.395c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285c0-0.582-0.17-0.997-0.51-1.254
-			c-0.34-0.255-0.887-0.381-1.645-0.381h-1.322v3.349h-0.004V4.897z"/>
-		<path fill="#FFFFFF" d="M171.03,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
-		<path fill="#FFFFFF" d="M179.636,7.081c0,0.773-0.281,1.374-0.838,1.805c-0.561,0.434-1.318,0.646-2.277,0.646
-			c-1.039,0-1.836-0.134-2.395-0.4V8.147c0.357,0.152,0.75,0.272,1.174,0.357c0.422,0.088,0.844,0.131,1.258,0.131
-			c0.68,0,1.188-0.129,1.531-0.384c0.346-0.257,0.514-0.62,0.514-1.073c0-0.304-0.061-0.556-0.184-0.748
-			c-0.119-0.194-0.318-0.375-0.607-0.537c-0.285-0.162-0.721-0.351-1.301-0.558c-0.816-0.29-1.398-0.636-1.748-1.036
-			c-0.352-0.398-0.525-0.92-0.525-1.562c0-0.674,0.254-1.211,0.764-1.611c0.508-0.398,1.178-0.599,2.014-0.599
-			c0.869,0,1.672,0.161,2.398,0.48l-0.316,0.884c-0.725-0.3-1.428-0.454-2.109-0.454c-0.539,0-0.959,0.114-1.266,0.347
-			c-0.303,0.231-0.453,0.553-0.453,0.965c0,0.305,0.057,0.551,0.168,0.745c0.115,0.195,0.303,0.372,0.566,0.533
-			c0.268,0.161,0.672,0.34,1.221,0.535c0.92,0.327,1.551,0.679,1.896,1.056C179.462,5.995,179.636,6.483,179.636,7.081z"/>
-		<path fill="#FFFFFF" d="M186.556,9.413h-4.881V0.656h4.881v0.903h-3.863V4.38h3.633v0.898h-3.633V8.5h3.863V9.413z"/>
-		<path fill="#FFFFFF" d="M197.677,9.413l-1.09-2.785h-3.51l-1.078,2.785h-1.031l3.463-8.793h0.854l3.443,8.793H197.677z
-			 M196.267,5.71l-1.018-2.712c-0.131-0.345-0.271-0.766-0.406-1.263c-0.09,0.383-0.211,0.804-0.377,1.263l-1.031,2.712H196.267z"/>
-		<path fill="#FFFFFF" d="M205.733,3.209c0,0.884-0.303,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.596,0.714h-1.031v3.444
-			h-1.021V0.656h2.273C204.642,0.656,205.733,1.504,205.733,3.209z M201.2,5.092h0.914c0.902,0,1.557-0.146,1.961-0.435
-			c0.398-0.293,0.605-0.759,0.605-1.404c0-0.577-0.189-1.006-0.57-1.295c-0.381-0.279-0.969-0.423-1.773-0.423H201.2V5.092
-			L201.2,5.092z"/>
-		<path fill="#FFFFFF" d="M213.366,3.209c0,0.884-0.307,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.598,0.714h-1.031v3.444h-1.02
-			V0.656h2.271C212.269,0.656,213.366,1.504,213.366,3.209z M208.827,5.092h0.918c0.904,0,1.559-0.146,1.959-0.435
-			c0.404-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.566-1.295c-0.381-0.279-0.971-0.423-1.773-0.423h-1.141V5.092
-			L208.827,5.092z"/>
-		<path fill="#FFFFFF" d="M215.44,9.413V0.656h1.021v7.832h3.857V9.41h-4.879V9.413z"/>
-		<path fill="#FFFFFF" d="M222.052,9.413V0.656h1.021v8.753h-1.021V9.413z"/>
-		<path fill="#FFFFFF" d="M229.466,1.44c-0.959,0-1.721,0.32-2.279,0.959c-0.557,0.642-0.834,1.518-0.834,2.633
-			c0,1.146,0.27,2.031,0.807,2.656c0.537,0.621,1.303,0.937,2.299,0.937c0.611,0,1.309-0.108,2.09-0.327v0.891
-			c-0.605,0.229-1.355,0.343-2.244,0.343c-1.289,0-2.285-0.396-2.988-1.181c-0.699-0.776-1.051-1.891-1.051-3.333
-			c0-0.902,0.17-1.69,0.506-2.371c0.336-0.678,0.824-1.202,1.461-1.569s1.387-0.551,2.248-0.551c0.918,0,1.719,0.168,2.408,0.504
-			l-0.432,0.875C230.798,1.594,230.13,1.44,229.466,1.44z"/>
-		<path fill="#FFFFFF" d="M239.204,9.413l-1.09-2.785h-3.512l-1.074,2.785h-1.031l3.459-8.793h0.857l3.445,8.793H239.204z
-			 M237.798,5.71l-1.018-2.712c-0.133-0.345-0.27-0.766-0.406-1.263c-0.088,0.383-0.215,0.804-0.377,1.263l-1.033,2.712H237.798z"/>
-		<path fill="#FFFFFF" d="M244.401,9.413h-1.016V1.561h-2.773V0.656h6.564v0.903h-2.771v7.852h-0.004V9.413z"/>
-		<path fill="#FFFFFF" d="M248.743,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
-		<path fill="#FFFFFF" d="M260.005,5.021c0,1.402-0.354,2.503-1.062,3.305c-0.707,0.806-1.691,1.206-2.955,1.206
-			c-1.291,0-2.285-0.396-2.988-1.186c-0.699-0.789-1.051-1.901-1.051-3.338c0-1.424,0.354-2.532,1.057-3.312
-			c0.699-0.785,1.703-1.18,2.99-1.18c1.262,0,2.24,0.399,2.951,1.2C259.655,2.513,260.005,3.614,260.005,5.021z M253.03,5.021
-			c0,1.186,0.25,2.085,0.754,2.697c0.508,0.613,1.242,0.922,2.203,0.922c0.973,0,1.705-0.311,2.201-0.918
-			c0.494-0.615,0.738-1.516,0.738-2.702c0-1.179-0.244-2.072-0.736-2.681c-0.49-0.61-1.223-0.914-2.189-0.914
-			c-0.969,0-1.705,0.306-2.213,0.918C253.282,2.96,253.03,3.851,253.03,5.021z"/>
-		<path fill="#FFFFFF" d="M269.044,9.413h-1.162l-4.783-7.352h-0.049c0.061,0.864,0.094,1.655,0.094,2.374v4.978H262.2V0.656h1.152
-			l4.771,7.319h0.049c-0.012-0.108-0.025-0.455-0.055-1.041c-0.027-0.582-0.041-0.998-0.029-1.256V0.656h0.951v8.755h0.006v0.002
-			H269.044z"/>
-	</g>
-	<g>
-		<path fill="#FFFFFF" d="M7.533,3.368c0,1.013-0.298,1.796-0.896,2.348C6.04,6.269,5.191,6.544,4.093,6.544H3.403v3.008H0.954
-			V0.485h3.139c1.145,0,2.005,0.25,2.58,0.75C7.246,1.736,7.533,2.447,7.533,3.368z M3.403,4.547h0.447
-			c0.368,0,0.66-0.103,0.877-0.31s0.326-0.492,0.326-0.856c0-0.612-0.339-0.918-1.018-0.918H3.403V4.547z"/>
-		<path fill="#FFFFFF" d="M17.652,9.552l-0.446-1.699h-2.944l-0.459,1.699h-2.691l2.958-9.104h3.268l2.995,9.104H17.652z
-			 M16.697,5.843l-0.39-1.489c-0.092-0.33-0.202-0.758-0.333-1.283c-0.13-0.525-0.216-0.901-0.257-1.128
-			c-0.037,0.211-0.111,0.558-0.221,1.042c-0.108,0.483-0.353,1.437-0.729,2.857H16.697z"/>
-		<path fill="#FFFFFF" d="M28.423,9.552h-2.449V2.488H23.76V0.485h6.871v2.003h-2.208V9.552z"/>
-		<path fill="#FFFFFF" d="M39.037,9.552h-2.449V2.488h-2.214V0.485h6.871v2.003h-2.208V9.552z"/>
-		<path fill="#FFFFFF" d="M51.035,9.552h-5.382V0.485h5.382V2.45h-2.933v1.427h2.716v1.966h-2.716v1.711h2.933V9.552z"/>
-		<path fill="#FFFFFF" d="M58.184,6.253v3.299h-2.449V0.485h2.97c2.464,0,3.696,0.893,3.696,2.679c0,1.05-0.513,1.862-1.538,2.437
-			l2.642,3.951h-2.777l-1.922-3.299H58.184z M58.184,4.41h0.459c0.855,0,1.284-0.378,1.284-1.135c0-0.625-0.42-0.937-1.26-0.937
-			h-0.483V4.41z"/>
-		<path fill="#FFFFFF" d="M76.072,9.552H72.86L69.55,3.164h-0.057c0.079,1.004,0.118,1.771,0.118,2.301v4.086h-2.17V0.485h3.2
-			l3.299,6.301h0.037c-0.059-0.914-0.086-1.648-0.086-2.202V0.485h2.183v9.066H76.072z"/>
-		<path fill="#FFFFFF" d="M83.557,9.552h-2.412V0.485h5.356V2.45h-2.944v1.73h2.716v1.965h-2.716V9.552z"/>
-		<path fill="#FFFFFF" d="M91.102,9.552V0.485h2.449v7.088h3.49v1.979H91.102z"/>
-		<path fill="#FFFFFF" d="M104.842,3.846l1.562-3.361h2.654l-2.983,5.525v3.541h-2.468V6.085l-2.983-5.6h2.667L104.842,3.846z"/>
-	</g>
-</g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="270px" height="10px" viewBox="0 0 270 10" enable-background="new 0 0 270 10" xml:space="preserve">
+<g>
+	<g>
+		<path fill="#FFFFFF" d="M121.965,9.413h-4.883V0.656h4.883v0.903h-3.862V4.38h3.63v0.898h-3.63V8.5h3.862V9.413z"/>
+		<path fill="#FFFFFF" d="M130.988,9.413h-1.158l-4.789-7.352h-0.046c0.062,0.864,0.095,1.655,0.095,2.374v4.978h-0.94V0.656h1.15
+			l4.774,7.317h0.045c-0.006-0.107-0.022-0.453-0.051-1.041c-0.028-0.582-0.039-0.998-0.028-1.254V0.656h0.951v8.753h-0.003V9.413
+			L130.988,9.413z"/>
+		<path fill="#FFFFFF" d="M136.339,9.413h-1.018V1.561h-2.771V0.656h6.564v0.903h-2.771v7.852h-0.002v0.002H136.339z"/>
+		<path fill="#FFFFFF" d="M145.554,9.413h-4.877V0.656h4.877v0.903h-3.859V4.38h3.631v0.898h-3.631V8.5h3.859V9.413z"/>
+		<path fill="#FFFFFF" d="M148.761,5.769v3.641h-1.018V0.656h2.402c1.074,0,1.865,0.204,2.379,0.614
+			c0.514,0.412,0.771,1.032,0.771,1.858c0,1.156-0.586,1.94-1.764,2.349l2.383,3.934h-1.207l-2.121-3.645h-1.826V5.769
+			L148.761,5.769z M148.761,4.897h1.396c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285
+			c0-0.582-0.17-0.997-0.512-1.254c-0.34-0.255-0.889-0.381-1.643-0.381h-1.324v3.349h-0.004V4.897z"/>
+		<path fill="#FFFFFF" d="M161.124,3.209c0,0.884-0.301,1.567-0.904,2.046c-0.605,0.477-1.475,0.714-2.6,0.714h-1.031v3.444h-1.016
+			V0.656h2.27C160.03,0.656,161.124,1.504,161.124,3.209z M156.589,5.092h0.92c0.898,0,1.555-0.146,1.959-0.435
+			c0.4-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.568-1.295c-0.381-0.279-0.973-0.423-1.773-0.423h-1.139v3.557H156.589z
+			"/>
+		<path fill="#FFFFFF" d="M164.22,5.769v3.641h-1.02V0.656h2.402c1.074,0,1.865,0.204,2.383,0.614
+			c0.512,0.412,0.771,1.032,0.771,1.858c0,1.156-0.588,1.94-1.762,2.349l2.379,3.934h-1.205l-2.119-3.645h-1.826v0.002H164.22z
+			 M164.22,4.897h1.395c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285c0-0.582-0.17-0.997-0.51-1.254
+			c-0.34-0.255-0.887-0.381-1.645-0.381h-1.322v3.349h-0.004V4.897z"/>
+		<path fill="#FFFFFF" d="M171.03,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
+		<path fill="#FFFFFF" d="M179.636,7.081c0,0.773-0.281,1.374-0.838,1.805c-0.561,0.434-1.318,0.646-2.277,0.646
+			c-1.039,0-1.836-0.134-2.395-0.4V8.147c0.357,0.152,0.75,0.272,1.174,0.357c0.422,0.088,0.844,0.131,1.258,0.131
+			c0.68,0,1.188-0.129,1.531-0.384c0.346-0.257,0.514-0.62,0.514-1.073c0-0.304-0.061-0.556-0.184-0.748
+			c-0.119-0.194-0.318-0.375-0.607-0.537c-0.285-0.162-0.721-0.351-1.301-0.558c-0.816-0.29-1.398-0.636-1.748-1.036
+			c-0.352-0.398-0.525-0.92-0.525-1.562c0-0.674,0.254-1.211,0.764-1.611c0.508-0.398,1.178-0.599,2.014-0.599
+			c0.869,0,1.672,0.161,2.398,0.48l-0.316,0.884c-0.725-0.3-1.428-0.454-2.109-0.454c-0.539,0-0.959,0.114-1.266,0.347
+			c-0.303,0.231-0.453,0.553-0.453,0.965c0,0.305,0.057,0.551,0.168,0.745c0.115,0.195,0.303,0.372,0.566,0.533
+			c0.268,0.161,0.672,0.34,1.221,0.535c0.92,0.327,1.551,0.679,1.896,1.056C179.462,5.995,179.636,6.483,179.636,7.081z"/>
+		<path fill="#FFFFFF" d="M186.556,9.413h-4.881V0.656h4.881v0.903h-3.863V4.38h3.633v0.898h-3.633V8.5h3.863V9.413z"/>
+		<path fill="#FFFFFF" d="M197.677,9.413l-1.09-2.785h-3.51l-1.078,2.785h-1.031l3.463-8.793h0.854l3.443,8.793H197.677z
+			 M196.267,5.71l-1.018-2.712c-0.131-0.345-0.271-0.766-0.406-1.263c-0.09,0.383-0.211,0.804-0.377,1.263l-1.031,2.712H196.267z"/>
+		<path fill="#FFFFFF" d="M205.733,3.209c0,0.884-0.303,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.596,0.714h-1.031v3.444
+			h-1.021V0.656h2.273C204.642,0.656,205.733,1.504,205.733,3.209z M201.2,5.092h0.914c0.902,0,1.557-0.146,1.961-0.435
+			c0.398-0.293,0.605-0.759,0.605-1.404c0-0.577-0.189-1.006-0.57-1.295c-0.381-0.279-0.969-0.423-1.773-0.423H201.2V5.092
+			L201.2,5.092z"/>
+		<path fill="#FFFFFF" d="M213.366,3.209c0,0.884-0.307,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.598,0.714h-1.031v3.444h-1.02
+			V0.656h2.271C212.269,0.656,213.366,1.504,213.366,3.209z M208.827,5.092h0.918c0.904,0,1.559-0.146,1.959-0.435
+			c0.404-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.566-1.295c-0.381-0.279-0.971-0.423-1.773-0.423h-1.141V5.092
+			L208.827,5.092z"/>
+		<path fill="#FFFFFF" d="M215.44,9.413V0.656h1.021v7.832h3.857V9.41h-4.879V9.413z"/>
+		<path fill="#FFFFFF" d="M222.052,9.413V0.656h1.021v8.753h-1.021V9.413z"/>
+		<path fill="#FFFFFF" d="M229.466,1.44c-0.959,0-1.721,0.32-2.279,0.959c-0.557,0.642-0.834,1.518-0.834,2.633
+			c0,1.146,0.27,2.031,0.807,2.656c0.537,0.621,1.303,0.937,2.299,0.937c0.611,0,1.309-0.108,2.09-0.327v0.891
+			c-0.605,0.229-1.355,0.343-2.244,0.343c-1.289,0-2.285-0.396-2.988-1.181c-0.699-0.776-1.051-1.891-1.051-3.333
+			c0-0.902,0.17-1.69,0.506-2.371c0.336-0.678,0.824-1.202,1.461-1.569s1.387-0.551,2.248-0.551c0.918,0,1.719,0.168,2.408,0.504
+			l-0.432,0.875C230.798,1.594,230.13,1.44,229.466,1.44z"/>
+		<path fill="#FFFFFF" d="M239.204,9.413l-1.09-2.785h-3.512l-1.074,2.785h-1.031l3.459-8.793h0.857l3.445,8.793H239.204z
+			 M237.798,5.71l-1.018-2.712c-0.133-0.345-0.27-0.766-0.406-1.263c-0.088,0.383-0.215,0.804-0.377,1.263l-1.033,2.712H237.798z"/>
+		<path fill="#FFFFFF" d="M244.401,9.413h-1.016V1.561h-2.773V0.656h6.564v0.903h-2.771v7.852h-0.004V9.413z"/>
+		<path fill="#FFFFFF" d="M248.743,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
+		<path fill="#FFFFFF" d="M260.005,5.021c0,1.402-0.354,2.503-1.062,3.305c-0.707,0.806-1.691,1.206-2.955,1.206
+			c-1.291,0-2.285-0.396-2.988-1.186c-0.699-0.789-1.051-1.901-1.051-3.338c0-1.424,0.354-2.532,1.057-3.312
+			c0.699-0.785,1.703-1.18,2.99-1.18c1.262,0,2.24,0.399,2.951,1.2C259.655,2.513,260.005,3.614,260.005,5.021z M253.03,5.021
+			c0,1.186,0.25,2.085,0.754,2.697c0.508,0.613,1.242,0.922,2.203,0.922c0.973,0,1.705-0.311,2.201-0.918
+			c0.494-0.615,0.738-1.516,0.738-2.702c0-1.179-0.244-2.072-0.736-2.681c-0.49-0.61-1.223-0.914-2.189-0.914
+			c-0.969,0-1.705,0.306-2.213,0.918C253.282,2.96,253.03,3.851,253.03,5.021z"/>
+		<path fill="#FFFFFF" d="M269.044,9.413h-1.162l-4.783-7.352h-0.049c0.061,0.864,0.094,1.655,0.094,2.374v4.978H262.2V0.656h1.152
+			l4.771,7.319h0.049c-0.012-0.108-0.025-0.455-0.055-1.041c-0.027-0.582-0.041-0.998-0.029-1.256V0.656h0.951v8.755h0.006v0.002
+			H269.044z"/>
+	</g>
+	<g>
+		<path fill="#FFFFFF" d="M7.533,3.368c0,1.013-0.298,1.796-0.896,2.348C6.04,6.269,5.191,6.544,4.093,6.544H3.403v3.008H0.954
+			V0.485h3.139c1.145,0,2.005,0.25,2.58,0.75C7.246,1.736,7.533,2.447,7.533,3.368z M3.403,4.547h0.447
+			c0.368,0,0.66-0.103,0.877-0.31s0.326-0.492,0.326-0.856c0-0.612-0.339-0.918-1.018-0.918H3.403V4.547z"/>
+		<path fill="#FFFFFF" d="M17.652,9.552l-0.446-1.699h-2.944l-0.459,1.699h-2.691l2.958-9.104h3.268l2.995,9.104H17.652z
+			 M16.697,5.843l-0.39-1.489c-0.092-0.33-0.202-0.758-0.333-1.283c-0.13-0.525-0.216-0.901-0.257-1.128
+			c-0.037,0.211-0.111,0.558-0.221,1.042c-0.108,0.483-0.353,1.437-0.729,2.857H16.697z"/>
+		<path fill="#FFFFFF" d="M28.423,9.552h-2.449V2.488H23.76V0.485h6.871v2.003h-2.208V9.552z"/>
+		<path fill="#FFFFFF" d="M39.037,9.552h-2.449V2.488h-2.214V0.485h6.871v2.003h-2.208V9.552z"/>
+		<path fill="#FFFFFF" d="M51.035,9.552h-5.382V0.485h5.382V2.45h-2.933v1.427h2.716v1.966h-2.716v1.711h2.933V9.552z"/>
+		<path fill="#FFFFFF" d="M58.184,6.253v3.299h-2.449V0.485h2.97c2.464,0,3.696,0.893,3.696,2.679c0,1.05-0.513,1.862-1.538,2.437
+			l2.642,3.951h-2.777l-1.922-3.299H58.184z M58.184,4.41h0.459c0.855,0,1.284-0.378,1.284-1.135c0-0.625-0.42-0.937-1.26-0.937
+			h-0.483V4.41z"/>
+		<path fill="#FFFFFF" d="M76.072,9.552H72.86L69.55,3.164h-0.057c0.079,1.004,0.118,1.771,0.118,2.301v4.086h-2.17V0.485h3.2
+			l3.299,6.301h0.037c-0.059-0.914-0.086-1.648-0.086-2.202V0.485h2.183v9.066H76.072z"/>
+		<path fill="#FFFFFF" d="M83.557,9.552h-2.412V0.485h5.356V2.45h-2.944v1.73h2.716v1.965h-2.716V9.552z"/>
+		<path fill="#FFFFFF" d="M91.102,9.552V0.485h2.449v7.088h3.49v1.979H91.102z"/>
+		<path fill="#FFFFFF" d="M104.842,3.846l1.562-3.361h2.654l-2.983,5.525v3.541h-2.468V6.085l-2.983-5.6h2.667L104.842,3.846z"/>
+	</g>
+</g>
+</svg>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/logo.svg b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/logo.svg
index a04f0f9..b9ce0ac 100755
--- a/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/logo.svg
+++ b/forms/common-themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/img/logo.svg
@@ -1,22 +1,22 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="73px" height="69px" viewBox="0 0 73 69" enable-background="new 0 0 73 69" xml:space="preserve">
-<g>
-	<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="36.2046" y1="2.1504" x2="36.2046" y2="68.6623">
-		<stop  offset="0" style="stop-color:#60EFFF"/>
-		<stop  offset="1" style="stop-color:#1F89C7"/>
-	</linearGradient>
-	<path fill="url(#SVGID_1_)" d="M36.287,0.137l0.008-0.063l-0.031,0.039l-0.012-0.012L36.262,0l-0.057,0.056L36.148,0l0.011,0.101
-		l-0.013,0.012l-0.03-0.039l0.007,0.063L0,35.447l14.307,20.267l11.05-2.538l10.848,15.255l10.85-15.255l11.05,2.538l8.861-12.554
-		l5.444-7.713L36.287,0.137z M35.108,4.282L30.174,50.52l-9.642-13.151L35.108,4.282z M20.059,36.725l-6.068-8.277L35.057,2.683
-		L20.059,36.725z M29.967,51.407l-4.313,0.99l-7.251-10.193l1.807-4.104L29.967,51.407z M36.092,2.051l0.113-0.258l0.114,0.257
-		l5.102,49.711l-0.015-0.01l-4.999,7.387l-5.409-7.396l-0.007,0.004L36.092,2.051z M42.237,50.521L37.303,4.281l14.576,33.087
-		L42.237,50.521z M52.201,38.101l1.808,4.104l-7.251,10.193l-4.312-0.99L52.201,38.101z M37.355,2.684L58.42,28.448l-6.067,8.277
-		L37.355,2.684z M14.605,54.935L0.907,35.53L32.779,4.374L13.114,28.425l6.623,9.03l-2.127,4.83l7.312,10.28L14.605,54.935z
-		 M36.205,67.235L26.086,53.009l4.326-0.992l0.072,0.099l-0.045,0.034l5.988,8.191l5.552-8.201l-0.048-0.032L42,52.017l4.324,0.992
-		L36.205,67.235z M66.4,42.762l-8.594,12.173l-10.317-2.369l7.312-10.28l-2.127-4.83l6.622-9.03L39.633,4.374L71.504,35.53
-		L66.4,42.762z"/>
-</g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="73px" height="69px" viewBox="0 0 73 69" enable-background="new 0 0 73 69" xml:space="preserve">
+<g>
+	<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="36.2046" y1="2.1504" x2="36.2046" y2="68.6623">
+		<stop  offset="0" style="stop-color:#60EFFF"/>
+		<stop  offset="1" style="stop-color:#1F89C7"/>
+	</linearGradient>
+	<path fill="url(#SVGID_1_)" d="M36.287,0.137l0.008-0.063l-0.031,0.039l-0.012-0.012L36.262,0l-0.057,0.056L36.148,0l0.011,0.101
+		l-0.013,0.012l-0.03-0.039l0.007,0.063L0,35.447l14.307,20.267l11.05-2.538l10.848,15.255l10.85-15.255l11.05,2.538l8.861-12.554
+		l5.444-7.713L36.287,0.137z M35.108,4.282L30.174,50.52l-9.642-13.151L35.108,4.282z M20.059,36.725l-6.068-8.277L35.057,2.683
+		L20.059,36.725z M29.967,51.407l-4.313,0.99l-7.251-10.193l1.807-4.104L29.967,51.407z M36.092,2.051l0.113-0.258l0.114,0.257
+		l5.102,49.711l-0.015-0.01l-4.999,7.387l-5.409-7.396l-0.007,0.004L36.092,2.051z M42.237,50.521L37.303,4.281l14.576,33.087
+		L42.237,50.521z M52.201,38.101l1.808,4.104l-7.251,10.193l-4.312-0.99L52.201,38.101z M37.355,2.684L58.42,28.448l-6.067,8.277
+		L37.355,2.684z M14.605,54.935L0.907,35.53L32.779,4.374L13.114,28.425l6.623,9.03l-2.127,4.83l7.312,10.28L14.605,54.935z
+		 M36.205,67.235L26.086,53.009l4.326-0.992l0.072,0.099l-0.045,0.034l5.988,8.191l5.552-8.201l-0.048-0.032L42,52.017l4.324,0.992
+		L36.205,67.235z M66.4,42.762l-8.594,12.173l-10.317-2.369l7.312-10.28l-2.127-4.83l6.622-9.03L39.633,4.374L71.504,35.53
+		L66.4,42.762z"/>
+</g>
+</svg>
diff --git a/forms/email-api/pom.xml b/forms/email-api/pom.xml
index 4eb50b9..f6f37dc 100755
--- a/forms/email-api/pom.xml
+++ b/forms/email-api/pom.xml
@@ -1,47 +1,47 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-email-api</artifactId>
-	<name>Keycloak Email API</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-email-api</artifactId>
+	<name>Keycloak Email API</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/email-freemarker/pom.xml b/forms/email-freemarker/pom.xml
index 31a5f4a..9d51f68 100755
--- a/forms/email-freemarker/pom.xml
+++ b/forms/email-freemarker/pom.xml
@@ -1,72 +1,72 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-forms-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-email-freemarker</artifactId>
-    <name>Keycloak Email FreeMarker</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.freemarker</groupId>
-            <artifactId>freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.mail</groupId>
-            <artifactId>mail</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-forms-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-email-freemarker</artifactId>
+    <name>Keycloak Email FreeMarker</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/forms/login-api/pom.xml b/forms/login-api/pom.xml
index da72ddf..c35db01 100755
--- a/forms/login-api/pom.xml
+++ b/forms/login-api/pom.xml
@@ -1,52 +1,52 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-login-api</artifactId>
-	<name>Keycloak Login API</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                    <source>${maven.compiler.source}</source>
-                                    <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-login-api</artifactId>
+	<name>Keycloak Login API</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                    <source>${maven.compiler.source}</source>
+                                    <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
index dd5bc60..cad0c1a 100755
--- a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
+++ b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
@@ -1,81 +1,81 @@
-package org.keycloak.login;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.provider.Provider;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public interface LoginFormsProvider extends Provider {
-
-    public Response createResponse(UserModel.RequiredAction action);
-
-    Response createForm(String form, Map<String, Object> attributes);
-
-    public Response createLogin();
-
-    public Response createPasswordReset();
-
-    public Response createLoginTotp();
-
-    public Response createRegistration();
-
-    public Response createInfoPage();
-
-    public Response createErrorPage();
-
-    public Response createOAuthGrant(ClientSessionModel clientSessionModel);
-
-    public Response createCode();
-
-    public LoginFormsProvider setClientSessionCode(String accessCode);
-
-    public LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String,RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappers);
-    public LoginFormsProvider setAccessRequest(String message);
-
-    /**
-     * Set one global error message.
-     * 
-     * @param message key of message
-     * @param parameters to be formatted into message
-     */
-    public LoginFormsProvider setError(String message, Object ... parameters);
-    
-    /**
-     * Set multiple error messages.
-     * 
-     * @param messages to be set
-     */
-    public LoginFormsProvider setErrors(List<FormMessage> messages);
-
-    LoginFormsProvider addError(FormMessage errorMessage);
-
-    public LoginFormsProvider setSuccess(String message, Object ... parameters);
-
-    public LoginFormsProvider setUser(UserModel user);
-
-    public LoginFormsProvider setResponseHeader(String headerName, String headerValue);
-
-    public LoginFormsProvider setFormData(MultivaluedMap<String, String> formData);
-
-    LoginFormsProvider setAttribute(String name, Object value);
-
-    public LoginFormsProvider setStatus(Response.Status status);
-
-    LoginFormsProvider setActionUri(URI requestUri);
-}
+package org.keycloak.login;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface LoginFormsProvider extends Provider {
+
+    public Response createResponse(UserModel.RequiredAction action);
+
+    Response createForm(String form, Map<String, Object> attributes);
+
+    public Response createLogin();
+
+    public Response createPasswordReset();
+
+    public Response createLoginTotp();
+
+    public Response createRegistration();
+
+    public Response createInfoPage();
+
+    public Response createErrorPage();
+
+    public Response createOAuthGrant(ClientSessionModel clientSessionModel);
+
+    public Response createCode();
+
+    public LoginFormsProvider setClientSessionCode(String accessCode);
+
+    public LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String,RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappers);
+    public LoginFormsProvider setAccessRequest(String message);
+
+    /**
+     * Set one global error message.
+     * 
+     * @param message key of message
+     * @param parameters to be formatted into message
+     */
+    public LoginFormsProvider setError(String message, Object ... parameters);
+    
+    /**
+     * Set multiple error messages.
+     * 
+     * @param messages to be set
+     */
+    public LoginFormsProvider setErrors(List<FormMessage> messages);
+
+    LoginFormsProvider addError(FormMessage errorMessage);
+
+    public LoginFormsProvider setSuccess(String message, Object ... parameters);
+
+    public LoginFormsProvider setUser(UserModel user);
+
+    public LoginFormsProvider setResponseHeader(String headerName, String headerValue);
+
+    public LoginFormsProvider setFormData(MultivaluedMap<String, String> formData);
+
+    LoginFormsProvider setAttribute(String name, Object value);
+
+    public LoginFormsProvider setStatus(Response.Status status);
+
+    LoginFormsProvider setActionUri(URI requestUri);
+}
diff --git a/forms/login-freemarker/pom.xml b/forms/login-freemarker/pom.xml
index 7e18b3a..e725efe 100755
--- a/forms/login-freemarker/pom.xml
+++ b/forms/login-freemarker/pom.xml
@@ -1,88 +1,88 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-forms-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-login-freemarker</artifactId>
-	<name>Keycloak Login FreeMarker</name>
-	<description />
-
-	<dependencies>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-login-api</artifactId>
-            <scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-email-api</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-social-core</artifactId>
-            <scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.freemarker</groupId>
-            <artifactId>freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-                                        <source>${maven.compiler.source}</source>
-                                        <target>${maven.compiler.target}</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-forms-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-login-freemarker</artifactId>
+	<name>Keycloak Login FreeMarker</name>
+	<description />
+
+	<dependencies>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-login-api</artifactId>
+            <scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-email-api</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+                                        <source>${maven.compiler.source}</source>
+                                        <target>${maven.compiler.target}</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
index 2f74db9..245e625 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -1,533 +1,533 @@
-package org.keycloak.login.freemarker;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.email.EmailException;
-import org.keycloak.email.EmailProvider;
-import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
-import org.keycloak.freemarker.FreeMarkerException;
-import org.keycloak.freemarker.FreeMarkerUtil;
-import org.keycloak.freemarker.LocaleHelper;
-import org.keycloak.freemarker.Theme;
-import org.keycloak.freemarker.ThemeProvider;
-import org.keycloak.freemarker.beans.AdvancedMessageFormatterMethod;
-import org.keycloak.freemarker.beans.LocaleBean;
-import org.keycloak.freemarker.beans.MessageBean;
-import org.keycloak.freemarker.beans.MessageFormatterMethod;
-import org.keycloak.freemarker.beans.MessageType;
-import org.keycloak.freemarker.beans.MessagesPerFieldBean;
-import org.keycloak.login.LoginFormsPages;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.login.freemarker.model.ClientBean;
-import org.keycloak.login.freemarker.model.CodeBean;
-import org.keycloak.login.freemarker.model.IdentityProviderBean;
-import org.keycloak.login.freemarker.model.LoginBean;
-import org.keycloak.login.freemarker.model.OAuthGrantBean;
-import org.keycloak.login.freemarker.model.ProfileBean;
-import org.keycloak.login.freemarker.model.RealmBean;
-import org.keycloak.login.freemarker.model.RegisterBean;
-import org.keycloak.login.freemarker.model.RequiredActionUrlFormatterMethod;
-import org.keycloak.login.freemarker.model.TotpBean;
-import org.keycloak.login.freemarker.model.UrlBean;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.services.Urls;
-import org.keycloak.services.messages.Messages;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.net.URI;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
-
-    private static final Logger logger = Logger.getLogger(FreeMarkerLoginFormsProvider.class);
-
-    private String accessCode;
-    private Response.Status status;
-    private List<RoleModel> realmRolesRequested;
-    private MultivaluedMap<String, RoleModel> resourceRolesRequested;
-    private List<ProtocolMapperModel> protocolMappersRequested;
-    private MultivaluedMap<String, String> queryParams;
-    private Map<String, String> httpResponseHeaders = new HashMap<String, String>();
-    private String accessRequestMessage;
-    private URI actionUri;
-
-    private List<FormMessage> messages = null;
-    private MessageType messageType = MessageType.ERROR;
-
-    private MultivaluedMap<String, String> formData;
-
-    private KeycloakSession session;
-    private FreeMarkerUtil freeMarker;
-
-    private UserModel user;
-
-    private ClientSessionModel clientSession;
-    private final Map<String, Object> attributes = new HashMap<String, Object>();
-
-    public FreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
-        this.session = session;
-        this.freeMarker = freeMarker;
-    }
-
-    public Response createResponse(UserModel.RequiredAction action) {
-        RealmModel realm = session.getContext().getRealm();
-        UriInfo uriInfo = session.getContext().getUri();
-
-        String actionMessage;
-        LoginFormsPages page;
-
-        switch (action) {
-            case CONFIGURE_TOTP:
-                actionMessage = Messages.CONFIGURE_TOTP;
-                page = LoginFormsPages.LOGIN_CONFIG_TOTP;
-                break;
-            case UPDATE_PROFILE:
-                actionMessage = Messages.UPDATE_PROFILE;
-                page = LoginFormsPages.LOGIN_UPDATE_PROFILE;
-                break;
-            case UPDATE_PASSWORD:
-                actionMessage = Messages.UPDATE_PASSWORD;
-                page = LoginFormsPages.LOGIN_UPDATE_PASSWORD;
-                break;
-            case VERIFY_EMAIL:
-                try {
-                    UriBuilder builder = Urls.loginActionEmailVerificationBuilder(uriInfo.getBaseUri());
-                    builder.queryParam("key", accessCode);
-
-                    String link = builder.build(realm.getName()).toString();
-                    long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
-
-                    session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendVerifyEmail(link, expiration);
-                } catch (EmailException e) {
-                    logger.error("Failed to send verification email", e);
-                    return setError(Messages.EMAIL_SENT_ERROR).createErrorPage();
-                }
-
-                actionMessage = Messages.VERIFY_EMAIL;
-                page = LoginFormsPages.LOGIN_VERIFY_EMAIL;
-                break;
-            default:
-                return Response.serverError().build();
-        }
-
-        if (messages == null) {
-            setMessage(MessageType.WARNING, actionMessage);
-        }
-
-        return createResponse(page);
-    }
-
-    private Response createResponse(LoginFormsPages page) {
-        RealmModel realm = session.getContext().getRealm();
-        ClientModel client = session.getContext().getClient();
-        UriInfo uriInfo = session.getContext().getUri();
-
-        MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
-
-        String requestURI = uriInfo.getBaseUri().getPath();
-        UriBuilder uriBuilder = UriBuilder.fromUri(requestURI);
-
-        for (String k : queryParameterMap.keySet()) {
-
-            Object[] objects = queryParameterMap.get(k).toArray();
-            if (objects.length == 1 && objects[0] == null) continue; //
-            uriBuilder.replaceQueryParam(k, objects);
-        }
-
-        if (accessCode != null) {
-            uriBuilder.replaceQueryParam(OAuth2Constants.CODE, accessCode);
-        }
-
-        ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
-        Theme theme;
-        try {
-            theme = themeProvider.getTheme(realm.getLoginTheme(), Theme.Type.LOGIN);
-        } catch (IOException e) {
-            logger.error("Failed to create theme", e);
-            return Response.serverError().build();
-        }
-
-        try {
-            attributes.put("properties", theme.getProperties());
-        } catch (IOException e) {
-            logger.warn("Failed to load properties", e);
-        }
-
-        Properties messagesBundle;
-        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
-        try {
-            messagesBundle = theme.getMessages(locale);
-            attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
-        } catch (IOException e) {
-            logger.warn("Failed to load messages", e);
-            messagesBundle = new Properties();
-        }
-
-        MessagesPerFieldBean messagesPerField = new MessagesPerFieldBean();
-        if (messages != null) {
-            MessageBean wholeMessage = new MessageBean(null, messageType);
-            for (FormMessage message : this.messages) {
-                String formattedMessageText = formatMessage(message, messagesBundle, locale);
-                if (formattedMessageText != null) {
-                    wholeMessage.appendSummaryLine(formattedMessageText);
-                    messagesPerField.addMessage(message.getField(), formattedMessageText, messageType);
-                }
-            }
-            attributes.put("message", wholeMessage);
-        }
-        attributes.put("messagesPerField", messagesPerField);
-
-        if (page == LoginFormsPages.OAUTH_GRANT) {
-            // for some reason Resteasy 2.3.7 doesn't like query params and form params with the same name and will null out the code form param
-            uriBuilder.replaceQuery(null);
-        }
-        URI baseUri = uriBuilder.build();
-        attributes.put("requiredActionUrl", new RequiredActionUrlFormatterMethod(realm, baseUri));
-        if (realm != null && user != null && session != null) {
-            attributes.put("authenticatorConfigured", new AuthenticatorConfiguredMethod(realm, user, session));
-        }
-
-        if (realm != null) {
-            attributes.put("realm", new RealmBean(realm));
-            attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
-            attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
-
-            if (realm.isInternationalizationEnabled()) {
-                UriBuilder b;
-                switch (page) {
-                    case LOGIN:
-                        b = UriBuilder.fromUri(Urls.realmLoginPage(baseUri, realm.getName()));
-                        break;
-                    case REGISTER:
-                        b = UriBuilder.fromUri(Urls.realmRegisterPage(baseUri, realm.getName()));
-                        break;
-                    default:
-                        b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
-                        break;
-                }
-                attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle));
-            }
-        }
-
-        if (client != null) {
-            attributes.put("client", new ClientBean(client));
-        }
-
-        attributes.put("login", new LoginBean(formData));
-
-        switch (page) {
-            case LOGIN_CONFIG_TOTP:
-                attributes.put("totp", new TotpBean(realm, user, baseUri));
-                break;
-            case LOGIN_UPDATE_PROFILE:
-                attributes.put("user", new ProfileBean(user));
-                break;
-            case REGISTER:
-                attributes.put("register", new RegisterBean(formData));
-                break;
-            case OAUTH_GRANT:
-                attributes.put("oauth", new OAuthGrantBean(accessCode, clientSession, client, realmRolesRequested, resourceRolesRequested, protocolMappersRequested, this.accessRequestMessage));
-                attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle));
-                break;
-            case CODE:
-                attributes.put(OAuth2Constants.CODE, new CodeBean(accessCode, messageType == MessageType.ERROR ? getFirstMessageUnformatted() : null));
-                break;
-        }
-
-        if (status == null) {
-            status = Response.Status.OK;
-        }
-
-        try {
-            String result = freeMarker.processTemplate(attributes, Templates.getTemplate(page), theme);
-            Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result);
-            BrowserSecurityHeaderSetup.headers(builder, realm);
-            for (Map.Entry<String, String> entry : httpResponseHeaders.entrySet()) {
-                builder.header(entry.getKey(), entry.getValue());
-            }
-            LocaleHelper.updateLocaleCookie(builder, locale, realm, uriInfo, Urls.localeCookiePath(baseUri, realm.getName()));
-            return builder.build();
-        } catch (FreeMarkerException e) {
-            logger.error("Failed to process template", e);
-            return Response.serverError().build();
-        }
-    }
-
-    @Override
-    public Response createForm(String form, Map<String, Object> extraAttributes) {
-
-        RealmModel realm = session.getContext().getRealm();
-        ClientModel client = session.getContext().getClient();
-        UriInfo uriInfo = session.getContext().getUri();
-
-        MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
-
-        String requestURI = uriInfo.getBaseUri().getPath();
-        UriBuilder uriBuilder = UriBuilder.fromUri(requestURI);
-
-        for (String k : queryParameterMap.keySet()) {
-
-            Object[] objects = queryParameterMap.get(k).toArray();
-            if (objects.length == 1 && objects[0] == null) continue; //
-            uriBuilder.replaceQueryParam(k, objects);
-        }
-        if (accessCode != null) {
-            uriBuilder.replaceQueryParam(OAuth2Constants.CODE, accessCode);
-        }
-        URI baseUri = uriBuilder.build();
-
-        ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
-        Theme theme;
-        try {
-            theme = themeProvider.getTheme(realm.getLoginTheme(), Theme.Type.LOGIN);
-        } catch (IOException e) {
-            logger.error("Failed to create theme", e);
-            return Response.serverError().build();
-        }
-
-        try {
-            attributes.put("properties", theme.getProperties());
-        } catch (IOException e) {
-            logger.warn("Failed to load properties", e);
-        }
-        if (client != null) {
-            attributes.put("client", new ClientBean(client));
-        }
-
-        Properties messagesBundle;
-        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
-        try {
-            messagesBundle = theme.getMessages(locale);
-            attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
-        } catch (IOException e) {
-            logger.warn("Failed to load messages", e);
-            messagesBundle = new Properties();
-        }
-
-        MessagesPerFieldBean messagesPerField = new MessagesPerFieldBean();
-        if (messages != null) {
-            MessageBean wholeMessage = new MessageBean(null, messageType);
-            for (FormMessage message : this.messages) {
-                String formattedMessageText = formatMessage(message, messagesBundle, locale);
-                if (formattedMessageText != null) {
-                    wholeMessage.appendSummaryLine(formattedMessageText);
-                    messagesPerField.addMessage(message.getField(), formattedMessageText, messageType);
-                }
-            }
-            attributes.put("message", wholeMessage);
-        }
-        attributes.put("messagesPerField", messagesPerField);
-
-        if (status == null) {
-            status = Response.Status.OK;
-        }
-
-        if (realm != null) {
-            attributes.put("realm", new RealmBean(realm));
-            attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
-            attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
-            attributes.put("requiredActionUrl", new RequiredActionUrlFormatterMethod(realm, baseUri));
-
-            if (realm.isInternationalizationEnabled()) {
-                UriBuilder b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
-                attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle));
-            }
-        }
-        if (realm != null && user != null && session != null) {
-            attributes.put("authenticatorConfigured", new AuthenticatorConfiguredMethod(realm, user, session));
-        }
-        try {
-            String result = freeMarker.processTemplate(attributes, form, theme);
-            Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result);
-            BrowserSecurityHeaderSetup.headers(builder, realm);
-            for (Map.Entry<String, String> entry : httpResponseHeaders.entrySet()) {
-                builder.header(entry.getKey(), entry.getValue());
-            }
-            LocaleHelper.updateLocaleCookie(builder, locale, realm, uriInfo, Urls.localeCookiePath(baseUri, realm.getName()));
-            return builder.build();
-        } catch (FreeMarkerException e) {
-            logger.error("Failed to process template", e);
-            return Response.serverError().build();
-        }
-    }
-
-
-    public Response createLogin() {
-        return createResponse(LoginFormsPages.LOGIN);
-    }
-
-    public Response createPasswordReset() {
-        return createResponse(LoginFormsPages.LOGIN_RESET_PASSWORD);
-    }
-
-    public Response createLoginTotp() {
-        return createResponse(LoginFormsPages.LOGIN_TOTP);
-    }
-
-    public Response createRegistration() {
-        return createResponse(LoginFormsPages.REGISTER);
-    }
-
-    public Response createInfoPage() {
-        return createResponse(LoginFormsPages.INFO);
-    }
-
-    public Response createErrorPage() {
-        if (status == null) {
-            status = Response.Status.INTERNAL_SERVER_ERROR;
-        }
-        return createResponse(LoginFormsPages.ERROR);
-    }
-
-
-    public Response createOAuthGrant(ClientSessionModel clientSession) {
-        this.clientSession = clientSession;
-        return createResponse(LoginFormsPages.OAUTH_GRANT);
-    }
-
-    @Override
-    public Response createCode() {
-        return createResponse(LoginFormsPages.CODE);
-    }
-
-    protected void setMessage(MessageType type, String message, Object... parameters) {
-        messageType = type;
-        messages = new ArrayList<>();
-        messages.add(new FormMessage(null, message, parameters));
-    }
-
-    protected String getFirstMessageUnformatted() {
-        if (messages != null && !messages.isEmpty()) {
-            return messages.get(0).getMessage();
-        }
-        return null;
-    }
-
-    protected String formatMessage(FormMessage message, Properties messagesBundle, Locale locale) {
-        if (message == null)
-            return null;
-        if (messagesBundle.containsKey(message.getMessage())) {
-            return new MessageFormat(messagesBundle.getProperty(message.getMessage()), locale).format(message.getParameters());
-        } else {
-            return message.getMessage();
-        }
-    }
-
-    @Override
-    public FreeMarkerLoginFormsProvider setError(String message, Object... parameters) {
-        setMessage(MessageType.ERROR, message, parameters);
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setErrors(List<FormMessage> messages) {
-        if (messages == null) return this;
-        this.messageType = MessageType.ERROR;
-        this.messages = new ArrayList<>(messages);
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider addError(FormMessage errorMessage) {
-        if (this.messageType != MessageType.ERROR) {
-            this.messageType = null;
-            this.messages = null;
-        }
-        if (messages == null) {
-            this.messageType = MessageType.ERROR;
-            this.messages = new LinkedList<>();
-        }
-        this.messages.add(errorMessage);
-        return this;
-
-    }
-
-    @Override
-    public FreeMarkerLoginFormsProvider setSuccess(String message, Object... parameters) {
-        setMessage(MessageType.SUCCESS, message, parameters);
-        return this;
-    }
-
-    public FreeMarkerLoginFormsProvider setUser(UserModel user) {
-        this.user = user;
-        return this;
-    }
-
-    public FreeMarkerLoginFormsProvider setFormData(MultivaluedMap<String, String> formData) {
-        this.formData = formData;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setClientSessionCode(String accessCode) {
-        this.accessCode = accessCode;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappersRequested) {
-        this.realmRolesRequested = realmRolesRequested;
-        this.resourceRolesRequested = resourceRolesRequested;
-        this.protocolMappersRequested = protocolMappersRequested;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setAccessRequest(String accessRequestMessage) {
-        this.accessRequestMessage = accessRequestMessage;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setAttribute(String name, Object value) {
-        this.attributes.put(name, value);
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setStatus(Response.Status status) {
-        this.status = status;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setActionUri(URI actionUri) {
-        this.actionUri = actionUri;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setResponseHeader(String headerName, String headerValue) {
-        this.httpResponseHeaders.put(headerName, headerValue);
-        return this;
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
+package org.keycloak.login.freemarker;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.email.EmailException;
+import org.keycloak.email.EmailProvider;
+import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
+import org.keycloak.freemarker.FreeMarkerException;
+import org.keycloak.freemarker.FreeMarkerUtil;
+import org.keycloak.freemarker.LocaleHelper;
+import org.keycloak.freemarker.Theme;
+import org.keycloak.freemarker.ThemeProvider;
+import org.keycloak.freemarker.beans.AdvancedMessageFormatterMethod;
+import org.keycloak.freemarker.beans.LocaleBean;
+import org.keycloak.freemarker.beans.MessageBean;
+import org.keycloak.freemarker.beans.MessageFormatterMethod;
+import org.keycloak.freemarker.beans.MessageType;
+import org.keycloak.freemarker.beans.MessagesPerFieldBean;
+import org.keycloak.login.LoginFormsPages;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.login.freemarker.model.ClientBean;
+import org.keycloak.login.freemarker.model.CodeBean;
+import org.keycloak.login.freemarker.model.IdentityProviderBean;
+import org.keycloak.login.freemarker.model.LoginBean;
+import org.keycloak.login.freemarker.model.OAuthGrantBean;
+import org.keycloak.login.freemarker.model.ProfileBean;
+import org.keycloak.login.freemarker.model.RealmBean;
+import org.keycloak.login.freemarker.model.RegisterBean;
+import org.keycloak.login.freemarker.model.RequiredActionUrlFormatterMethod;
+import org.keycloak.login.freemarker.model.TotpBean;
+import org.keycloak.login.freemarker.model.UrlBean;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.services.Urls;
+import org.keycloak.services.messages.Messages;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.net.URI;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
+
+    private static final Logger logger = Logger.getLogger(FreeMarkerLoginFormsProvider.class);
+
+    private String accessCode;
+    private Response.Status status;
+    private List<RoleModel> realmRolesRequested;
+    private MultivaluedMap<String, RoleModel> resourceRolesRequested;
+    private List<ProtocolMapperModel> protocolMappersRequested;
+    private MultivaluedMap<String, String> queryParams;
+    private Map<String, String> httpResponseHeaders = new HashMap<String, String>();
+    private String accessRequestMessage;
+    private URI actionUri;
+
+    private List<FormMessage> messages = null;
+    private MessageType messageType = MessageType.ERROR;
+
+    private MultivaluedMap<String, String> formData;
+
+    private KeycloakSession session;
+    private FreeMarkerUtil freeMarker;
+
+    private UserModel user;
+
+    private ClientSessionModel clientSession;
+    private final Map<String, Object> attributes = new HashMap<String, Object>();
+
+    public FreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
+        this.session = session;
+        this.freeMarker = freeMarker;
+    }
+
+    public Response createResponse(UserModel.RequiredAction action) {
+        RealmModel realm = session.getContext().getRealm();
+        UriInfo uriInfo = session.getContext().getUri();
+
+        String actionMessage;
+        LoginFormsPages page;
+
+        switch (action) {
+            case CONFIGURE_TOTP:
+                actionMessage = Messages.CONFIGURE_TOTP;
+                page = LoginFormsPages.LOGIN_CONFIG_TOTP;
+                break;
+            case UPDATE_PROFILE:
+                actionMessage = Messages.UPDATE_PROFILE;
+                page = LoginFormsPages.LOGIN_UPDATE_PROFILE;
+                break;
+            case UPDATE_PASSWORD:
+                actionMessage = Messages.UPDATE_PASSWORD;
+                page = LoginFormsPages.LOGIN_UPDATE_PASSWORD;
+                break;
+            case VERIFY_EMAIL:
+                try {
+                    UriBuilder builder = Urls.loginActionEmailVerificationBuilder(uriInfo.getBaseUri());
+                    builder.queryParam("key", accessCode);
+
+                    String link = builder.build(realm.getName()).toString();
+                    long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
+
+                    session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendVerifyEmail(link, expiration);
+                } catch (EmailException e) {
+                    logger.error("Failed to send verification email", e);
+                    return setError(Messages.EMAIL_SENT_ERROR).createErrorPage();
+                }
+
+                actionMessage = Messages.VERIFY_EMAIL;
+                page = LoginFormsPages.LOGIN_VERIFY_EMAIL;
+                break;
+            default:
+                return Response.serverError().build();
+        }
+
+        if (messages == null) {
+            setMessage(MessageType.WARNING, actionMessage);
+        }
+
+        return createResponse(page);
+    }
+
+    private Response createResponse(LoginFormsPages page) {
+        RealmModel realm = session.getContext().getRealm();
+        ClientModel client = session.getContext().getClient();
+        UriInfo uriInfo = session.getContext().getUri();
+
+        MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
+
+        String requestURI = uriInfo.getBaseUri().getPath();
+        UriBuilder uriBuilder = UriBuilder.fromUri(requestURI);
+
+        for (String k : queryParameterMap.keySet()) {
+
+            Object[] objects = queryParameterMap.get(k).toArray();
+            if (objects.length == 1 && objects[0] == null) continue; //
+            uriBuilder.replaceQueryParam(k, objects);
+        }
+
+        if (accessCode != null) {
+            uriBuilder.replaceQueryParam(OAuth2Constants.CODE, accessCode);
+        }
+
+        ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
+        Theme theme;
+        try {
+            theme = themeProvider.getTheme(realm.getLoginTheme(), Theme.Type.LOGIN);
+        } catch (IOException e) {
+            logger.error("Failed to create theme", e);
+            return Response.serverError().build();
+        }
+
+        try {
+            attributes.put("properties", theme.getProperties());
+        } catch (IOException e) {
+            logger.warn("Failed to load properties", e);
+        }
+
+        Properties messagesBundle;
+        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
+        try {
+            messagesBundle = theme.getMessages(locale);
+            attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
+        } catch (IOException e) {
+            logger.warn("Failed to load messages", e);
+            messagesBundle = new Properties();
+        }
+
+        MessagesPerFieldBean messagesPerField = new MessagesPerFieldBean();
+        if (messages != null) {
+            MessageBean wholeMessage = new MessageBean(null, messageType);
+            for (FormMessage message : this.messages) {
+                String formattedMessageText = formatMessage(message, messagesBundle, locale);
+                if (formattedMessageText != null) {
+                    wholeMessage.appendSummaryLine(formattedMessageText);
+                    messagesPerField.addMessage(message.getField(), formattedMessageText, messageType);
+                }
+            }
+            attributes.put("message", wholeMessage);
+        }
+        attributes.put("messagesPerField", messagesPerField);
+
+        if (page == LoginFormsPages.OAUTH_GRANT) {
+            // for some reason Resteasy 2.3.7 doesn't like query params and form params with the same name and will null out the code form param
+            uriBuilder.replaceQuery(null);
+        }
+        URI baseUri = uriBuilder.build();
+        attributes.put("requiredActionUrl", new RequiredActionUrlFormatterMethod(realm, baseUri));
+        if (realm != null && user != null && session != null) {
+            attributes.put("authenticatorConfigured", new AuthenticatorConfiguredMethod(realm, user, session));
+        }
+
+        if (realm != null) {
+            attributes.put("realm", new RealmBean(realm));
+            attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
+            attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
+
+            if (realm.isInternationalizationEnabled()) {
+                UriBuilder b;
+                switch (page) {
+                    case LOGIN:
+                        b = UriBuilder.fromUri(Urls.realmLoginPage(baseUri, realm.getName()));
+                        break;
+                    case REGISTER:
+                        b = UriBuilder.fromUri(Urls.realmRegisterPage(baseUri, realm.getName()));
+                        break;
+                    default:
+                        b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
+                        break;
+                }
+                attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle));
+            }
+        }
+
+        if (client != null) {
+            attributes.put("client", new ClientBean(client));
+        }
+
+        attributes.put("login", new LoginBean(formData));
+
+        switch (page) {
+            case LOGIN_CONFIG_TOTP:
+                attributes.put("totp", new TotpBean(realm, user, baseUri));
+                break;
+            case LOGIN_UPDATE_PROFILE:
+                attributes.put("user", new ProfileBean(user));
+                break;
+            case REGISTER:
+                attributes.put("register", new RegisterBean(formData));
+                break;
+            case OAUTH_GRANT:
+                attributes.put("oauth", new OAuthGrantBean(accessCode, clientSession, client, realmRolesRequested, resourceRolesRequested, protocolMappersRequested, this.accessRequestMessage));
+                attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle));
+                break;
+            case CODE:
+                attributes.put(OAuth2Constants.CODE, new CodeBean(accessCode, messageType == MessageType.ERROR ? getFirstMessageUnformatted() : null));
+                break;
+        }
+
+        if (status == null) {
+            status = Response.Status.OK;
+        }
+
+        try {
+            String result = freeMarker.processTemplate(attributes, Templates.getTemplate(page), theme);
+            Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result);
+            BrowserSecurityHeaderSetup.headers(builder, realm);
+            for (Map.Entry<String, String> entry : httpResponseHeaders.entrySet()) {
+                builder.header(entry.getKey(), entry.getValue());
+            }
+            LocaleHelper.updateLocaleCookie(builder, locale, realm, uriInfo, Urls.localeCookiePath(baseUri, realm.getName()));
+            return builder.build();
+        } catch (FreeMarkerException e) {
+            logger.error("Failed to process template", e);
+            return Response.serverError().build();
+        }
+    }
+
+    @Override
+    public Response createForm(String form, Map<String, Object> extraAttributes) {
+
+        RealmModel realm = session.getContext().getRealm();
+        ClientModel client = session.getContext().getClient();
+        UriInfo uriInfo = session.getContext().getUri();
+
+        MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
+
+        String requestURI = uriInfo.getBaseUri().getPath();
+        UriBuilder uriBuilder = UriBuilder.fromUri(requestURI);
+
+        for (String k : queryParameterMap.keySet()) {
+
+            Object[] objects = queryParameterMap.get(k).toArray();
+            if (objects.length == 1 && objects[0] == null) continue; //
+            uriBuilder.replaceQueryParam(k, objects);
+        }
+        if (accessCode != null) {
+            uriBuilder.replaceQueryParam(OAuth2Constants.CODE, accessCode);
+        }
+        URI baseUri = uriBuilder.build();
+
+        ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
+        Theme theme;
+        try {
+            theme = themeProvider.getTheme(realm.getLoginTheme(), Theme.Type.LOGIN);
+        } catch (IOException e) {
+            logger.error("Failed to create theme", e);
+            return Response.serverError().build();
+        }
+
+        try {
+            attributes.put("properties", theme.getProperties());
+        } catch (IOException e) {
+            logger.warn("Failed to load properties", e);
+        }
+        if (client != null) {
+            attributes.put("client", new ClientBean(client));
+        }
+
+        Properties messagesBundle;
+        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
+        try {
+            messagesBundle = theme.getMessages(locale);
+            attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
+        } catch (IOException e) {
+            logger.warn("Failed to load messages", e);
+            messagesBundle = new Properties();
+        }
+
+        MessagesPerFieldBean messagesPerField = new MessagesPerFieldBean();
+        if (messages != null) {
+            MessageBean wholeMessage = new MessageBean(null, messageType);
+            for (FormMessage message : this.messages) {
+                String formattedMessageText = formatMessage(message, messagesBundle, locale);
+                if (formattedMessageText != null) {
+                    wholeMessage.appendSummaryLine(formattedMessageText);
+                    messagesPerField.addMessage(message.getField(), formattedMessageText, messageType);
+                }
+            }
+            attributes.put("message", wholeMessage);
+        }
+        attributes.put("messagesPerField", messagesPerField);
+
+        if (status == null) {
+            status = Response.Status.OK;
+        }
+
+        if (realm != null) {
+            attributes.put("realm", new RealmBean(realm));
+            attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
+            attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
+            attributes.put("requiredActionUrl", new RequiredActionUrlFormatterMethod(realm, baseUri));
+
+            if (realm.isInternationalizationEnabled()) {
+                UriBuilder b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
+                attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle));
+            }
+        }
+        if (realm != null && user != null && session != null) {
+            attributes.put("authenticatorConfigured", new AuthenticatorConfiguredMethod(realm, user, session));
+        }
+        try {
+            String result = freeMarker.processTemplate(attributes, form, theme);
+            Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result);
+            BrowserSecurityHeaderSetup.headers(builder, realm);
+            for (Map.Entry<String, String> entry : httpResponseHeaders.entrySet()) {
+                builder.header(entry.getKey(), entry.getValue());
+            }
+            LocaleHelper.updateLocaleCookie(builder, locale, realm, uriInfo, Urls.localeCookiePath(baseUri, realm.getName()));
+            return builder.build();
+        } catch (FreeMarkerException e) {
+            logger.error("Failed to process template", e);
+            return Response.serverError().build();
+        }
+    }
+
+
+    public Response createLogin() {
+        return createResponse(LoginFormsPages.LOGIN);
+    }
+
+    public Response createPasswordReset() {
+        return createResponse(LoginFormsPages.LOGIN_RESET_PASSWORD);
+    }
+
+    public Response createLoginTotp() {
+        return createResponse(LoginFormsPages.LOGIN_TOTP);
+    }
+
+    public Response createRegistration() {
+        return createResponse(LoginFormsPages.REGISTER);
+    }
+
+    public Response createInfoPage() {
+        return createResponse(LoginFormsPages.INFO);
+    }
+
+    public Response createErrorPage() {
+        if (status == null) {
+            status = Response.Status.INTERNAL_SERVER_ERROR;
+        }
+        return createResponse(LoginFormsPages.ERROR);
+    }
+
+
+    public Response createOAuthGrant(ClientSessionModel clientSession) {
+        this.clientSession = clientSession;
+        return createResponse(LoginFormsPages.OAUTH_GRANT);
+    }
+
+    @Override
+    public Response createCode() {
+        return createResponse(LoginFormsPages.CODE);
+    }
+
+    protected void setMessage(MessageType type, String message, Object... parameters) {
+        messageType = type;
+        messages = new ArrayList<>();
+        messages.add(new FormMessage(null, message, parameters));
+    }
+
+    protected String getFirstMessageUnformatted() {
+        if (messages != null && !messages.isEmpty()) {
+            return messages.get(0).getMessage();
+        }
+        return null;
+    }
+
+    protected String formatMessage(FormMessage message, Properties messagesBundle, Locale locale) {
+        if (message == null)
+            return null;
+        if (messagesBundle.containsKey(message.getMessage())) {
+            return new MessageFormat(messagesBundle.getProperty(message.getMessage()), locale).format(message.getParameters());
+        } else {
+            return message.getMessage();
+        }
+    }
+
+    @Override
+    public FreeMarkerLoginFormsProvider setError(String message, Object... parameters) {
+        setMessage(MessageType.ERROR, message, parameters);
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setErrors(List<FormMessage> messages) {
+        if (messages == null) return this;
+        this.messageType = MessageType.ERROR;
+        this.messages = new ArrayList<>(messages);
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider addError(FormMessage errorMessage) {
+        if (this.messageType != MessageType.ERROR) {
+            this.messageType = null;
+            this.messages = null;
+        }
+        if (messages == null) {
+            this.messageType = MessageType.ERROR;
+            this.messages = new LinkedList<>();
+        }
+        this.messages.add(errorMessage);
+        return this;
+
+    }
+
+    @Override
+    public FreeMarkerLoginFormsProvider setSuccess(String message, Object... parameters) {
+        setMessage(MessageType.SUCCESS, message, parameters);
+        return this;
+    }
+
+    public FreeMarkerLoginFormsProvider setUser(UserModel user) {
+        this.user = user;
+        return this;
+    }
+
+    public FreeMarkerLoginFormsProvider setFormData(MultivaluedMap<String, String> formData) {
+        this.formData = formData;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setClientSessionCode(String accessCode) {
+        this.accessCode = accessCode;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappersRequested) {
+        this.realmRolesRequested = realmRolesRequested;
+        this.resourceRolesRequested = resourceRolesRequested;
+        this.protocolMappersRequested = protocolMappersRequested;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setAccessRequest(String accessRequestMessage) {
+        this.accessRequestMessage = accessRequestMessage;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setAttribute(String name, Object value) {
+        this.attributes.put(name, value);
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setStatus(Response.Status status) {
+        this.status = status;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setActionUri(URI actionUri) {
+        this.actionUri = actionUri;
+        return this;
+    }
+
+    @Override
+    public LoginFormsProvider setResponseHeader(String headerName, String headerValue) {
+        this.httpResponseHeaders.put(headerName, headerValue);
+        return this;
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
index d945c38..0404ea7 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
@@ -1,29 +1,29 @@
-package org.keycloak.login.freemarker.model;
-
-import org.keycloak.models.ClientModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientBean {
-
-    protected ClientModel client;
-
-    public ClientBean(ClientModel client) {
-        this.client = client;
-    }
-
-    public String getClientId() {
-        return client.getClientId();
-    }
-
-    public String getName() {
-        return client.getName();
-    }
-
-    public String getBaseUrl() {
-        return client.getBaseUrl();
-    }
-
-}
+package org.keycloak.login.freemarker.model;
+
+import org.keycloak.models.ClientModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientBean {
+
+    protected ClientModel client;
+
+    public ClientBean(ClientModel client) {
+        this.client = client;
+    }
+
+    public String getClientId() {
+        return client.getClientId();
+    }
+
+    public String getName() {
+        return client.getName();
+    }
+
+    public String getBaseUrl() {
+        return client.getBaseUrl();
+    }
+
+}
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
index 6032587..f304084 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
@@ -1,129 +1,129 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.login.freemarker.model;
-
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RoleModel;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
- */
-public class OAuthGrantBean {
-
-    private final String accessRequestMessage;
-    private List<RoleModel> realmRolesRequested;
-    private MultivaluedMap<String, ClientRoleEntry> resourceRolesRequested;
-    private String code;
-    private ClientModel client;
-    private List<String> claimsRequested;
-
-    public OAuthGrantBean(String code, ClientSessionModel clientSession, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested,
-                          List<ProtocolMapperModel> protocolMappersRequested, String accessRequestMessage) {
-        this.code = code;
-        this.client = client;
-        this.realmRolesRequested = realmRolesRequested;
-        if (resourceRolesRequested != null) {
-            this.resourceRolesRequested = new MultivaluedMapImpl<String, ClientRoleEntry>();
-            for (List<RoleModel> clientRoles : resourceRolesRequested.values()) {
-                for (RoleModel role : clientRoles) {
-                    ClientModel currentClient = (ClientModel) role.getContainer();
-                    ClientRoleEntry roleEntry = new ClientRoleEntry(currentClient.getClientId(), currentClient.getName(), role.getName(), role.getDescription());
-                    this.resourceRolesRequested.add(currentClient.getClientId(), roleEntry);
-                }
-            }
-        }
-
-        this.accessRequestMessage = accessRequestMessage;
-
-        List<String> claims = new LinkedList<String>();
-        if (protocolMappersRequested != null) {
-            for (ProtocolMapperModel model : protocolMappersRequested) {
-                claims.add(model.getConsentText());
-            }
-        }
-        if (claims.size() > 0) this.claimsRequested = claims;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public MultivaluedMap<String, ClientRoleEntry> getResourceRolesRequested() {
-        return resourceRolesRequested;
-    }
-
-    public List<RoleModel> getRealmRolesRequested() {
-        return realmRolesRequested;
-    }
-
-    public String getClient() {
-        return client.getClientId();
-    }
-
-    public List<String> getClaimsRequested() {
-        return claimsRequested;
-    }
-
-    public String getAccessRequestMessage() {
-        return this.accessRequestMessage;
-    }
-
-    // Same class used in ConsentBean in account as well. Maybe should be merged into common-freemarker...
-    public static class ClientRoleEntry {
-
-        private final String clientId;
-        private final String clientName;
-        private final String roleName;
-        private final String roleDescription;
-
-        public ClientRoleEntry(String clientId, String clientName, String roleName, String roleDescription) {
-            this.clientId = clientId;
-            this.clientName = clientName;
-            this.roleName = roleName;
-            this.roleDescription = roleDescription;
-        }
-
-        public String getClientId() {
-            return clientId;
-        }
-
-        public String getClientName() {
-            return clientName;
-        }
-
-        public String getRoleName() {
-            return roleName;
-        }
-
-        public String getRoleDescription() {
-            return roleDescription;
-        }
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.login.freemarker.model;
+
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RoleModel;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
+ */
+public class OAuthGrantBean {
+
+    private final String accessRequestMessage;
+    private List<RoleModel> realmRolesRequested;
+    private MultivaluedMap<String, ClientRoleEntry> resourceRolesRequested;
+    private String code;
+    private ClientModel client;
+    private List<String> claimsRequested;
+
+    public OAuthGrantBean(String code, ClientSessionModel clientSession, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested,
+                          List<ProtocolMapperModel> protocolMappersRequested, String accessRequestMessage) {
+        this.code = code;
+        this.client = client;
+        this.realmRolesRequested = realmRolesRequested;
+        if (resourceRolesRequested != null) {
+            this.resourceRolesRequested = new MultivaluedMapImpl<String, ClientRoleEntry>();
+            for (List<RoleModel> clientRoles : resourceRolesRequested.values()) {
+                for (RoleModel role : clientRoles) {
+                    ClientModel currentClient = (ClientModel) role.getContainer();
+                    ClientRoleEntry roleEntry = new ClientRoleEntry(currentClient.getClientId(), currentClient.getName(), role.getName(), role.getDescription());
+                    this.resourceRolesRequested.add(currentClient.getClientId(), roleEntry);
+                }
+            }
+        }
+
+        this.accessRequestMessage = accessRequestMessage;
+
+        List<String> claims = new LinkedList<String>();
+        if (protocolMappersRequested != null) {
+            for (ProtocolMapperModel model : protocolMappersRequested) {
+                claims.add(model.getConsentText());
+            }
+        }
+        if (claims.size() > 0) this.claimsRequested = claims;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public MultivaluedMap<String, ClientRoleEntry> getResourceRolesRequested() {
+        return resourceRolesRequested;
+    }
+
+    public List<RoleModel> getRealmRolesRequested() {
+        return realmRolesRequested;
+    }
+
+    public String getClient() {
+        return client.getClientId();
+    }
+
+    public List<String> getClaimsRequested() {
+        return claimsRequested;
+    }
+
+    public String getAccessRequestMessage() {
+        return this.accessRequestMessage;
+    }
+
+    // Same class used in ConsentBean in account as well. Maybe should be merged into common-freemarker...
+    public static class ClientRoleEntry {
+
+        private final String clientId;
+        private final String clientName;
+        private final String roleName;
+        private final String roleDescription;
+
+        public ClientRoleEntry(String clientId, String clientName, String roleName, String roleDescription) {
+            this.clientId = clientId;
+            this.clientName = clientName;
+            this.roleName = roleName;
+            this.roleDescription = roleDescription;
+        }
+
+        public String getClientId() {
+            return clientId;
+        }
+
+        public String getClientName() {
+            return clientName;
+        }
+
+        public String getRoleName() {
+            return roleName;
+        }
+
+        public String getRoleDescription() {
+            return roleDescription;
+        }
+    }
+}
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
index 011e7f3..4fdc9fa 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
@@ -1,105 +1,105 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.login.freemarker.model;
-
-import org.keycloak.freemarker.Theme;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.Urls;
-
-import java.net.URI;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class UrlBean {
-
-    private final URI actionuri;
-    private URI baseURI;
-    private Theme theme;
-    private String realm;
-
-    public UrlBean(RealmModel realm, Theme theme, URI baseURI, URI actionUri) {
-        this.realm = realm.getName();
-        this.theme = theme;
-        this.baseURI = baseURI;
-        this.actionuri = actionUri;
-    }
-
-    public String getLoginAction() {
-        if (this.actionuri != null) {
-            return this.actionuri.toString();
-        }
-        throw new RuntimeException("action URI not set");
-    }
-
-    public String getLoginUrl() {
-        return Urls.realmLoginPage(baseURI, realm).toString();
-    }
-
-    public String getRegistrationAction() {
-        if (this.actionuri != null) {
-            return this.actionuri.toString();
-        }
-        return Urls.realmRegisterAction(baseURI, realm).toString();
-    }
-
-    public String getRegistrationUrl() {
-        return Urls.realmRegisterPage(baseURI, realm).toString();
-    }
-
-    public String getLoginUpdatePasswordUrl() {
-        return Urls.loginActionUpdatePassword(baseURI, realm).toString();
-    }
-
-    public String getLoginUpdateTotpUrl() {
-        return Urls.loginActionUpdateTotp(baseURI, realm).toString();
-    }
-
-    public String getLoginUpdateProfileUrl() {
-        return Urls.loginActionUpdateProfile(baseURI, realm).toString();
-    }
-
-    public String getLoginPasswordResetUrl() {
-        return Urls.loginPasswordReset(baseURI, realm).toString();
-    }
-
-    public String getLoginUsernameReminderUrl() {
-        return Urls.loginUsernameReminder(baseURI, realm).toString();
-    }
-
-    public String getLoginEmailVerificationUrl() {
-        return Urls.loginActionEmailVerification(baseURI, realm).toString();
-    }
-
-    public String getOauthAction() {
-        if (this.actionuri != null) {
-            return this.actionuri.getPath();
-        }
-
-        return Urls.realmOauthAction(baseURI, realm).toString();
-    }
-
-    public String getResourcesPath() {
-        URI uri = Urls.themeRoot(baseURI);
-        return uri.getPath() + "/" + theme.getType().toString().toLowerCase() +"/" + theme.getName();
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.login.freemarker.model;
+
+import org.keycloak.freemarker.Theme;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.Urls;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class UrlBean {
+
+    private final URI actionuri;
+    private URI baseURI;
+    private Theme theme;
+    private String realm;
+
+    public UrlBean(RealmModel realm, Theme theme, URI baseURI, URI actionUri) {
+        this.realm = realm.getName();
+        this.theme = theme;
+        this.baseURI = baseURI;
+        this.actionuri = actionUri;
+    }
+
+    public String getLoginAction() {
+        if (this.actionuri != null) {
+            return this.actionuri.toString();
+        }
+        throw new RuntimeException("action URI not set");
+    }
+
+    public String getLoginUrl() {
+        return Urls.realmLoginPage(baseURI, realm).toString();
+    }
+
+    public String getRegistrationAction() {
+        if (this.actionuri != null) {
+            return this.actionuri.toString();
+        }
+        return Urls.realmRegisterAction(baseURI, realm).toString();
+    }
+
+    public String getRegistrationUrl() {
+        return Urls.realmRegisterPage(baseURI, realm).toString();
+    }
+
+    public String getLoginUpdatePasswordUrl() {
+        return Urls.loginActionUpdatePassword(baseURI, realm).toString();
+    }
+
+    public String getLoginUpdateTotpUrl() {
+        return Urls.loginActionUpdateTotp(baseURI, realm).toString();
+    }
+
+    public String getLoginUpdateProfileUrl() {
+        return Urls.loginActionUpdateProfile(baseURI, realm).toString();
+    }
+
+    public String getLoginPasswordResetUrl() {
+        return Urls.loginPasswordReset(baseURI, realm).toString();
+    }
+
+    public String getLoginUsernameReminderUrl() {
+        return Urls.loginUsernameReminder(baseURI, realm).toString();
+    }
+
+    public String getLoginEmailVerificationUrl() {
+        return Urls.loginActionEmailVerification(baseURI, realm).toString();
+    }
+
+    public String getOauthAction() {
+        if (this.actionuri != null) {
+            return this.actionuri.getPath();
+        }
+
+        return Urls.realmOauthAction(baseURI, realm).toString();
+    }
+
+    public String getResourcesPath() {
+        URI uri = Urls.themeRoot(baseURI);
+        return uri.getPath() + "/" + theme.getType().toString().toLowerCase() +"/" + theme.getName();
+    }
+}

forms/pom.xml 56(+28 -28)

diff --git a/forms/pom.xml b/forms/pom.xml
index 5fa20aa..2034a4e 100755
--- a/forms/pom.xml
+++ b/forms/pom.xml
@@ -1,28 +1,28 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-    <packaging>pom</packaging>
-
-	<artifactId>keycloak-forms-parent</artifactId>
-	<name>Keycloak Forms</name>
-	<description />
-
-    <modules>
-        <module>common-freemarker</module>
-        <module>common-themes</module>
-        <module>account-api</module>
-        <module>account-freemarker</module>
-        <module>email-api</module>
-        <module>email-freemarker</module>
-        <module>login-api</module>
-        <module>login-freemarker</module>
-    </modules>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
+
+	<artifactId>keycloak-forms-parent</artifactId>
+	<name>Keycloak Forms</name>
+	<description />
+
+    <modules>
+        <module>common-freemarker</module>
+        <module>common-themes</module>
+        <module>account-api</module>
+        <module>account-freemarker</module>
+        <module>email-api</module>
+        <module>email-freemarker</module>
+        <module>login-api</module>
+        <module>login-freemarker</module>
+    </modules>
+
+</project>
diff --git a/integration/adapter-core/pom.xml b/integration/adapter-core/pom.xml
index d9a39ff..b7e5889 100755
--- a/integration/adapter-core/pom.xml
+++ b/integration/adapter-core/pom.xml
@@ -1,123 +1,123 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-adapter-core</artifactId>
-    <name>Keycloak Adapter Core</name>
-    <description/>
-
-    <properties>
-        <keycloak.osgi.export>
-            org.keycloak.adapters.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            org.keycloak.*;version="${project.version}",
-            org.apache.http.*;version=${apache.httpcomponents.version},
-            org.apache.karaf.jaas.boot.principal;resolution:=optional,
-            org.apache.karaf.jaas.modules;resolution:=optional,
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <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-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-adapter-core</artifactId>
+    <name>Keycloak Adapter Core</name>
+    <description/>
+
+    <properties>
+        <keycloak.osgi.export>
+            org.keycloak.adapters.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            org.keycloak.*;version="${project.version}",
+            org.apache.http.*;version=${apache.httpcomponents.version},
+            org.apache.karaf.jaas.boot.principal;resolution:=optional,
+            org.apache.karaf.jaas.modules;resolution:=optional,
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <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-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
index 50a13f9..b9b495b 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
@@ -1,463 +1,463 @@
-package org.keycloak.adapters;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.jboss.logging.Logger;
-import org.keycloak.enums.RelativeUrlsUsed;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.enums.TokenStore;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.representations.idm.PublishedRealmRepresentation;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.security.PublicKey;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AdapterDeploymentContext {
-    private static final Logger log = Logger.getLogger(AdapterDeploymentContext.class);
-    protected KeycloakDeployment deployment;
-    protected KeycloakConfigResolver configResolver;
-
-    public AdapterDeploymentContext() {
-    }
-
-    /**
-     * For single-tenant deployments, this constructor is to be used, as a
-     * full KeycloakDeployment is known at deployment time and won't change
-     * during the application deployment's life cycle.
-     *
-     * @param deployment A KeycloakConfigResolver, possibly missing the Auth
-     *                   Server URL and/or Realm Public Key
-     */
-    public AdapterDeploymentContext(KeycloakDeployment deployment) {
-        this.deployment = deployment;
-    }
-
-    /**
-     * For multi-tenant deployments, this constructor is to be used, as a
-     * KeycloakDeployment is not known at deployment time. It defers the
-     * resolution of a KeycloakDeployment to a KeycloakConfigResolver,
-     * to be implemented by the target application.
-     *
-     * @param configResolver A KeycloakConfigResolver that will be used
-     *                       to resolve a KeycloakDeployment
-     */
-    public AdapterDeploymentContext(KeycloakConfigResolver configResolver) {
-        this.configResolver = configResolver;
-    }
-
-    /**
-     * For single-tenant deployments, it complements KeycloakDeployment
-     * by resolving a relative Auth Server's URL based on the current request
-     * and, if needed, will lazily resolve the Realm's Public Key.
-     *
-     * For multi-tenant deployments, defers the resolution of KeycloakDeployment
-     * to the KeycloakConfigResolver .
-     *
-     * @param facade the Request/Response Façade , used to either determine
-     *               the Auth Server URL (single tenant) or pass thru to the
-     *               KeycloakConfigResolver.
-     * @return
-     */
-    public KeycloakDeployment resolveDeployment(HttpFacade facade) {
-        if (null != configResolver) {
-            return configResolver.resolve(facade.getRequest());
-        }
-
-        if (deployment == null) return null;
-        if (deployment.getAuthServerBaseUrl() == null) return deployment;
-
-        KeycloakDeployment resolvedDeployment = resolveUrls(deployment, facade);
-        if (resolvedDeployment.getRealmKey() == null) {
-            resolveRealmKey(resolvedDeployment);
-        }
-        return resolvedDeployment;
-    }
-
-    protected KeycloakDeployment resolveUrls(KeycloakDeployment deployment, HttpFacade facade) {
-        if (deployment.relativeUrls == RelativeUrlsUsed.NEVER) {
-            // Absolute URI are already set to everything
-            return deployment;
-        } else {
-            DeploymentDelegate delegate = new DeploymentDelegate(this.deployment);
-            delegate.setAuthServerBaseUrl(getBaseBuilder(facade, this.deployment.getAuthServerBaseUrl()).build().toString());
-            return delegate;
-        }
-    }
-
-    public void resolveRealmKey(KeycloakDeployment deployment) {
-        if (deployment.getClient() == null) {
-            throw new RuntimeException("KeycloakDeployment was never initialized through appropriate SPIs");
-        }
-        HttpGet get = new HttpGet(deployment.getRealmInfoUrl());
-        try {
-            HttpResponse response = deployment.getClient().execute(get);
-            int status = response.getStatusLine().getStatusCode();
-            if (status != 200) {
-                close(response);
-                throw new RuntimeException("Unable to resolve realm public key remotely, status = " + status);
-            }
-            HttpEntity entity = response.getEntity();
-            if (entity == null) {
-                throw new RuntimeException("Unable to resolve realm public key remotely.  There was no entity.");
-            }
-            InputStream is = entity.getContent();
-            try {
-                ByteArrayOutputStream os = new ByteArrayOutputStream();
-                int c;
-                while ((c = is.read()) != -1) {
-                    os.write(c);
-                }
-                byte[] bytes = os.toByteArray();
-                String json = new String(bytes);
-                PublishedRealmRepresentation rep = JsonSerialization.readValue(json, PublishedRealmRepresentation.class);
-                deployment.setRealmKey(rep.getPublicKey());
-            } finally {
-                try {
-                    is.close();
-                } catch (IOException ignored) {
-
-                }
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to resolve realm public key remotely", e);
-        }
-    }
-
-    /**
-     * This delegate is used to store temporary, per-request metadata like request resolved URLs.
-     * Ever method is delegated except URL get methods and isConfigured()
-     *
-     */
-    protected static class DeploymentDelegate extends KeycloakDeployment {
-        protected KeycloakDeployment delegate;
-
-        public DeploymentDelegate(KeycloakDeployment delegate) {
-            this.delegate = delegate;
-        }
-
-        public void setAuthServerBaseUrl(String authServerBaseUrl) {
-            this.authServerBaseUrl = authServerBaseUrl;
-            KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
-            resolveBrowserUrls(serverBuilder);
-
-            if (delegate.getRelativeUrls() == RelativeUrlsUsed.ALL_REQUESTS) {
-                resolveNonBrowserUrls(serverBuilder);
-            }
-        }
-
-        @Override
-        public RelativeUrlsUsed getRelativeUrls() {
-            return delegate.getRelativeUrls();
-        }
-
-        @Override
-        public String getRealmInfoUrl() {
-            return (this.realmInfoUrl != null) ? this.realmInfoUrl : delegate.getRealmInfoUrl();
-        }
-
-        @Override
-        public String getTokenUrl() {
-            return (this.tokenUrl != null) ? this.tokenUrl : delegate.getTokenUrl();
-        }
-
-        @Override
-        public KeycloakUriBuilder getLogoutUrl() {
-            return (this.logoutUrl != null) ? this.logoutUrl : delegate.getLogoutUrl();
-        }
-
-        @Override
-        public String getAccountUrl() {
-            return (this.accountUrl != null) ? this.accountUrl : delegate.getAccountUrl();
-        }
-
-        @Override
-        public String getRegisterNodeUrl() {
-            return (this.registerNodeUrl != null) ? this.registerNodeUrl : delegate.getRegisterNodeUrl();
-        }
-
-        @Override
-        public String getUnregisterNodeUrl() {
-            return (this.unregisterNodeUrl != null) ? this.unregisterNodeUrl : delegate.getUnregisterNodeUrl();
-        }
-
-        @Override
-        public String getResourceName() {
-            return delegate.getResourceName();
-        }
-
-        @Override
-        public String getRealm() {
-            return delegate.getRealm();
-        }
-
-        @Override
-        public void setRealm(String realm) {
-            delegate.setRealm(realm);
-        }
-
-        @Override
-        public PublicKey getRealmKey() {
-            return delegate.getRealmKey();
-        }
-
-        @Override
-        public void setRealmKey(PublicKey realmKey) {
-            delegate.setRealmKey(realmKey);
-        }
-
-        @Override
-        public void setResourceName(String resourceName) {
-            delegate.setResourceName(resourceName);
-        }
-
-        @Override
-        public boolean isBearerOnly() {
-            return delegate.isBearerOnly();
-        }
-
-        @Override
-        public void setBearerOnly(boolean bearerOnly) {
-            delegate.setBearerOnly(bearerOnly);
-        }
-
-        @Override
-        public boolean isEnableBasicAuth() {
-            return delegate.isEnableBasicAuth();
-        }
-
-        @Override
-        public void setEnableBasicAuth(boolean enableBasicAuth) {
-            delegate.setEnableBasicAuth(enableBasicAuth);
-        }
-
-        @Override
-        public boolean isPublicClient() {
-            return delegate.isPublicClient();
-        }
-
-        @Override
-        public void setPublicClient(boolean publicClient) {
-            delegate.setPublicClient(publicClient);
-        }
-
-        @Override
-        public Map<String, String> getResourceCredentials() {
-            return delegate.getResourceCredentials();
-        }
-
-        @Override
-        public void setResourceCredentials(Map<String, String> resourceCredentials) {
-            delegate.setResourceCredentials(resourceCredentials);
-        }
-
-        @Override
-        public HttpClient getClient() {
-            return delegate.getClient();
-        }
-
-        @Override
-        public void setClient(HttpClient client) {
-            delegate.setClient(client);
-        }
-
-        @Override
-        public String getScope() {
-            return delegate.getScope();
-        }
-
-        @Override
-        public void setScope(String scope) {
-            delegate.setScope(scope);
-        }
-
-        @Override
-        public SslRequired getSslRequired() {
-            return delegate.getSslRequired();
-        }
-
-        @Override
-        public void setSslRequired(SslRequired sslRequired) {
-            delegate.setSslRequired(sslRequired);
-        }
-
-        @Override
-        public TokenStore getTokenStore() {
-            return delegate.getTokenStore();
-        }
-
-        @Override
-        public void setTokenStore(TokenStore tokenStore) {
-            delegate.setTokenStore(tokenStore);
-        }
-
-        @Override
-        public String getStateCookieName() {
-            return delegate.getStateCookieName();
-        }
-
-        @Override
-        public void setStateCookieName(String stateCookieName) {
-            delegate.setStateCookieName(stateCookieName);
-        }
-
-        @Override
-        public boolean isUseResourceRoleMappings() {
-            return delegate.isUseResourceRoleMappings();
-        }
-
-        @Override
-        public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
-            delegate.setUseResourceRoleMappings(useResourceRoleMappings);
-        }
-
-        @Override
-        public boolean isCors() {
-            return delegate.isCors();
-        }
-
-        @Override
-        public void setCors(boolean cors) {
-            delegate.setCors(cors);
-        }
-
-        @Override
-        public int getCorsMaxAge() {
-            return delegate.getCorsMaxAge();
-        }
-
-        @Override
-        public void setCorsMaxAge(int corsMaxAge) {
-            delegate.setCorsMaxAge(corsMaxAge);
-        }
-
-        @Override
-        public String getCorsAllowedHeaders() {
-            return delegate.getCorsAllowedHeaders();
-        }
-
-        @Override
-        public void setNotBefore(int notBefore) {
-            delegate.setNotBefore(notBefore);
-        }
-
-        @Override
-        public int getNotBefore() {
-            return delegate.getNotBefore();
-        }
-
-        @Override
-        public void setExposeToken(boolean exposeToken) {
-            delegate.setExposeToken(exposeToken);
-        }
-
-        @Override
-        public boolean isExposeToken() {
-            return delegate.isExposeToken();
-        }
-
-        @Override
-        public void setCorsAllowedMethods(String corsAllowedMethods) {
-            delegate.setCorsAllowedMethods(corsAllowedMethods);
-        }
-
-        @Override
-        public String getCorsAllowedMethods() {
-            return delegate.getCorsAllowedMethods();
-        }
-
-        @Override
-        public void setCorsAllowedHeaders(String corsAllowedHeaders) {
-            delegate.setCorsAllowedHeaders(corsAllowedHeaders);
-        }
-
-        @Override
-        public boolean isAlwaysRefreshToken() {
-            return delegate.isAlwaysRefreshToken();
-        }
-
-        @Override
-        public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
-            delegate.setAlwaysRefreshToken(alwaysRefreshToken);
-        }
-
-        @Override
-        public int getRegisterNodePeriod() {
-            return delegate.getRegisterNodePeriod();
-        }
-
-        @Override
-        public void setRegisterNodePeriod(int registerNodePeriod) {
-            delegate.setRegisterNodePeriod(registerNodePeriod);
-        }
-
-        @Override
-        public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
-            delegate.setRegisterNodeAtStartup(registerNodeAtStartup);
-        }
-
-        @Override
-        public boolean isRegisterNodeAtStartup() {
-            return delegate.isRegisterNodeAtStartup();
-        }
-
-        @Override
-        public String getPrincipalAttribute() {
-            return delegate.getPrincipalAttribute();
-        }
-
-        @Override
-        public void setPrincipalAttribute(String principalAttribute) {
-            delegate.setPrincipalAttribute(principalAttribute);
-        }
-    }
-
-    protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(base);
-        URI request = URI.create(facade.getRequest().getURI());
-        String scheme = request.getScheme();
-        if (deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            scheme = "https";
-            if (!request.getScheme().equals(scheme) && request.getPort() != -1) {
-                log.error("request scheme: " + request.getScheme() + " ssl required");
-                throw new RuntimeException("Can't resolve relative url from adapter config.");
-            }
-        }
-        builder.scheme(scheme);
-        builder.host(request.getHost());
-        if (request.getPort() != -1) {
-           builder.port(request.getPort());
-        }
-        return builder;
-    }
-
-
-
-    protected void close(HttpResponse response) {
-        if (response.getEntity() != null) {
-            try {
-                response.getEntity().getContent().close();
-            } catch (IOException e) {
-
-            }
-        }
-    }
-
-    public void updateDeployment(AdapterConfig config) {
-        if (null != configResolver) {
-            throw new IllegalStateException("Cannot parse an adapter config and build an updated deployment when on a multi-tenant scenario.");
-        }
-        deployment = KeycloakDeploymentBuilder.build(config);
-    }
-}
+package org.keycloak.adapters;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.jboss.logging.Logger;
+import org.keycloak.enums.RelativeUrlsUsed;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.enums.TokenStore;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.representations.idm.PublishedRealmRepresentation;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.PublicKey;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AdapterDeploymentContext {
+    private static final Logger log = Logger.getLogger(AdapterDeploymentContext.class);
+    protected KeycloakDeployment deployment;
+    protected KeycloakConfigResolver configResolver;
+
+    public AdapterDeploymentContext() {
+    }
+
+    /**
+     * For single-tenant deployments, this constructor is to be used, as a
+     * full KeycloakDeployment is known at deployment time and won't change
+     * during the application deployment's life cycle.
+     *
+     * @param deployment A KeycloakConfigResolver, possibly missing the Auth
+     *                   Server URL and/or Realm Public Key
+     */
+    public AdapterDeploymentContext(KeycloakDeployment deployment) {
+        this.deployment = deployment;
+    }
+
+    /**
+     * For multi-tenant deployments, this constructor is to be used, as a
+     * KeycloakDeployment is not known at deployment time. It defers the
+     * resolution of a KeycloakDeployment to a KeycloakConfigResolver,
+     * to be implemented by the target application.
+     *
+     * @param configResolver A KeycloakConfigResolver that will be used
+     *                       to resolve a KeycloakDeployment
+     */
+    public AdapterDeploymentContext(KeycloakConfigResolver configResolver) {
+        this.configResolver = configResolver;
+    }
+
+    /**
+     * For single-tenant deployments, it complements KeycloakDeployment
+     * by resolving a relative Auth Server's URL based on the current request
+     * and, if needed, will lazily resolve the Realm's Public Key.
+     *
+     * For multi-tenant deployments, defers the resolution of KeycloakDeployment
+     * to the KeycloakConfigResolver .
+     *
+     * @param facade the Request/Response Façade , used to either determine
+     *               the Auth Server URL (single tenant) or pass thru to the
+     *               KeycloakConfigResolver.
+     * @return
+     */
+    public KeycloakDeployment resolveDeployment(HttpFacade facade) {
+        if (null != configResolver) {
+            return configResolver.resolve(facade.getRequest());
+        }
+
+        if (deployment == null) return null;
+        if (deployment.getAuthServerBaseUrl() == null) return deployment;
+
+        KeycloakDeployment resolvedDeployment = resolveUrls(deployment, facade);
+        if (resolvedDeployment.getRealmKey() == null) {
+            resolveRealmKey(resolvedDeployment);
+        }
+        return resolvedDeployment;
+    }
+
+    protected KeycloakDeployment resolveUrls(KeycloakDeployment deployment, HttpFacade facade) {
+        if (deployment.relativeUrls == RelativeUrlsUsed.NEVER) {
+            // Absolute URI are already set to everything
+            return deployment;
+        } else {
+            DeploymentDelegate delegate = new DeploymentDelegate(this.deployment);
+            delegate.setAuthServerBaseUrl(getBaseBuilder(facade, this.deployment.getAuthServerBaseUrl()).build().toString());
+            return delegate;
+        }
+    }
+
+    public void resolveRealmKey(KeycloakDeployment deployment) {
+        if (deployment.getClient() == null) {
+            throw new RuntimeException("KeycloakDeployment was never initialized through appropriate SPIs");
+        }
+        HttpGet get = new HttpGet(deployment.getRealmInfoUrl());
+        try {
+            HttpResponse response = deployment.getClient().execute(get);
+            int status = response.getStatusLine().getStatusCode();
+            if (status != 200) {
+                close(response);
+                throw new RuntimeException("Unable to resolve realm public key remotely, status = " + status);
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity == null) {
+                throw new RuntimeException("Unable to resolve realm public key remotely.  There was no entity.");
+            }
+            InputStream is = entity.getContent();
+            try {
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                int c;
+                while ((c = is.read()) != -1) {
+                    os.write(c);
+                }
+                byte[] bytes = os.toByteArray();
+                String json = new String(bytes);
+                PublishedRealmRepresentation rep = JsonSerialization.readValue(json, PublishedRealmRepresentation.class);
+                deployment.setRealmKey(rep.getPublicKey());
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ignored) {
+
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to resolve realm public key remotely", e);
+        }
+    }
+
+    /**
+     * This delegate is used to store temporary, per-request metadata like request resolved URLs.
+     * Ever method is delegated except URL get methods and isConfigured()
+     *
+     */
+    protected static class DeploymentDelegate extends KeycloakDeployment {
+        protected KeycloakDeployment delegate;
+
+        public DeploymentDelegate(KeycloakDeployment delegate) {
+            this.delegate = delegate;
+        }
+
+        public void setAuthServerBaseUrl(String authServerBaseUrl) {
+            this.authServerBaseUrl = authServerBaseUrl;
+            KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
+            resolveBrowserUrls(serverBuilder);
+
+            if (delegate.getRelativeUrls() == RelativeUrlsUsed.ALL_REQUESTS) {
+                resolveNonBrowserUrls(serverBuilder);
+            }
+        }
+
+        @Override
+        public RelativeUrlsUsed getRelativeUrls() {
+            return delegate.getRelativeUrls();
+        }
+
+        @Override
+        public String getRealmInfoUrl() {
+            return (this.realmInfoUrl != null) ? this.realmInfoUrl : delegate.getRealmInfoUrl();
+        }
+
+        @Override
+        public String getTokenUrl() {
+            return (this.tokenUrl != null) ? this.tokenUrl : delegate.getTokenUrl();
+        }
+
+        @Override
+        public KeycloakUriBuilder getLogoutUrl() {
+            return (this.logoutUrl != null) ? this.logoutUrl : delegate.getLogoutUrl();
+        }
+
+        @Override
+        public String getAccountUrl() {
+            return (this.accountUrl != null) ? this.accountUrl : delegate.getAccountUrl();
+        }
+
+        @Override
+        public String getRegisterNodeUrl() {
+            return (this.registerNodeUrl != null) ? this.registerNodeUrl : delegate.getRegisterNodeUrl();
+        }
+
+        @Override
+        public String getUnregisterNodeUrl() {
+            return (this.unregisterNodeUrl != null) ? this.unregisterNodeUrl : delegate.getUnregisterNodeUrl();
+        }
+
+        @Override
+        public String getResourceName() {
+            return delegate.getResourceName();
+        }
+
+        @Override
+        public String getRealm() {
+            return delegate.getRealm();
+        }
+
+        @Override
+        public void setRealm(String realm) {
+            delegate.setRealm(realm);
+        }
+
+        @Override
+        public PublicKey getRealmKey() {
+            return delegate.getRealmKey();
+        }
+
+        @Override
+        public void setRealmKey(PublicKey realmKey) {
+            delegate.setRealmKey(realmKey);
+        }
+
+        @Override
+        public void setResourceName(String resourceName) {
+            delegate.setResourceName(resourceName);
+        }
+
+        @Override
+        public boolean isBearerOnly() {
+            return delegate.isBearerOnly();
+        }
+
+        @Override
+        public void setBearerOnly(boolean bearerOnly) {
+            delegate.setBearerOnly(bearerOnly);
+        }
+
+        @Override
+        public boolean isEnableBasicAuth() {
+            return delegate.isEnableBasicAuth();
+        }
+
+        @Override
+        public void setEnableBasicAuth(boolean enableBasicAuth) {
+            delegate.setEnableBasicAuth(enableBasicAuth);
+        }
+
+        @Override
+        public boolean isPublicClient() {
+            return delegate.isPublicClient();
+        }
+
+        @Override
+        public void setPublicClient(boolean publicClient) {
+            delegate.setPublicClient(publicClient);
+        }
+
+        @Override
+        public Map<String, String> getResourceCredentials() {
+            return delegate.getResourceCredentials();
+        }
+
+        @Override
+        public void setResourceCredentials(Map<String, String> resourceCredentials) {
+            delegate.setResourceCredentials(resourceCredentials);
+        }
+
+        @Override
+        public HttpClient getClient() {
+            return delegate.getClient();
+        }
+
+        @Override
+        public void setClient(HttpClient client) {
+            delegate.setClient(client);
+        }
+
+        @Override
+        public String getScope() {
+            return delegate.getScope();
+        }
+
+        @Override
+        public void setScope(String scope) {
+            delegate.setScope(scope);
+        }
+
+        @Override
+        public SslRequired getSslRequired() {
+            return delegate.getSslRequired();
+        }
+
+        @Override
+        public void setSslRequired(SslRequired sslRequired) {
+            delegate.setSslRequired(sslRequired);
+        }
+
+        @Override
+        public TokenStore getTokenStore() {
+            return delegate.getTokenStore();
+        }
+
+        @Override
+        public void setTokenStore(TokenStore tokenStore) {
+            delegate.setTokenStore(tokenStore);
+        }
+
+        @Override
+        public String getStateCookieName() {
+            return delegate.getStateCookieName();
+        }
+
+        @Override
+        public void setStateCookieName(String stateCookieName) {
+            delegate.setStateCookieName(stateCookieName);
+        }
+
+        @Override
+        public boolean isUseResourceRoleMappings() {
+            return delegate.isUseResourceRoleMappings();
+        }
+
+        @Override
+        public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
+            delegate.setUseResourceRoleMappings(useResourceRoleMappings);
+        }
+
+        @Override
+        public boolean isCors() {
+            return delegate.isCors();
+        }
+
+        @Override
+        public void setCors(boolean cors) {
+            delegate.setCors(cors);
+        }
+
+        @Override
+        public int getCorsMaxAge() {
+            return delegate.getCorsMaxAge();
+        }
+
+        @Override
+        public void setCorsMaxAge(int corsMaxAge) {
+            delegate.setCorsMaxAge(corsMaxAge);
+        }
+
+        @Override
+        public String getCorsAllowedHeaders() {
+            return delegate.getCorsAllowedHeaders();
+        }
+
+        @Override
+        public void setNotBefore(int notBefore) {
+            delegate.setNotBefore(notBefore);
+        }
+
+        @Override
+        public int getNotBefore() {
+            return delegate.getNotBefore();
+        }
+
+        @Override
+        public void setExposeToken(boolean exposeToken) {
+            delegate.setExposeToken(exposeToken);
+        }
+
+        @Override
+        public boolean isExposeToken() {
+            return delegate.isExposeToken();
+        }
+
+        @Override
+        public void setCorsAllowedMethods(String corsAllowedMethods) {
+            delegate.setCorsAllowedMethods(corsAllowedMethods);
+        }
+
+        @Override
+        public String getCorsAllowedMethods() {
+            return delegate.getCorsAllowedMethods();
+        }
+
+        @Override
+        public void setCorsAllowedHeaders(String corsAllowedHeaders) {
+            delegate.setCorsAllowedHeaders(corsAllowedHeaders);
+        }
+
+        @Override
+        public boolean isAlwaysRefreshToken() {
+            return delegate.isAlwaysRefreshToken();
+        }
+
+        @Override
+        public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
+            delegate.setAlwaysRefreshToken(alwaysRefreshToken);
+        }
+
+        @Override
+        public int getRegisterNodePeriod() {
+            return delegate.getRegisterNodePeriod();
+        }
+
+        @Override
+        public void setRegisterNodePeriod(int registerNodePeriod) {
+            delegate.setRegisterNodePeriod(registerNodePeriod);
+        }
+
+        @Override
+        public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
+            delegate.setRegisterNodeAtStartup(registerNodeAtStartup);
+        }
+
+        @Override
+        public boolean isRegisterNodeAtStartup() {
+            return delegate.isRegisterNodeAtStartup();
+        }
+
+        @Override
+        public String getPrincipalAttribute() {
+            return delegate.getPrincipalAttribute();
+        }
+
+        @Override
+        public void setPrincipalAttribute(String principalAttribute) {
+            delegate.setPrincipalAttribute(principalAttribute);
+        }
+    }
+
+    protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(base);
+        URI request = URI.create(facade.getRequest().getURI());
+        String scheme = request.getScheme();
+        if (deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            scheme = "https";
+            if (!request.getScheme().equals(scheme) && request.getPort() != -1) {
+                log.error("request scheme: " + request.getScheme() + " ssl required");
+                throw new RuntimeException("Can't resolve relative url from adapter config.");
+            }
+        }
+        builder.scheme(scheme);
+        builder.host(request.getHost());
+        if (request.getPort() != -1) {
+           builder.port(request.getPort());
+        }
+        return builder;
+    }
+
+
+
+    protected void close(HttpResponse response) {
+        if (response.getEntity() != null) {
+            try {
+                response.getEntity().getContent().close();
+            } catch (IOException e) {
+
+            }
+        }
+    }
+
+    public void updateDeployment(AdapterConfig config) {
+        if (null != configResolver) {
+            throw new IllegalStateException("Cannot parse an adapter config and build an updated deployment when on a multi-tenant scenario.");
+        }
+        deployment = KeycloakDeploymentBuilder.build(config);
+    }
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
index 10f960e..94385f0 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
@@ -1,21 +1,21 @@
-package org.keycloak.adapters;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface AuthChallenge {
-    /**
-     *
-     * @param exchange
-     * @return challenge sent
-     */
-    boolean challenge(HttpFacade exchange);
-
-    /**
-     * Whether or not an error page should be displayed if possible
-     *
-     * @return
-     */
-    boolean errorPage();
-}
+package org.keycloak.adapters;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AuthChallenge {
+    /**
+     *
+     * @param exchange
+     * @return challenge sent
+     */
+    boolean challenge(HttpFacade exchange);
+
+    /**
+     * Whether or not an error page should be displayed if possible
+     *
+     * @return
+     */
+    boolean errorPage();
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
index 98bc5cc..4ba3f1d 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java
@@ -1,111 +1,111 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.util.UriUtils;
-
-import java.io.IOException;
-import java.util.Set;
-
-/**
- * Pre-installed actions that must be authenticated
- *
- * Actions include:
- *
- * CORS Origin Check and Response headers
- * k_query_bearer_token: Get bearer token from server for Javascripts CORS requests
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticatedActionsHandler {
-    private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class);
-    protected KeycloakDeployment deployment;
-    protected HttpFacade facade;
-
-    public AuthenticatedActionsHandler(KeycloakDeployment deployment, HttpFacade facade) {
-        this.deployment = deployment;
-        this.facade = facade;
-    }
-
-    public boolean handledRequest() {
-        log.debugv("AuthenticatedActionsValve.invoke {0}", facade.getRequest().getURI());
-        if (corsRequest()) return true;
-        String requestUri = facade.getRequest().getURI();
-        if (requestUri.endsWith(AdapterConstants.K_QUERY_BEARER_TOKEN)) {
-            queryBearerToken();
-            return true;
-        }
-        return false;
-    }
-
-    protected void queryBearerToken()  {
-        log.debugv("queryBearerToken {0}",facade.getRequest().getURI());
-        if (abortTokenResponse()) return;
-        facade.getResponse().setStatus(200);
-        facade.getResponse().setHeader("Content-Type", "text/plain");
-        try {
-            facade.getResponse().getOutputStream().write(facade.getSecurityContext().getTokenString().getBytes());
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        facade.getResponse().end();
-    }
-
-    protected boolean abortTokenResponse() {
-        if (facade.getSecurityContext() == null) {
-            log.debugv("Not logged in, sending back 401: {0}",facade.getRequest().getURI());
-            facade.getResponse().setStatus(401);
-            facade.getResponse().end();
-            return true;
-        }
-        if (!deployment.isExposeToken()) {
-            facade.getResponse().setStatus(200);
-            facade.getResponse().end();
-             return true;
-        }
-        // Don't allow a CORS request if we're not validating CORS requests.
-        if (!deployment.isCors() && facade.getRequest().getHeader(CorsHeaders.ORIGIN) != null) {
-            facade.getResponse().setStatus(200);
-            facade.getResponse().end();
-            return true;
-        }
-        return false;
-    }
-
-    protected boolean corsRequest()  {
-        if (!deployment.isCors()) return false;
-        KeycloakSecurityContext securityContext = facade.getSecurityContext();
-        String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
-        String requestOrigin = UriUtils.getOrigin(facade.getRequest().getURI());
-        log.debugv("Origin: {0} uri: {1}", origin, facade.getRequest().getURI());
-        if (securityContext != null && origin != null && !origin.equals(requestOrigin)) {
-            AccessToken token = securityContext.getToken();
-            Set<String> allowedOrigins = token.getAllowedOrigins();
-            if (log.isDebugEnabled()) {
-                for (String a : allowedOrigins) log.debug("   " + a);
-            }
-            if (allowedOrigins == null || (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin))) {
-                if (allowedOrigins == null) {
-                    log.debugv("allowedOrigins was null in token");
-                }
-                if (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin)) {
-                    log.debugv("allowedOrigins did not contain origin");
-
-                }
-                facade.getResponse().setStatus(403);
-                facade.getResponse().end();
-                return true;
-            }
-            log.debugv("returning origin: {0}", origin);
-            facade.getResponse().setStatus(200);
-            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
-            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
-        } else {
-            log.debugv("cors validation not needed as we're not a secure session or origin header was null: {0}", facade.getRequest().getURI());
-        }
-        return false;
-    }
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.util.UriUtils;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Pre-installed actions that must be authenticated
+ *
+ * Actions include:
+ *
+ * CORS Origin Check and Response headers
+ * k_query_bearer_token: Get bearer token from server for Javascripts CORS requests
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticatedActionsHandler {
+    private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class);
+    protected KeycloakDeployment deployment;
+    protected HttpFacade facade;
+
+    public AuthenticatedActionsHandler(KeycloakDeployment deployment, HttpFacade facade) {
+        this.deployment = deployment;
+        this.facade = facade;
+    }
+
+    public boolean handledRequest() {
+        log.debugv("AuthenticatedActionsValve.invoke {0}", facade.getRequest().getURI());
+        if (corsRequest()) return true;
+        String requestUri = facade.getRequest().getURI();
+        if (requestUri.endsWith(AdapterConstants.K_QUERY_BEARER_TOKEN)) {
+            queryBearerToken();
+            return true;
+        }
+        return false;
+    }
+
+    protected void queryBearerToken()  {
+        log.debugv("queryBearerToken {0}",facade.getRequest().getURI());
+        if (abortTokenResponse()) return;
+        facade.getResponse().setStatus(200);
+        facade.getResponse().setHeader("Content-Type", "text/plain");
+        try {
+            facade.getResponse().getOutputStream().write(facade.getSecurityContext().getTokenString().getBytes());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        facade.getResponse().end();
+    }
+
+    protected boolean abortTokenResponse() {
+        if (facade.getSecurityContext() == null) {
+            log.debugv("Not logged in, sending back 401: {0}",facade.getRequest().getURI());
+            facade.getResponse().setStatus(401);
+            facade.getResponse().end();
+            return true;
+        }
+        if (!deployment.isExposeToken()) {
+            facade.getResponse().setStatus(200);
+            facade.getResponse().end();
+             return true;
+        }
+        // Don't allow a CORS request if we're not validating CORS requests.
+        if (!deployment.isCors() && facade.getRequest().getHeader(CorsHeaders.ORIGIN) != null) {
+            facade.getResponse().setStatus(200);
+            facade.getResponse().end();
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean corsRequest()  {
+        if (!deployment.isCors()) return false;
+        KeycloakSecurityContext securityContext = facade.getSecurityContext();
+        String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
+        String requestOrigin = UriUtils.getOrigin(facade.getRequest().getURI());
+        log.debugv("Origin: {0} uri: {1}", origin, facade.getRequest().getURI());
+        if (securityContext != null && origin != null && !origin.equals(requestOrigin)) {
+            AccessToken token = securityContext.getToken();
+            Set<String> allowedOrigins = token.getAllowedOrigins();
+            if (log.isDebugEnabled()) {
+                for (String a : allowedOrigins) log.debug("   " + a);
+            }
+            if (allowedOrigins == null || (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin))) {
+                if (allowedOrigins == null) {
+                    log.debugv("allowedOrigins was null in token");
+                }
+                if (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin)) {
+                    log.debugv("allowedOrigins did not contain origin");
+
+                }
+                facade.getResponse().setStatus(403);
+                facade.getResponse().end();
+                return true;
+            }
+            log.debugv("returning origin: {0}", origin);
+            facade.getResponse().setStatus(200);
+            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
+        } else {
+            log.debugv("cors validation not needed as we're not a secure session or origin header was null: {0}", facade.getRequest().getURI());
+        }
+        return false;
+    }
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java
index e19dfa0..47eeee1 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java
@@ -1,11 +1,11 @@
-package org.keycloak.adapters;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public enum AuthOutcome {
-    NOT_ATTEMPTED,
-    FAILED,
-    AUTHENTICATED
-}
+package org.keycloak.adapters;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public enum AuthOutcome {
+    NOT_ATTEMPTED,
+    FAILED,
+    AUTHENTICATED
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java
index 6f8f649..ae3888c 100644
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BasicAuthRequestAuthenticator.java
@@ -1,114 +1,114 @@
-package org.keycloak.adapters;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-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.OAuth2Constants;
-import org.keycloak.constants.ServiceUrlConstants;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.util.BasicAuthHelper;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import java.util.List;
-
-/**
- * Basic auth request authenticator.
- */
-public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticator {
-    protected Logger log = Logger.getLogger(BasicAuthRequestAuthenticator.class);
-    
-    public BasicAuthRequestAuthenticator(KeycloakDeployment deployment) {
-    	super(deployment);
-    }
-
-    public AuthOutcome authenticate(HttpFacade exchange)  {
-        List<String> authHeaders = exchange.getRequest().getHeaders("Authorization");
-        if (authHeaders == null || authHeaders.size() == 0) {
-            challenge = challengeResponse(exchange, null, null);
-            return AuthOutcome.NOT_ATTEMPTED;
-        }
-
-        tokenString = null;
-        for (String authHeader : authHeaders) {
-            String[] split = authHeader.trim().split("\\s+");
-            if (split == null || split.length != 2) continue;
-            if (!split[0].equalsIgnoreCase("Basic")) continue;
-            tokenString = split[1];
-        }
-
-        if (tokenString == null) {
-            challenge = challengeResponse(exchange, null, null);
-            return AuthOutcome.NOT_ATTEMPTED;
-        }
-
-        AccessTokenResponse atr=null;        
-        try {
-            String userpw=new String(net.iharder.Base64.decode(tokenString));
-            String[] parts=userpw.split(":");
-            
-            atr = getToken(parts[0], parts[1]);
-            tokenString = atr.getToken();
-        } catch (Exception e) {
-            log.debug("Failed to obtain token", e);
-            challenge = challengeResponse(exchange, "no_token", e.getMessage());
-            return AuthOutcome.FAILED;
-        }
-
-        return authenticateToken(exchange, atr.getToken());
-    }
-    
-    private AccessTokenResponse getToken(String username, String password) throws Exception {
-    	AccessTokenResponse tokenResponse=null;
-    	HttpClient client = new HttpClientBuilder().disableTrustManager().build();
-
-    	try {
-    	    HttpPost post = new HttpPost(
-    	            KeycloakUriBuilder.fromUri(deployment.getAuthServerBaseUrl())
-    	            .path(ServiceUrlConstants.TOKEN_PATH).build(deployment.getRealm()));
-    	    java.util.List <NameValuePair> formparams = new java.util.ArrayList <NameValuePair>();
-    	    formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD));
-    	    formparams.add(new BasicNameValuePair("username", username));
-    	    formparams.add(new BasicNameValuePair("password", password));
-
-    	    if (deployment.isPublicClient()) {
-    	        formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, deployment.getResourceName()));
-    	    } else {
-    	        String authorization = BasicAuthHelper.createHeader(deployment.getResourceName(),
-    	                deployment.getResourceCredentials().get("secret"));
-    	        post.setHeader("Authorization", authorization);
-    	    }
-
-    	    UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-    	    post.setEntity(form);
-
-    	    HttpResponse response = client.execute(post);
-    	    int status = response.getStatusLine().getStatusCode();
-    	    HttpEntity entity = response.getEntity();
-    	    if (status != 200) {
-    	        throw new java.io.IOException("Bad status: " + status);
-    	    }
-    	    if (entity == null) {
-    	        throw new java.io.IOException("No Entity");
-    	    }
-    	    java.io.InputStream is = entity.getContent();
-    	    try {
-    	        tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
-    	    } finally {
-    	        try {
-    	            is.close();
-    	        } catch (java.io.IOException ignored) { }
-    	    }
-    	} finally {
-    	    client.getConnectionManager().shutdown();
-    	}
-    	
-    	return (tokenResponse);
-    }
-
-}
+package org.keycloak.adapters;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+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.OAuth2Constants;
+import org.keycloak.constants.ServiceUrlConstants;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.util.BasicAuthHelper;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.util.List;
+
+/**
+ * Basic auth request authenticator.
+ */
+public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticator {
+    protected Logger log = Logger.getLogger(BasicAuthRequestAuthenticator.class);
+    
+    public BasicAuthRequestAuthenticator(KeycloakDeployment deployment) {
+    	super(deployment);
+    }
+
+    public AuthOutcome authenticate(HttpFacade exchange)  {
+        List<String> authHeaders = exchange.getRequest().getHeaders("Authorization");
+        if (authHeaders == null || authHeaders.size() == 0) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        tokenString = null;
+        for (String authHeader : authHeaders) {
+            String[] split = authHeader.trim().split("\\s+");
+            if (split == null || split.length != 2) continue;
+            if (!split[0].equalsIgnoreCase("Basic")) continue;
+            tokenString = split[1];
+        }
+
+        if (tokenString == null) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        AccessTokenResponse atr=null;        
+        try {
+            String userpw=new String(net.iharder.Base64.decode(tokenString));
+            String[] parts=userpw.split(":");
+            
+            atr = getToken(parts[0], parts[1]);
+            tokenString = atr.getToken();
+        } catch (Exception e) {
+            log.debug("Failed to obtain token", e);
+            challenge = challengeResponse(exchange, "no_token", e.getMessage());
+            return AuthOutcome.FAILED;
+        }
+
+        return authenticateToken(exchange, atr.getToken());
+    }
+    
+    private AccessTokenResponse getToken(String username, String password) throws Exception {
+    	AccessTokenResponse tokenResponse=null;
+    	HttpClient client = new HttpClientBuilder().disableTrustManager().build();
+
+    	try {
+    	    HttpPost post = new HttpPost(
+    	            KeycloakUriBuilder.fromUri(deployment.getAuthServerBaseUrl())
+    	            .path(ServiceUrlConstants.TOKEN_PATH).build(deployment.getRealm()));
+    	    java.util.List <NameValuePair> formparams = new java.util.ArrayList <NameValuePair>();
+    	    formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD));
+    	    formparams.add(new BasicNameValuePair("username", username));
+    	    formparams.add(new BasicNameValuePair("password", password));
+
+    	    if (deployment.isPublicClient()) {
+    	        formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, deployment.getResourceName()));
+    	    } else {
+    	        String authorization = BasicAuthHelper.createHeader(deployment.getResourceName(),
+    	                deployment.getResourceCredentials().get("secret"));
+    	        post.setHeader("Authorization", authorization);
+    	    }
+
+    	    UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+    	    post.setEntity(form);
+
+    	    HttpResponse response = client.execute(post);
+    	    int status = response.getStatusLine().getStatusCode();
+    	    HttpEntity entity = response.getEntity();
+    	    if (status != 200) {
+    	        throw new java.io.IOException("Bad status: " + status);
+    	    }
+    	    if (entity == null) {
+    	        throw new java.io.IOException("No Entity");
+    	    }
+    	    java.io.InputStream is = entity.getContent();
+    	    try {
+    	        tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
+    	    } finally {
+    	        try {
+    	            is.close();
+    	        } catch (java.io.IOException ignored) { }
+    	    }
+    	} finally {
+    	    client.getConnectionManager().shutdown();
+    	}
+    	
+    	return (tokenResponse);
+    }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
index 1ff7b15..54395eb 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
@@ -1,150 +1,150 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.VerificationException;
-import org.keycloak.representations.AccessToken;
-
-import javax.security.cert.X509Certificate;
-import java.util.List;
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class BearerTokenRequestAuthenticator {
-    protected Logger log = Logger.getLogger(BearerTokenRequestAuthenticator.class);
-    protected String tokenString;
-    protected AccessToken token;
-    protected String surrogate;
-    protected AuthChallenge challenge;
-    protected KeycloakDeployment deployment;
-
-    public BearerTokenRequestAuthenticator(KeycloakDeployment deployment) {
-        this.deployment = deployment;
-    }
-
-    public AuthChallenge getChallenge() {
-        return challenge;
-    }
-
-    public String getTokenString() {
-        return tokenString;
-    }
-
-    public AccessToken getToken() {
-        return token;
-    }
-
-    public String getSurrogate() {
-        return surrogate;
-    }
-
-    public AuthOutcome authenticate(HttpFacade exchange)  {
-        List<String> authHeaders = exchange.getRequest().getHeaders("Authorization");
-        if (authHeaders == null || authHeaders.size() == 0) {
-            challenge = challengeResponse(exchange, null, null);
-            return AuthOutcome.NOT_ATTEMPTED;
-        }
-
-        tokenString = null;
-        for (String authHeader : authHeaders) {
-            String[] split = authHeader.trim().split("\\s+");
-            if (split == null || split.length != 2) continue;
-            if (!split[0].equalsIgnoreCase("Bearer")) continue;
-            tokenString = split[1];
-        }
-
-        if (tokenString == null) {
-            challenge = challengeResponse(exchange, null, null);
-            return AuthOutcome.NOT_ATTEMPTED;
-        }
-
-        return (authenticateToken(exchange, tokenString));
-    }
-    
-    protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
-        try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
-        } catch (VerificationException e) {
-            log.error("Failed to verify token", e);
-            challenge = challengeResponse(exchange, "invalid_token", e.getMessage());
-            return AuthOutcome.FAILED;
-        }
-        if (token.getIssuedAt() < deployment.getNotBefore()) {
-            log.error("Stale token");
-            challenge = challengeResponse(exchange, "invalid_token", "Stale token");
-            return AuthOutcome.FAILED;
-        }
-        boolean verifyCaller = false;
-        if (deployment.isUseResourceRoleMappings()) {
-            verifyCaller = token.isVerifyCaller(deployment.getResourceName());
-        } else {
-            verifyCaller = token.isVerifyCaller();
-        }
-        surrogate = null;
-        if (verifyCaller) {
-            if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0) {
-                log.warn("No trusted certificates in token");
-                challenge = clientCertChallenge();
-                return AuthOutcome.FAILED;
-            }
-
-            // for now, we just make sure Undertow did two-way SSL
-            // assume JBoss Web verifies the client cert
-            X509Certificate[] chain = new X509Certificate[0];
-            try {
-                chain = exchange.getCertificateChain();
-            } catch (Exception ignore) {
-
-            }
-            if (chain == null || chain.length == 0) {
-                log.warn("No certificates provided by undertow to verify the caller");
-                challenge = clientCertChallenge();
-                return AuthOutcome.FAILED;
-            }
-            surrogate = chain[0].getSubjectDN().getName();
-        }
-        return AuthOutcome.AUTHENTICATED;
-    }
-
-    protected AuthChallenge clientCertChallenge() {
-        return new AuthChallenge() {
-            @Override
-            public boolean errorPage() {
-                return false;
-            }
-
-            @Override
-            public boolean challenge(HttpFacade exchange) {
-                // do the same thing as client cert auth
-                return false;
-            }
-        };
-    }
-
-
-    protected AuthChallenge challengeResponse(HttpFacade facade, String error, String description) {
-        StringBuilder header = new StringBuilder("Bearer realm=\"");
-        header.append(deployment.getRealm()).append("\"");
-        if (error != null) {
-            header.append(", error=\"").append(error).append("\"");
-        }
-        if (description != null) {
-            header.append(", error_description=\"").append(description).append("\"");
-        }
-        final String challenge = header.toString();
-        return new AuthChallenge() {
-            @Override
-            public boolean errorPage() {
-                return true;
-            }
-
-            @Override
-            public boolean challenge(HttpFacade facade) {
-                facade.getResponse().setStatus(401);
-                facade.getResponse().addHeader("WWW-Authenticate", challenge);
-                return true;
-            }
-        };
-    }
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.representations.AccessToken;
+
+import javax.security.cert.X509Certificate;
+import java.util.List;
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class BearerTokenRequestAuthenticator {
+    protected Logger log = Logger.getLogger(BearerTokenRequestAuthenticator.class);
+    protected String tokenString;
+    protected AccessToken token;
+    protected String surrogate;
+    protected AuthChallenge challenge;
+    protected KeycloakDeployment deployment;
+
+    public BearerTokenRequestAuthenticator(KeycloakDeployment deployment) {
+        this.deployment = deployment;
+    }
+
+    public AuthChallenge getChallenge() {
+        return challenge;
+    }
+
+    public String getTokenString() {
+        return tokenString;
+    }
+
+    public AccessToken getToken() {
+        return token;
+    }
+
+    public String getSurrogate() {
+        return surrogate;
+    }
+
+    public AuthOutcome authenticate(HttpFacade exchange)  {
+        List<String> authHeaders = exchange.getRequest().getHeaders("Authorization");
+        if (authHeaders == null || authHeaders.size() == 0) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        tokenString = null;
+        for (String authHeader : authHeaders) {
+            String[] split = authHeader.trim().split("\\s+");
+            if (split == null || split.length != 2) continue;
+            if (!split[0].equalsIgnoreCase("Bearer")) continue;
+            tokenString = split[1];
+        }
+
+        if (tokenString == null) {
+            challenge = challengeResponse(exchange, null, null);
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        return (authenticateToken(exchange, tokenString));
+    }
+    
+    protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
+        try {
+            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+        } catch (VerificationException e) {
+            log.error("Failed to verify token", e);
+            challenge = challengeResponse(exchange, "invalid_token", e.getMessage());
+            return AuthOutcome.FAILED;
+        }
+        if (token.getIssuedAt() < deployment.getNotBefore()) {
+            log.error("Stale token");
+            challenge = challengeResponse(exchange, "invalid_token", "Stale token");
+            return AuthOutcome.FAILED;
+        }
+        boolean verifyCaller = false;
+        if (deployment.isUseResourceRoleMappings()) {
+            verifyCaller = token.isVerifyCaller(deployment.getResourceName());
+        } else {
+            verifyCaller = token.isVerifyCaller();
+        }
+        surrogate = null;
+        if (verifyCaller) {
+            if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0) {
+                log.warn("No trusted certificates in token");
+                challenge = clientCertChallenge();
+                return AuthOutcome.FAILED;
+            }
+
+            // for now, we just make sure Undertow did two-way SSL
+            // assume JBoss Web verifies the client cert
+            X509Certificate[] chain = new X509Certificate[0];
+            try {
+                chain = exchange.getCertificateChain();
+            } catch (Exception ignore) {
+
+            }
+            if (chain == null || chain.length == 0) {
+                log.warn("No certificates provided by undertow to verify the caller");
+                challenge = clientCertChallenge();
+                return AuthOutcome.FAILED;
+            }
+            surrogate = chain[0].getSubjectDN().getName();
+        }
+        return AuthOutcome.AUTHENTICATED;
+    }
+
+    protected AuthChallenge clientCertChallenge() {
+        return new AuthChallenge() {
+            @Override
+            public boolean errorPage() {
+                return false;
+            }
+
+            @Override
+            public boolean challenge(HttpFacade exchange) {
+                // do the same thing as client cert auth
+                return false;
+            }
+        };
+    }
+
+
+    protected AuthChallenge challengeResponse(HttpFacade facade, String error, String description) {
+        StringBuilder header = new StringBuilder("Bearer realm=\"");
+        header.append(deployment.getRealm()).append("\"");
+        if (error != null) {
+            header.append(", error=\"").append(error).append("\"");
+        }
+        if (description != null) {
+            header.append(", error_description=\"").append(description).append("\"");
+        }
+        final String challenge = header.toString();
+        return new AuthChallenge() {
+            @Override
+            public boolean errorPage() {
+                return true;
+            }
+
+            @Override
+            public boolean challenge(HttpFacade facade) {
+                facade.getResponse().setStatus(401);
+                facade.getResponse().addHeader("WWW-Authenticate", challenge);
+                return true;
+            }
+        };
+    }
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
index 21f2b94..a4a5ae1 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/CorsHeaders.java
@@ -1,16 +1,16 @@
-package org.keycloak.adapters;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface CorsHeaders {
-    String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
-    String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
-    String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
-    String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
-    String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
-    String ORIGIN = "Origin";
-    String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
-    String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
-}
+package org.keycloak.adapters;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CorsHeaders {
+    String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
+    String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
+    String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
+    String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
+    String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
+    String ORIGIN = "Origin";
+    String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
+    String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
index 88d5247..fdf6186 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
@@ -1,352 +1,352 @@
-package org.keycloak.adapters;
-
-import org.apache.http.client.CookieStore;
-import org.apache.http.client.HttpClient;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.cookie.Cookie;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.SingleClientConnManager;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.EnvUtil;
-import org.keycloak.util.KeystoreUtil;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Abstraction for creating HttpClients. Allows SSL configuration.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HttpClientBuilder {
-    public static enum HostnameVerificationPolicy {
-        /**
-         * Hostname verification is not done on the server's certificate
-         */
-        ANY,
-        /**
-         * Allows wildcards in subdomain names i.e. *.foo.com
-         */
-        WILDCARD,
-        /**
-         * CN must match hostname connecting to
-         */
-        STRICT
-    }
-
-
-    /**
-     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-     * @version $Revision: 1 $
-     */
-    private static class PassthroughTrustManager implements X509TrustManager {
-        public void checkClientTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
-    }
-
-    protected KeyStore truststore;
-    protected KeyStore clientKeyStore;
-    protected String clientPrivateKeyPassword;
-    protected boolean disableTrustManager;
-    protected boolean disableCookieCache = true;
-    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
-    protected SSLContext sslContext;
-    protected int connectionPoolSize = 100;
-    protected int maxPooledPerRoute = 0;
-    protected long connectionTTL = -1;
-    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
-    protected HostnameVerifier verifier = null;
-    protected long socketTimeout = -1;
-    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
-    protected long establishConnectionTimeout = -1;
-    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
-
-
-    /**
-     * Socket inactivity timeout
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
-    {
-        this.socketTimeout = timeout;
-        this.socketTimeoutUnits = unit;
-        return this;
-    }
-
-    /**
-     * When trying to make an initial socket connection, what is the timeout?
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
-    {
-        this.establishConnectionTimeout = timeout;
-        this.establishConnectionTimeoutUnits = unit;
-        return this;
-    }
-
-    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
-        this.connectionTTL = ttl;
-        this.connectionTTLUnit = unit;
-        return this;
-    }
-
-    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
-        this.maxPooledPerRoute = maxPooledPerRoute;
-        return this;
-    }
-
-    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
-        this.connectionPoolSize = connectionPoolSize;
-        return this;
-    }
-
-    /**
-     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
-     * hole, so only set this option if you cannot or do not want to verify the identity of the
-     * host you are communicating with.
-     */
-    public HttpClientBuilder disableTrustManager() {
-        this.disableTrustManager = true;
-        return this;
-    }
-
-    public HttpClientBuilder disableCookieCache() {
-        this.disableCookieCache = true;
-        return this;
-    }
-
-    /**
-     * SSL policy used to verify hostnames
-     *
-     * @param policy
-     * @return
-     */
-    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
-        this.policy = policy;
-        return this;
-    }
-
-
-    public HttpClientBuilder sslContext(SSLContext sslContext) {
-        this.sslContext = sslContext;
-        return this;
-    }
-
-    public HttpClientBuilder trustStore(KeyStore truststore) {
-        this.truststore = truststore;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = password;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = new String(password);
-        return this;
-    }
-
-
-    static class VerifierWrapper implements X509HostnameVerifier {
-        protected HostnameVerifier verifier;
-
-        VerifierWrapper(HostnameVerifier verifier) {
-            this.verifier = verifier;
-        }
-
-        @Override
-        public void verify(String host, SSLSocket ssl) throws IOException {
-            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
-        }
-
-        @Override
-        public void verify(String host, X509Certificate cert) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public boolean verify(String s, SSLSession sslSession) {
-            return verifier.verify(s, sslSession);
-        }
-    }
-
-    public HttpClient build() {
-        X509HostnameVerifier verifier = null;
-        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
-        else {
-            switch (policy) {
-                case ANY:
-                    verifier = new AllowAllHostnameVerifier();
-                    break;
-                case WILDCARD:
-                    verifier = new BrowserCompatHostnameVerifier();
-                    break;
-                case STRICT:
-                    verifier = new StrictHostnameVerifier();
-                    break;
-            }
-        }
-        try {
-            SSLSocketFactory sslsf = null;
-            SSLContext theContext = sslContext;
-            if (disableTrustManager) {
-                theContext = SSLContext.getInstance("SSL");
-                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
-                        new SecureRandom());
-                verifier = new AllowAllHostnameVerifier();
-                sslsf = new SSLSocketFactory(theContext, verifier);
-            } else if (theContext != null) {
-                sslsf = new SSLSocketFactory(theContext, verifier);
-            } else if (clientKeyStore != null || truststore != null) {
-                sslsf = new SSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
-            } else {
-                final SSLContext tlsContext = SSLContext.getInstance(SSLSocketFactory.TLS);
-                tlsContext.init(null, null, null);
-                sslsf = new SSLSocketFactory(tlsContext, verifier);
-            }
-            SchemeRegistry registry = new SchemeRegistry();
-            registry.register(
-                    new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
-            Scheme httpsScheme = new Scheme("https", 443, sslsf);
-            registry.register(httpsScheme);
-            ClientConnectionManager cm = null;
-            if (connectionPoolSize > 0) {
-                ThreadSafeClientConnManager tcm = new ThreadSafeClientConnManager(registry, connectionTTL, connectionTTLUnit);
-                tcm.setMaxTotal(connectionPoolSize);
-                if (maxPooledPerRoute == 0) maxPooledPerRoute = connectionPoolSize;
-                tcm.setDefaultMaxPerRoute(maxPooledPerRoute);
-                cm = tcm;
-
-            } else {
-                cm = new SingleClientConnManager(registry);
-            }
-            BasicHttpParams params = new BasicHttpParams();
-            if (socketTimeout > -1)
-            {
-                HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
-
-            }
-            if (establishConnectionTimeout > -1)
-            {
-                HttpConnectionParams.setConnectionTimeout(params, (int)establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
-            }
-            DefaultHttpClient client = new DefaultHttpClient(cm, params);
-            if (disableCookieCache) {
-                client.setCookieStore(new CookieStore() {
-                    @Override
-                    public void addCookie(Cookie cookie) {
-                        //To change body of implemented methods use File | Settings | File Templates.
-                    }
-
-                    @Override
-                    public List<Cookie> getCookies() {
-                        return Collections.emptyList();
-                    }
-
-                    @Override
-                    public boolean clearExpired(Date date) {
-                        return false;  //To change body of implemented methods use File | Settings | File Templates.
-                    }
-
-                    @Override
-                    public void clear() {
-                        //To change body of implemented methods use File | Settings | File Templates.
-                    }
-                });
-
-            }
-            return client;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public HttpClient build(AdapterConfig adapterConfig) {
-        disableCookieCache(); // disable cookie cache as we don't want sticky sessions for load balancing
-
-        String truststorePath = adapterConfig.getTruststore();
-        if (truststorePath != null) {
-            truststorePath = EnvUtil.replace(truststorePath);
-            String truststorePassword = adapterConfig.getTruststorePassword();
-            try {
-                this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);
-            } catch (Exception e) {
-                throw new RuntimeException("Failed to load truststore", e);
-            }
-        }
-        String clientKeystore = adapterConfig.getClientKeystore();
-        if (clientKeystore != null) {
-            clientKeystore = EnvUtil.replace(clientKeystore);
-            String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
-            try {
-                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
-                keyStore(clientCertKeystore, clientKeystorePassword);
-            } catch (Exception e) {
-                throw new RuntimeException("Failed to load keystore", e);
-            }
-        }
-        int size = 10;
-        if (adapterConfig.getConnectionPoolSize() > 0)
-            size = adapterConfig.getConnectionPoolSize();
-        HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;
-        if (adapterConfig.isAllowAnyHostname())
-            policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;
-        connectionPoolSize(size);
-        hostnameVerification(policy);
-        if (adapterConfig.isDisableTrustManager()) {
-            disableTrustManager();
-        } else {
-            trustStore(truststore);
-        }
-        return build();
-    }
+package org.keycloak.adapters;
+
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.SingleClientConnManager;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.EnvUtil;
+import org.keycloak.util.KeystoreUtil;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Abstraction for creating HttpClients. Allows SSL configuration.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HttpClientBuilder {
+    public static enum HostnameVerificationPolicy {
+        /**
+         * Hostname verification is not done on the server's certificate
+         */
+        ANY,
+        /**
+         * Allows wildcards in subdomain names i.e. *.foo.com
+         */
+        WILDCARD,
+        /**
+         * CN must match hostname connecting to
+         */
+        STRICT
+    }
+
+
+    /**
+     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+     * @version $Revision: 1 $
+     */
+    private static class PassthroughTrustManager implements X509TrustManager {
+        public void checkClientTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+
+    protected KeyStore truststore;
+    protected KeyStore clientKeyStore;
+    protected String clientPrivateKeyPassword;
+    protected boolean disableTrustManager;
+    protected boolean disableCookieCache = true;
+    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
+    protected SSLContext sslContext;
+    protected int connectionPoolSize = 100;
+    protected int maxPooledPerRoute = 0;
+    protected long connectionTTL = -1;
+    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
+    protected HostnameVerifier verifier = null;
+    protected long socketTimeout = -1;
+    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected long establishConnectionTimeout = -1;
+    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
+
+
+    /**
+     * Socket inactivity timeout
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
+    {
+        this.socketTimeout = timeout;
+        this.socketTimeoutUnits = unit;
+        return this;
+    }
+
+    /**
+     * When trying to make an initial socket connection, what is the timeout?
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
+    {
+        this.establishConnectionTimeout = timeout;
+        this.establishConnectionTimeoutUnits = unit;
+        return this;
+    }
+
+    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
+        this.connectionTTL = ttl;
+        this.connectionTTLUnit = unit;
+        return this;
+    }
+
+    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
+        this.maxPooledPerRoute = maxPooledPerRoute;
+        return this;
+    }
+
+    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+        return this;
+    }
+
+    /**
+     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
+     * hole, so only set this option if you cannot or do not want to verify the identity of the
+     * host you are communicating with.
+     */
+    public HttpClientBuilder disableTrustManager() {
+        this.disableTrustManager = true;
+        return this;
+    }
+
+    public HttpClientBuilder disableCookieCache() {
+        this.disableCookieCache = true;
+        return this;
+    }
+
+    /**
+     * SSL policy used to verify hostnames
+     *
+     * @param policy
+     * @return
+     */
+    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
+        this.policy = policy;
+        return this;
+    }
+
+
+    public HttpClientBuilder sslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+        return this;
+    }
+
+    public HttpClientBuilder trustStore(KeyStore truststore) {
+        this.truststore = truststore;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = password;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = new String(password);
+        return this;
+    }
+
+
+    static class VerifierWrapper implements X509HostnameVerifier {
+        protected HostnameVerifier verifier;
+
+        VerifierWrapper(HostnameVerifier verifier) {
+            this.verifier = verifier;
+        }
+
+        @Override
+        public void verify(String host, SSLSocket ssl) throws IOException {
+            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
+        }
+
+        @Override
+        public void verify(String host, X509Certificate cert) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public boolean verify(String s, SSLSession sslSession) {
+            return verifier.verify(s, sslSession);
+        }
+    }
+
+    public HttpClient build() {
+        X509HostnameVerifier verifier = null;
+        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
+        else {
+            switch (policy) {
+                case ANY:
+                    verifier = new AllowAllHostnameVerifier();
+                    break;
+                case WILDCARD:
+                    verifier = new BrowserCompatHostnameVerifier();
+                    break;
+                case STRICT:
+                    verifier = new StrictHostnameVerifier();
+                    break;
+            }
+        }
+        try {
+            SSLSocketFactory sslsf = null;
+            SSLContext theContext = sslContext;
+            if (disableTrustManager) {
+                theContext = SSLContext.getInstance("SSL");
+                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
+                        new SecureRandom());
+                verifier = new AllowAllHostnameVerifier();
+                sslsf = new SSLSocketFactory(theContext, verifier);
+            } else if (theContext != null) {
+                sslsf = new SSLSocketFactory(theContext, verifier);
+            } else if (clientKeyStore != null || truststore != null) {
+                sslsf = new SSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
+            } else {
+                final SSLContext tlsContext = SSLContext.getInstance(SSLSocketFactory.TLS);
+                tlsContext.init(null, null, null);
+                sslsf = new SSLSocketFactory(tlsContext, verifier);
+            }
+            SchemeRegistry registry = new SchemeRegistry();
+            registry.register(
+                    new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+            Scheme httpsScheme = new Scheme("https", 443, sslsf);
+            registry.register(httpsScheme);
+            ClientConnectionManager cm = null;
+            if (connectionPoolSize > 0) {
+                ThreadSafeClientConnManager tcm = new ThreadSafeClientConnManager(registry, connectionTTL, connectionTTLUnit);
+                tcm.setMaxTotal(connectionPoolSize);
+                if (maxPooledPerRoute == 0) maxPooledPerRoute = connectionPoolSize;
+                tcm.setDefaultMaxPerRoute(maxPooledPerRoute);
+                cm = tcm;
+
+            } else {
+                cm = new SingleClientConnManager(registry);
+            }
+            BasicHttpParams params = new BasicHttpParams();
+            if (socketTimeout > -1)
+            {
+                HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
+
+            }
+            if (establishConnectionTimeout > -1)
+            {
+                HttpConnectionParams.setConnectionTimeout(params, (int)establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
+            }
+            DefaultHttpClient client = new DefaultHttpClient(cm, params);
+            if (disableCookieCache) {
+                client.setCookieStore(new CookieStore() {
+                    @Override
+                    public void addCookie(Cookie cookie) {
+                        //To change body of implemented methods use File | Settings | File Templates.
+                    }
+
+                    @Override
+                    public List<Cookie> getCookies() {
+                        return Collections.emptyList();
+                    }
+
+                    @Override
+                    public boolean clearExpired(Date date) {
+                        return false;  //To change body of implemented methods use File | Settings | File Templates.
+                    }
+
+                    @Override
+                    public void clear() {
+                        //To change body of implemented methods use File | Settings | File Templates.
+                    }
+                });
+
+            }
+            return client;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public HttpClient build(AdapterConfig adapterConfig) {
+        disableCookieCache(); // disable cookie cache as we don't want sticky sessions for load balancing
+
+        String truststorePath = adapterConfig.getTruststore();
+        if (truststorePath != null) {
+            truststorePath = EnvUtil.replace(truststorePath);
+            String truststorePassword = adapterConfig.getTruststorePassword();
+            try {
+                this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load truststore", e);
+            }
+        }
+        String clientKeystore = adapterConfig.getClientKeystore();
+        if (clientKeystore != null) {
+            clientKeystore = EnvUtil.replace(clientKeystore);
+            String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
+            try {
+                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
+                keyStore(clientCertKeystore, clientKeystorePassword);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load keystore", e);
+            }
+        }
+        int size = 10;
+        if (adapterConfig.getConnectionPoolSize() > 0)
+            size = adapterConfig.getConnectionPoolSize();
+        HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;
+        if (adapterConfig.isAllowAnyHostname())
+            policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;
+        connectionPoolSize(size);
+        hostnameVerification(policy);
+        if (adapterConfig.isDisableTrustManager()) {
+            disableTrustManager();
+        } else {
+            trustStore(truststore);
+        }
+        return build();
+    }
 }
\ No newline at end of file
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java
index 3805eef..336fa54 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java
@@ -1,100 +1,100 @@
-package org.keycloak.adapters;
-
-import org.keycloak.KeycloakSecurityContext;
-
-import javax.security.cert.X509Certificate;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-
-/**
- * Bridge between core adapter and HTTP Engine
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface HttpFacade {
-
-    public class Cookie {
-        protected String name;
-        protected String value;
-        protected int version;
-        protected String domain;
-        protected String path;
-
-        public Cookie(String name, String value, int version, String domain, String path) {
-            this.name = name;
-            this.value = value;
-            this.version = version;
-            this.domain = domain;
-            this.path = path;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getValue() {
-            return value;
-        }
-
-        public int getVersion() {
-            return version;
-        }
-
-        public String getDomain() {
-            return domain;
-        }
-
-        public String getPath() {
-            return path;
-        }
-    }
-
-    interface Request {
-
-        String getMethod();
-        /**
-         * Full request URI with query params
-         *
-         * @return
-         */
-        String getURI();
-
-        /**
-         * HTTPS?
-         *
-         * @return
-         */
-        boolean isSecure();
-
-        String getQueryParamValue(String param);
-        Cookie getCookie(String cookieName);
-        String getHeader(String name);
-        List<String> getHeaders(String name);
-        InputStream getInputStream();
-
-        String getRemoteAddr();
-    }
-
-    interface Response {
-        void setStatus(int status);
-        void addHeader(String name, String value);
-        void setHeader(String name, String value);
-        void resetCookie(String name, String path);
-        void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly);
-        OutputStream getOutputStream();
-        void sendError(int code, String message);
-
-        /**
-         * If the response is finished, end it.
-         *
-         */
-        void end();
-    }
-
-    KeycloakSecurityContext getSecurityContext();
-    Request getRequest();
-    Response getResponse();
-    X509Certificate[] getCertificateChain();
-}
+package org.keycloak.adapters;
+
+import org.keycloak.KeycloakSecurityContext;
+
+import javax.security.cert.X509Certificate;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * Bridge between core adapter and HTTP Engine
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface HttpFacade {
+
+    public class Cookie {
+        protected String name;
+        protected String value;
+        protected int version;
+        protected String domain;
+        protected String path;
+
+        public Cookie(String name, String value, int version, String domain, String path) {
+            this.name = name;
+            this.value = value;
+            this.version = version;
+            this.domain = domain;
+            this.path = path;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public int getVersion() {
+            return version;
+        }
+
+        public String getDomain() {
+            return domain;
+        }
+
+        public String getPath() {
+            return path;
+        }
+    }
+
+    interface Request {
+
+        String getMethod();
+        /**
+         * Full request URI with query params
+         *
+         * @return
+         */
+        String getURI();
+
+        /**
+         * HTTPS?
+         *
+         * @return
+         */
+        boolean isSecure();
+
+        String getQueryParamValue(String param);
+        Cookie getCookie(String cookieName);
+        String getHeader(String name);
+        List<String> getHeaders(String name);
+        InputStream getInputStream();
+
+        String getRemoteAddr();
+    }
+
+    interface Response {
+        void setStatus(int status);
+        void addHeader(String name, String value);
+        void setHeader(String name, String value);
+        void resetCookie(String name, String path);
+        void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly);
+        OutputStream getOutputStream();
+        void sendError(int code, String message);
+
+        /**
+         * If the response is finished, end it.
+         *
+         */
+        void end();
+    }
+
+    KeycloakSecurityContext getSecurityContext();
+    Request getRequest();
+    Response getResponse();
+    X509Certificate[] getCertificateChain();
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java
index 21543ca..a242779 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakAccount.java
@@ -1,16 +1,16 @@
-package org.keycloak.adapters;
-
-import org.keycloak.KeycloakSecurityContext;
-
-import java.security.Principal;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakAccount {
-    Principal getPrincipal();
-    Set<String> getRoles();
-    KeycloakSecurityContext getKeycloakSecurityContext();
-}
+package org.keycloak.adapters;
+
+import org.keycloak.KeycloakSecurityContext;
+
+import java.security.Principal;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakAccount {
+    Principal getPrincipal();
+    Set<String> getRoles();
+    KeycloakSecurityContext getKeycloakSecurityContext();
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
index 478ead2..01960a4 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -1,354 +1,354 @@
-package org.keycloak.adapters;
-
-import org.apache.http.client.HttpClient;
-import org.jboss.logging.Logger;
-import org.keycloak.constants.ServiceUrlConstants;
-import org.keycloak.enums.RelativeUrlsUsed;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.enums.TokenStore;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import java.net.URI;
-import java.security.PublicKey;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakDeployment {
-
-    private static final Logger log = Logger.getLogger(KeycloakDeployment.class);
-
-    protected RelativeUrlsUsed relativeUrls;
-    protected String realm;
-    protected volatile PublicKey realmKey;
-    protected String authServerBaseUrl;
-    protected String realmInfoUrl;
-    protected KeycloakUriBuilder authUrl;
-    protected String tokenUrl;
-    protected KeycloakUriBuilder logoutUrl;
-    protected String accountUrl;
-    protected String registerNodeUrl;
-    protected String unregisterNodeUrl;
-    protected String principalAttribute = "sub";
-
-    protected String resourceName;
-    protected boolean bearerOnly;
-    protected boolean enableBasicAuth;
-    protected boolean publicClient;
-    protected Map<String, String> resourceCredentials = new HashMap<String, String>();
-    protected HttpClient client;
-
-    protected String scope;
-    protected SslRequired sslRequired = SslRequired.ALL;
-    protected TokenStore tokenStore = TokenStore.SESSION;
-    protected String stateCookieName = "OAuth_Token_Request_State";
-    protected boolean useResourceRoleMappings;
-    protected boolean cors;
-    protected int corsMaxAge = -1;
-    protected String corsAllowedHeaders;
-    protected String corsAllowedMethods;
-    protected boolean exposeToken;
-    protected boolean alwaysRefreshToken;
-    protected boolean registerNodeAtStartup;
-    protected int registerNodePeriod;
-    protected volatile int notBefore;
-
-    public KeycloakDeployment() {
-    }
-
-    public boolean isConfigured() {
-        return getRealm() != null && getRealmKey() != null && (isBearerOnly() || getAuthServerBaseUrl() != null);
-    }
-
-    public String getResourceName() {
-        return resourceName;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public void setRealm(String realm) {
-        this.realm = realm;
-    }
-
-    public PublicKey getRealmKey() {
-        return realmKey;
-    }
-
-    public void setRealmKey(PublicKey realmKey) {
-        this.realmKey = realmKey;
-    }
-
-    public String getAuthServerBaseUrl() {
-        return authServerBaseUrl;
-    }
-
-    public void setAuthServerBaseUrl(AdapterConfig config) {
-        this.authServerBaseUrl = config.getAuthServerUrl();
-        String authServerURLForBackendReqs = config.getAuthServerUrlForBackendRequests();
-        if (authServerBaseUrl == null && authServerURLForBackendReqs == null) return;
-
-        URI authServerUri = null;
-        if (authServerBaseUrl != null) {
-            authServerUri = URI.create(authServerBaseUrl);
-        }
-
-        if (authServerUri == null || authServerUri.getHost() == null) {
-            if (authServerURLForBackendReqs != null) {
-                relativeUrls = RelativeUrlsUsed.BROWSER_ONLY;
-
-                KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
-                if (serverBuilder.getHost() == null || serverBuilder.getScheme() == null) {
-                    throw new IllegalStateException("Relative URL not supported for auth-server-url-for-backend-requests option. URL used: "
-                            + authServerURLForBackendReqs + ", Client: " + config.getResource());
-                }
-                resolveNonBrowserUrls(serverBuilder);
-            } else {
-                relativeUrls = RelativeUrlsUsed.ALL_REQUESTS;
-            }
-        } else {
-            // We have absolute URI in config
-            relativeUrls = RelativeUrlsUsed.NEVER;
-            KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
-            resolveBrowserUrls(serverBuilder);
-
-            if (authServerURLForBackendReqs == null) {
-                resolveNonBrowserUrls(serverBuilder);
-            } else {
-                serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
-                resolveNonBrowserUrls(serverBuilder);
-            }
-        }
-    }
-
-
-
-    /**
-     * @param authUrlBuilder absolute URI
-     */
-    protected void resolveBrowserUrls(KeycloakUriBuilder authUrlBuilder) {
-        if (log.isDebugEnabled()) {
-            log.debug("resolveBrowserUrls");
-        }
-
-        String login = authUrlBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(getRealm()).toString();
-        authUrl = KeycloakUriBuilder.fromUri(login);
-        realmInfoUrl = authUrlBuilder.clone().path(ServiceUrlConstants.REALM_INFO_PATH).build(getRealm()).toString();
-    }
-
-    /**
-     * @param authUrlBuilder absolute URI
-     */
-    protected void resolveNonBrowserUrls(KeycloakUriBuilder authUrlBuilder) {
-        if (log.isDebugEnabled()) {
-            log.debug("resolveNonBrowserUrls");
-        }
-
-        tokenUrl = authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_PATH).build(getRealm()).toString();
-        logoutUrl = KeycloakUriBuilder.fromUri(authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(getRealm()).toString());
-        accountUrl = authUrlBuilder.clone().path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH).build(getRealm()).toString();
-        registerNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_REGISTER_NODE_PATH).build(getRealm()).toString();
-        unregisterNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH).build(getRealm()).toString();
-    }
-
-    public RelativeUrlsUsed getRelativeUrls() {
-        return relativeUrls;
-    }
-
-    public String getRealmInfoUrl() {
-        return realmInfoUrl;
-    }
-
-    public KeycloakUriBuilder getAuthUrl() {
-        return authUrl;
-    }
-
-    public String getTokenUrl() {
-        return tokenUrl;
-    }
-
-    public KeycloakUriBuilder getLogoutUrl() {
-        return logoutUrl;
-    }
-
-    public String getAccountUrl() {
-        return accountUrl;
-    }
-
-    public String getRegisterNodeUrl() {
-        return registerNodeUrl;
-    }
-
-    public String getUnregisterNodeUrl() {
-        return unregisterNodeUrl;
-    }
-
-    public void setResourceName(String resourceName) {
-        this.resourceName = resourceName;
-    }
-
-    public boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public void setBearerOnly(boolean bearerOnly) {
-        this.bearerOnly = bearerOnly;
-    }
-
-    public boolean isEnableBasicAuth() {
-        return enableBasicAuth;
-    }
-
-    public void setEnableBasicAuth(boolean enableBasicAuth) {
-        this.enableBasicAuth = enableBasicAuth;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public Map<String, String> getResourceCredentials() {
-        return resourceCredentials;
-    }
-
-    public void setResourceCredentials(Map<String, String> resourceCredentials) {
-        this.resourceCredentials = resourceCredentials;
-    }
-
-    public HttpClient getClient() {
-        return client;
-    }
-
-    public void setClient(HttpClient client) {
-        this.client = client;
-    }
-
-    public String getScope() {
-        return scope;
-    }
-
-    public void setScope(String scope) {
-        this.scope = scope;
-    }
-
-    public SslRequired getSslRequired() {
-        return sslRequired;
-    }
-
-    public void setSslRequired(SslRequired sslRequired) {
-        this.sslRequired = sslRequired;
-    }
-
-    public TokenStore getTokenStore() {
-        return tokenStore;
-    }
-
-    public void setTokenStore(TokenStore tokenStore) {
-        this.tokenStore = tokenStore;
-    }
-
-    public String getStateCookieName() {
-        return stateCookieName;
-    }
-
-    public void setStateCookieName(String stateCookieName) {
-        this.stateCookieName = stateCookieName;
-    }
-
-    public boolean isUseResourceRoleMappings() {
-        return useResourceRoleMappings;
-    }
-
-    public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
-        this.useResourceRoleMappings = useResourceRoleMappings;
-    }
-
-    public boolean isCors() {
-        return cors;
-    }
-
-    public void setCors(boolean cors) {
-        this.cors = cors;
-    }
-
-    public int getCorsMaxAge() {
-        return corsMaxAge;
-    }
-
-    public void setCorsMaxAge(int corsMaxAge) {
-        this.corsMaxAge = corsMaxAge;
-    }
-
-    public String getCorsAllowedHeaders() {
-        return corsAllowedHeaders;
-    }
-
-    public void setCorsAllowedHeaders(String corsAllowedHeaders) {
-        this.corsAllowedHeaders = corsAllowedHeaders;
-    }
-
-    public String getCorsAllowedMethods() {
-        return corsAllowedMethods;
-    }
-
-    public void setCorsAllowedMethods(String corsAllowedMethods) {
-        this.corsAllowedMethods = corsAllowedMethods;
-    }
-
-    public boolean isExposeToken() {
-        return exposeToken;
-    }
-
-    public void setExposeToken(boolean exposeToken) {
-        this.exposeToken = exposeToken;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public boolean isAlwaysRefreshToken() {
-        return alwaysRefreshToken;
-    }
-
-    public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
-        this.alwaysRefreshToken = alwaysRefreshToken;
-    }
-
-    public boolean isRegisterNodeAtStartup() {
-        return registerNodeAtStartup;
-    }
-
-    public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
-        this.registerNodeAtStartup = registerNodeAtStartup;
-    }
-
-    public int getRegisterNodePeriod() {
-        return registerNodePeriod;
-    }
-
-    public void setRegisterNodePeriod(int registerNodePeriod) {
-        this.registerNodePeriod = registerNodePeriod;
-    }
-
-    public String getPrincipalAttribute() {
-        return principalAttribute;
-    }
-
-    public void setPrincipalAttribute(String principalAttribute) {
-        this.principalAttribute = principalAttribute;
-    }
-}
+package org.keycloak.adapters;
+
+import org.apache.http.client.HttpClient;
+import org.jboss.logging.Logger;
+import org.keycloak.constants.ServiceUrlConstants;
+import org.keycloak.enums.RelativeUrlsUsed;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.enums.TokenStore;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.net.URI;
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakDeployment {
+
+    private static final Logger log = Logger.getLogger(KeycloakDeployment.class);
+
+    protected RelativeUrlsUsed relativeUrls;
+    protected String realm;
+    protected volatile PublicKey realmKey;
+    protected String authServerBaseUrl;
+    protected String realmInfoUrl;
+    protected KeycloakUriBuilder authUrl;
+    protected String tokenUrl;
+    protected KeycloakUriBuilder logoutUrl;
+    protected String accountUrl;
+    protected String registerNodeUrl;
+    protected String unregisterNodeUrl;
+    protected String principalAttribute = "sub";
+
+    protected String resourceName;
+    protected boolean bearerOnly;
+    protected boolean enableBasicAuth;
+    protected boolean publicClient;
+    protected Map<String, String> resourceCredentials = new HashMap<String, String>();
+    protected HttpClient client;
+
+    protected String scope;
+    protected SslRequired sslRequired = SslRequired.ALL;
+    protected TokenStore tokenStore = TokenStore.SESSION;
+    protected String stateCookieName = "OAuth_Token_Request_State";
+    protected boolean useResourceRoleMappings;
+    protected boolean cors;
+    protected int corsMaxAge = -1;
+    protected String corsAllowedHeaders;
+    protected String corsAllowedMethods;
+    protected boolean exposeToken;
+    protected boolean alwaysRefreshToken;
+    protected boolean registerNodeAtStartup;
+    protected int registerNodePeriod;
+    protected volatile int notBefore;
+
+    public KeycloakDeployment() {
+    }
+
+    public boolean isConfigured() {
+        return getRealm() != null && getRealmKey() != null && (isBearerOnly() || getAuthServerBaseUrl() != null);
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+
+    public PublicKey getRealmKey() {
+        return realmKey;
+    }
+
+    public void setRealmKey(PublicKey realmKey) {
+        this.realmKey = realmKey;
+    }
+
+    public String getAuthServerBaseUrl() {
+        return authServerBaseUrl;
+    }
+
+    public void setAuthServerBaseUrl(AdapterConfig config) {
+        this.authServerBaseUrl = config.getAuthServerUrl();
+        String authServerURLForBackendReqs = config.getAuthServerUrlForBackendRequests();
+        if (authServerBaseUrl == null && authServerURLForBackendReqs == null) return;
+
+        URI authServerUri = null;
+        if (authServerBaseUrl != null) {
+            authServerUri = URI.create(authServerBaseUrl);
+        }
+
+        if (authServerUri == null || authServerUri.getHost() == null) {
+            if (authServerURLForBackendReqs != null) {
+                relativeUrls = RelativeUrlsUsed.BROWSER_ONLY;
+
+                KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
+                if (serverBuilder.getHost() == null || serverBuilder.getScheme() == null) {
+                    throw new IllegalStateException("Relative URL not supported for auth-server-url-for-backend-requests option. URL used: "
+                            + authServerURLForBackendReqs + ", Client: " + config.getResource());
+                }
+                resolveNonBrowserUrls(serverBuilder);
+            } else {
+                relativeUrls = RelativeUrlsUsed.ALL_REQUESTS;
+            }
+        } else {
+            // We have absolute URI in config
+            relativeUrls = RelativeUrlsUsed.NEVER;
+            KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
+            resolveBrowserUrls(serverBuilder);
+
+            if (authServerURLForBackendReqs == null) {
+                resolveNonBrowserUrls(serverBuilder);
+            } else {
+                serverBuilder = KeycloakUriBuilder.fromUri(authServerURLForBackendReqs);
+                resolveNonBrowserUrls(serverBuilder);
+            }
+        }
+    }
+
+
+
+    /**
+     * @param authUrlBuilder absolute URI
+     */
+    protected void resolveBrowserUrls(KeycloakUriBuilder authUrlBuilder) {
+        if (log.isDebugEnabled()) {
+            log.debug("resolveBrowserUrls");
+        }
+
+        String login = authUrlBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(getRealm()).toString();
+        authUrl = KeycloakUriBuilder.fromUri(login);
+        realmInfoUrl = authUrlBuilder.clone().path(ServiceUrlConstants.REALM_INFO_PATH).build(getRealm()).toString();
+    }
+
+    /**
+     * @param authUrlBuilder absolute URI
+     */
+    protected void resolveNonBrowserUrls(KeycloakUriBuilder authUrlBuilder) {
+        if (log.isDebugEnabled()) {
+            log.debug("resolveNonBrowserUrls");
+        }
+
+        tokenUrl = authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_PATH).build(getRealm()).toString();
+        logoutUrl = KeycloakUriBuilder.fromUri(authUrlBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(getRealm()).toString());
+        accountUrl = authUrlBuilder.clone().path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH).build(getRealm()).toString();
+        registerNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_REGISTER_NODE_PATH).build(getRealm()).toString();
+        unregisterNodeUrl = authUrlBuilder.clone().path(ServiceUrlConstants.CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH).build(getRealm()).toString();
+    }
+
+    public RelativeUrlsUsed getRelativeUrls() {
+        return relativeUrls;
+    }
+
+    public String getRealmInfoUrl() {
+        return realmInfoUrl;
+    }
+
+    public KeycloakUriBuilder getAuthUrl() {
+        return authUrl;
+    }
+
+    public String getTokenUrl() {
+        return tokenUrl;
+    }
+
+    public KeycloakUriBuilder getLogoutUrl() {
+        return logoutUrl;
+    }
+
+    public String getAccountUrl() {
+        return accountUrl;
+    }
+
+    public String getRegisterNodeUrl() {
+        return registerNodeUrl;
+    }
+
+    public String getUnregisterNodeUrl() {
+        return unregisterNodeUrl;
+    }
+
+    public void setResourceName(String resourceName) {
+        this.resourceName = resourceName;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isEnableBasicAuth() {
+        return enableBasicAuth;
+    }
+
+    public void setEnableBasicAuth(boolean enableBasicAuth) {
+        this.enableBasicAuth = enableBasicAuth;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public Map<String, String> getResourceCredentials() {
+        return resourceCredentials;
+    }
+
+    public void setResourceCredentials(Map<String, String> resourceCredentials) {
+        this.resourceCredentials = resourceCredentials;
+    }
+
+    public HttpClient getClient() {
+        return client;
+    }
+
+    public void setClient(HttpClient client) {
+        this.client = client;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+    public SslRequired getSslRequired() {
+        return sslRequired;
+    }
+
+    public void setSslRequired(SslRequired sslRequired) {
+        this.sslRequired = sslRequired;
+    }
+
+    public TokenStore getTokenStore() {
+        return tokenStore;
+    }
+
+    public void setTokenStore(TokenStore tokenStore) {
+        this.tokenStore = tokenStore;
+    }
+
+    public String getStateCookieName() {
+        return stateCookieName;
+    }
+
+    public void setStateCookieName(String stateCookieName) {
+        this.stateCookieName = stateCookieName;
+    }
+
+    public boolean isUseResourceRoleMappings() {
+        return useResourceRoleMappings;
+    }
+
+    public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
+        this.useResourceRoleMappings = useResourceRoleMappings;
+    }
+
+    public boolean isCors() {
+        return cors;
+    }
+
+    public void setCors(boolean cors) {
+        this.cors = cors;
+    }
+
+    public int getCorsMaxAge() {
+        return corsMaxAge;
+    }
+
+    public void setCorsMaxAge(int corsMaxAge) {
+        this.corsMaxAge = corsMaxAge;
+    }
+
+    public String getCorsAllowedHeaders() {
+        return corsAllowedHeaders;
+    }
+
+    public void setCorsAllowedHeaders(String corsAllowedHeaders) {
+        this.corsAllowedHeaders = corsAllowedHeaders;
+    }
+
+    public String getCorsAllowedMethods() {
+        return corsAllowedMethods;
+    }
+
+    public void setCorsAllowedMethods(String corsAllowedMethods) {
+        this.corsAllowedMethods = corsAllowedMethods;
+    }
+
+    public boolean isExposeToken() {
+        return exposeToken;
+    }
+
+    public void setExposeToken(boolean exposeToken) {
+        this.exposeToken = exposeToken;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public boolean isAlwaysRefreshToken() {
+        return alwaysRefreshToken;
+    }
+
+    public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
+        this.alwaysRefreshToken = alwaysRefreshToken;
+    }
+
+    public boolean isRegisterNodeAtStartup() {
+        return registerNodeAtStartup;
+    }
+
+    public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
+        this.registerNodeAtStartup = registerNodeAtStartup;
+    }
+
+    public int getRegisterNodePeriod() {
+        return registerNodePeriod;
+    }
+
+    public void setRegisterNodePeriod(int registerNodePeriod) {
+        this.registerNodePeriod = registerNodePeriod;
+    }
+
+    public String getPrincipalAttribute() {
+        return principalAttribute;
+    }
+
+    public void setPrincipalAttribute(String principalAttribute) {
+        this.principalAttribute = principalAttribute;
+    }
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index be358aa..5ddc54b 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -1,115 +1,115 @@
-package org.keycloak.adapters;
-
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-import org.jboss.logging.Logger;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.enums.TokenStore;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.PemUtils;
-import org.keycloak.util.SystemPropertiesJsonParserFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.PublicKey;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakDeploymentBuilder {
-
-    private static final Logger log = Logger.getLogger(KeycloakDeploymentBuilder.class);
-
-    protected KeycloakDeployment deployment = new KeycloakDeployment();
-
-    protected KeycloakDeploymentBuilder() {
-    }
-
-
-    protected KeycloakDeployment internalBuild(AdapterConfig adapterConfig) {
-        if (adapterConfig.getRealm() == null) throw new RuntimeException("Must set 'realm' in config");
-        deployment.setRealm(adapterConfig.getRealm());
-        String resource = adapterConfig.getResource();
-        if (resource == null) throw new RuntimeException("Must set 'resource' in config");
-        deployment.setResourceName(resource);
-
-        String realmKeyPem = adapterConfig.getRealmKey();
-        if (realmKeyPem != null) {
-            PublicKey realmKey;
-            try {
-                realmKey = PemUtils.decodePublicKey(realmKeyPem);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-            deployment.setRealmKey(realmKey);
-        }
-        if (adapterConfig.getSslRequired() != null) {
-            deployment.setSslRequired(SslRequired.valueOf(adapterConfig.getSslRequired().toUpperCase()));
-        } else {
-            deployment.setSslRequired(SslRequired.EXTERNAL);
-        }
-        if (adapterConfig.getTokenStore() != null) {
-            deployment.setTokenStore(TokenStore.valueOf(adapterConfig.getTokenStore().toUpperCase()));
-        } else {
-            deployment.setTokenStore(TokenStore.SESSION);
-        }
-        if (adapterConfig.getPrincipalAttribute() != null) deployment.setPrincipalAttribute(adapterConfig.getPrincipalAttribute());
-        deployment.setResourceCredentials(adapterConfig.getCredentials());
-        deployment.setPublicClient(adapterConfig.isPublicClient());
-        deployment.setUseResourceRoleMappings(adapterConfig.isUseResourceRoleMappings());
-
-        deployment.setExposeToken(adapterConfig.isExposeToken());
-
-        if (adapterConfig.isCors()) {
-            deployment.setCors(true);
-            deployment.setCorsMaxAge(adapterConfig.getCorsMaxAge());
-            deployment.setCorsAllowedHeaders(adapterConfig.getCorsAllowedHeaders());
-            deployment.setCorsAllowedMethods(adapterConfig.getCorsAllowedMethods());
-        }
-
-        deployment.setBearerOnly(adapterConfig.isBearerOnly());
-        deployment.setEnableBasicAuth(adapterConfig.isEnableBasicAuth());
-        deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
-        deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
-        deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
-
-        if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
-            throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
-        }
-        if (realmKeyPem == null || !deployment.isBearerOnly() || deployment.isRegisterNodeAtStartup() || deployment.getRegisterNodePeriod() != -1) {
-            deployment.setClient(new HttpClientBuilder().build(adapterConfig));
-        }
-        if (adapterConfig.getAuthServerUrl() == null && (!deployment.isBearerOnly() || realmKeyPem == null)) {
-            throw new RuntimeException("You must specify auth-url");
-        }
-        deployment.setAuthServerBaseUrl(adapterConfig);
-
-        log.debug("Use authServerUrl: " + deployment.getAuthServerBaseUrl() + ", tokenUrl: " + deployment.getTokenUrl() + ", relativeUrls: " + deployment.getRelativeUrls());
-        return deployment;
-    }
-
-    public static KeycloakDeployment build(InputStream is) {
-        AdapterConfig adapterConfig = loadAdapterConfig(is);
-        return new KeycloakDeploymentBuilder().internalBuild(adapterConfig);
-    }
-
-    public static AdapterConfig loadAdapterConfig(InputStream is) {
-        ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
-        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
-        AdapterConfig adapterConfig;
-        try {
-            adapterConfig = mapper.readValue(is, AdapterConfig.class);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return adapterConfig;
-    }
-
-
-    public static KeycloakDeployment build(AdapterConfig adapterConfig) {
-        return new KeycloakDeploymentBuilder().internalBuild(adapterConfig);
-    }
-
-
-}
+package org.keycloak.adapters;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.jboss.logging.Logger;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.enums.TokenStore;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.PemUtils;
+import org.keycloak.util.SystemPropertiesJsonParserFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakDeploymentBuilder {
+
+    private static final Logger log = Logger.getLogger(KeycloakDeploymentBuilder.class);
+
+    protected KeycloakDeployment deployment = new KeycloakDeployment();
+
+    protected KeycloakDeploymentBuilder() {
+    }
+
+
+    protected KeycloakDeployment internalBuild(AdapterConfig adapterConfig) {
+        if (adapterConfig.getRealm() == null) throw new RuntimeException("Must set 'realm' in config");
+        deployment.setRealm(adapterConfig.getRealm());
+        String resource = adapterConfig.getResource();
+        if (resource == null) throw new RuntimeException("Must set 'resource' in config");
+        deployment.setResourceName(resource);
+
+        String realmKeyPem = adapterConfig.getRealmKey();
+        if (realmKeyPem != null) {
+            PublicKey realmKey;
+            try {
+                realmKey = PemUtils.decodePublicKey(realmKeyPem);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            deployment.setRealmKey(realmKey);
+        }
+        if (adapterConfig.getSslRequired() != null) {
+            deployment.setSslRequired(SslRequired.valueOf(adapterConfig.getSslRequired().toUpperCase()));
+        } else {
+            deployment.setSslRequired(SslRequired.EXTERNAL);
+        }
+        if (adapterConfig.getTokenStore() != null) {
+            deployment.setTokenStore(TokenStore.valueOf(adapterConfig.getTokenStore().toUpperCase()));
+        } else {
+            deployment.setTokenStore(TokenStore.SESSION);
+        }
+        if (adapterConfig.getPrincipalAttribute() != null) deployment.setPrincipalAttribute(adapterConfig.getPrincipalAttribute());
+        deployment.setResourceCredentials(adapterConfig.getCredentials());
+        deployment.setPublicClient(adapterConfig.isPublicClient());
+        deployment.setUseResourceRoleMappings(adapterConfig.isUseResourceRoleMappings());
+
+        deployment.setExposeToken(adapterConfig.isExposeToken());
+
+        if (adapterConfig.isCors()) {
+            deployment.setCors(true);
+            deployment.setCorsMaxAge(adapterConfig.getCorsMaxAge());
+            deployment.setCorsAllowedHeaders(adapterConfig.getCorsAllowedHeaders());
+            deployment.setCorsAllowedMethods(adapterConfig.getCorsAllowedMethods());
+        }
+
+        deployment.setBearerOnly(adapterConfig.isBearerOnly());
+        deployment.setEnableBasicAuth(adapterConfig.isEnableBasicAuth());
+        deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
+        deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
+        deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
+
+        if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
+            throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
+        }
+        if (realmKeyPem == null || !deployment.isBearerOnly() || deployment.isRegisterNodeAtStartup() || deployment.getRegisterNodePeriod() != -1) {
+            deployment.setClient(new HttpClientBuilder().build(adapterConfig));
+        }
+        if (adapterConfig.getAuthServerUrl() == null && (!deployment.isBearerOnly() || realmKeyPem == null)) {
+            throw new RuntimeException("You must specify auth-url");
+        }
+        deployment.setAuthServerBaseUrl(adapterConfig);
+
+        log.debug("Use authServerUrl: " + deployment.getAuthServerBaseUrl() + ", tokenUrl: " + deployment.getTokenUrl() + ", relativeUrls: " + deployment.getRelativeUrls());
+        return deployment;
+    }
+
+    public static KeycloakDeployment build(InputStream is) {
+        AdapterConfig adapterConfig = loadAdapterConfig(is);
+        return new KeycloakDeploymentBuilder().internalBuild(adapterConfig);
+    }
+
+    public static AdapterConfig loadAdapterConfig(InputStream is) {
+        ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
+        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
+        AdapterConfig adapterConfig;
+        try {
+            adapterConfig = mapper.readValue(is, AdapterConfig.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return adapterConfig;
+    }
+
+
+    public static KeycloakDeployment build(AdapterConfig adapterConfig) {
+        return new KeycloakDeploymentBuilder().internalBuild(adapterConfig);
+    }
+
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
index ea66837..aaab3a3 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
@@ -1,350 +1,350 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.VerificationException;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.enums.TokenStore;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.IDToken;
-import org.keycloak.util.KeycloakUriBuilder;
-import org.keycloak.util.UriUtils;
-
-import java.io.IOException;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OAuthRequestAuthenticator {
-    private static final Logger log = Logger.getLogger(OAuthRequestAuthenticator.class);
-    protected KeycloakDeployment deployment;
-    protected RequestAuthenticator reqAuthenticator;
-    protected int sslRedirectPort;
-    protected AdapterTokenStore tokenStore;
-    protected String tokenString;
-    protected String idTokenString;
-    protected IDToken idToken;
-    protected AccessToken token;
-    protected HttpFacade facade;
-    protected AuthChallenge challenge;
-    protected String refreshToken;
-    protected String strippedOauthParametersRequestUri;
-
-    public OAuthRequestAuthenticator(RequestAuthenticator requestAuthenticator, HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort, AdapterTokenStore tokenStore) {
-        this.reqAuthenticator = requestAuthenticator;
-        this.facade = facade;
-        this.deployment = deployment;
-        this.sslRedirectPort = sslRedirectPort;
-        this.tokenStore = tokenStore;
-    }
-
-    public AuthChallenge getChallenge() {
-        return challenge;
-    }
-
-    public String getTokenString() {
-        return tokenString;
-    }
-
-    public AccessToken getToken() {
-        return token;
-    }
-
-    public String getRefreshToken() {
-        return refreshToken;
-    }
-
-    public String getIdTokenString() {
-        return idTokenString;
-    }
-
-    public void setIdTokenString(String idTokenString) {
-        this.idTokenString = idTokenString;
-    }
-
-    public IDToken getIdToken() {
-        return idToken;
-    }
-
-    public void setIdToken(IDToken idToken) {
-        this.idToken = idToken;
-    }
-
-    public String getStrippedOauthParametersRequestUri() {
-        return strippedOauthParametersRequestUri;
-    }
-
-    public void setStrippedOauthParametersRequestUri(String strippedOauthParametersRequestUri) {
-        this.strippedOauthParametersRequestUri = strippedOauthParametersRequestUri;
-    }
-
-    protected String getRequestUrl() {
-        return facade.getRequest().getURI();
-    }
-
-    protected boolean isRequestSecure() {
-        return facade.getRequest().isSecure();
-    }
-
-    protected HttpFacade.Cookie getCookie(String cookieName) {
-        return facade.getRequest().getCookie(cookieName);
-    }
-
-    protected String getCookieValue(String cookieName) {
-        HttpFacade.Cookie cookie = getCookie(cookieName);
-        if (cookie == null) return null;
-        return cookie.getValue();
-    }
-
-    protected String getQueryParamValue(String paramName) {
-        return facade.getRequest().getQueryParamValue(paramName);
-    }
-
-    protected String getError() {
-        return getQueryParamValue(OAuth2Constants.ERROR);
-    }
-
-    protected String getCode() {
-        return getQueryParamValue(OAuth2Constants.CODE);
-    }
-
-    protected String getRedirectUri(String state) {
-        String url = getRequestUrl();
-        log.debugf("callback uri: %s", url);
-        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            int port = sslRedirectPort();
-            if (port < 0) {
-                // disabled?
-                return null;
-            }
-            KeycloakUriBuilder secureUrl = KeycloakUriBuilder.fromUri(url).scheme("https").port(-1);
-            if (port != 443) secureUrl.port(port);
-            url = secureUrl.build().toString();
-        }
-
-        String loginHint = getQueryParamValue("login_hint");
-        url = UriUtils.stripQueryParam(url,"login_hint");
-
-        String idpHint = getQueryParamValue(AdapterConstants.KC_IDP_HINT);
-        url = UriUtils.stripQueryParam(url, AdapterConstants.KC_IDP_HINT);
-
-        KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
-                .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
-                .queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
-                .queryParam(OAuth2Constants.REDIRECT_URI, url)
-                .queryParam(OAuth2Constants.STATE, state)
-                .queryParam("login", "true");
-        if(loginHint != null && loginHint.length() > 0){
-            redirectUriBuilder.queryParam("login_hint",loginHint);
-        }
-        if (idpHint != null && idpHint.length() > 0) {
-            redirectUriBuilder.queryParam(AdapterConstants.KC_IDP_HINT,idpHint);
-        }
-
-        return redirectUriBuilder.build().toString();
-    }
-
-    protected int sslRedirectPort() {
-        return sslRedirectPort;
-    }
-
-    protected static final AtomicLong counter = new AtomicLong();
-
-    protected String getStateCode() {
-        return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
-    }
-
-    protected AuthChallenge loginRedirect() {
-        final String state = getStateCode();
-        final String redirect = getRedirectUri(state);
-        if (redirect == null) {
-            return new AuthChallenge() {
-                @Override
-                public boolean challenge(HttpFacade exchange) {
-                    exchange.getResponse().setStatus(403);
-                    return true;
-                }
-
-                @Override
-                public boolean errorPage() {
-                    return true;
-                }
-            };
-        }
-        return new AuthChallenge() {
-
-            @Override
-            public boolean errorPage() {
-                return false;
-            }
-
-            @Override
-            public boolean challenge(HttpFacade exchange) {
-                tokenStore.saveRequest();
-                log.debug("Sending redirect to login page: " + redirect);
-                exchange.getResponse().setStatus(302);
-                exchange.getResponse().setCookie(deployment.getStateCookieName(), state, /* need to set path? */ null, null, -1, deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr()), false);
-                exchange.getResponse().setHeader("Location", redirect);
-                return true;
-            }
-        };
-    }
-
-    protected AuthChallenge checkStateCookie() {
-        HttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName());
-
-        if (stateCookie == null) {
-            log.warn("No state cookie");
-            return challenge(400);
-        }
-        // reset the cookie
-        log.debug("** reseting application state cookie");
-        facade.getResponse().resetCookie(deployment.getStateCookieName(), stateCookie.getPath());
-        String stateCookieValue = getCookieValue(deployment.getStateCookieName());
-
-        String state = getQueryParamValue(OAuth2Constants.STATE);
-        if (state == null) {
-            log.warn("state parameter was null");
-            return challenge(400);
-        }
-        if (!state.equals(stateCookieValue)) {
-            log.warn("state parameter invalid");
-            log.warn("cookie: " + stateCookieValue);
-            log.warn("queryParam: " + state);
-            return challenge(400);
-        }
-        return null;
-
-    }
-
-    public AuthOutcome authenticate() {
-        String code = getCode();
-        if (code == null) {
-            log.debug("there was no code");
-            String error = getError();
-            if (error != null) {
-                // todo how do we send a response?
-                log.warn("There was an error: " + error);
-                challenge = challenge(400);
-                return AuthOutcome.FAILED;
-            } else {
-                log.debug("redirecting to auth server");
-                challenge = loginRedirect();
-                return AuthOutcome.NOT_ATTEMPTED;
-            }
-        } else {
-            log.debug("there was a code, resolving");
-            challenge = resolveCode(code);
-            if (challenge != null) {
-                return AuthOutcome.FAILED;
-            }
-            return AuthOutcome.AUTHENTICATED;
-        }
-
-    }
-
-    protected AuthChallenge challenge(final int code) {
-        return new AuthChallenge() {
-            @Override
-            public boolean errorPage() {
-                return true;
-            }
-
-            @Override
-            public boolean challenge(HttpFacade exchange) {
-                exchange.getResponse().setStatus(code);
-                return true;
-            }
-        };
-    }
-
-    /**
-     * Start or continue the oauth login process.
-     * <p/>
-     * if code query parameter is not present, then browser is redirected to authUrl.  The redirect URL will be
-     * the URL of the current request.
-     * <p/>
-     * If code query parameter is present, then an access token is obtained by invoking a secure request to the codeUrl.
-     * If the access token is obtained, the browser is again redirected to the current request URL, but any OAuth
-     * protocol specific query parameters are removed.
-     *
-     * @return null if an access token was obtained, otherwise a challenge is returned
-     */
-    protected AuthChallenge resolveCode(String code) {
-        // abort if not HTTPS
-        if (!isRequestSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            log.error("Adapter requires SSL. Request: " + facade.getRequest().getURI());
-            return challenge(403);
-        }
-
-        log.debug("checking state cookie for after code");
-        AuthChallenge challenge = checkStateCookie();
-        if (challenge != null) return challenge;
-
-        AccessTokenResponse tokenResponse = null;
-        strippedOauthParametersRequestUri = stripOauthParametersFromRedirect();
-        try {
-            // For COOKIE store we don't have httpSessionId and single sign-out won't be available
-            String httpSessionId = deployment.getTokenStore() == TokenStore.SESSION ? reqAuthenticator.getHttpSessionId(true) : null;
-            tokenResponse = ServerRequest.invokeAccessCodeToToken(deployment, code, strippedOauthParametersRequestUri, httpSessionId);
-        } catch (ServerRequest.HttpFailure failure) {
-            log.error("failed to turn code into token");
-            log.error("status from server: " + failure.getStatus());
-            if (failure.getStatus() == 400 && failure.getError() != null) {
-                log.error("   " + failure.getError());
-            }
-            return challenge(403);
-
-        } catch (IOException e) {
-            log.error("failed to turn code into token", e);
-            return challenge(403);
-        }
-
-        tokenString = tokenResponse.getToken();
-        refreshToken = tokenResponse.getRefreshToken();
-        idTokenString = tokenResponse.getIdToken();
-        try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
-            if (idTokenString != null) {
-                JWSInput input = new JWSInput(idTokenString);
-                try {
-                    idToken = input.readJsonContent(IDToken.class);
-                } catch (IOException e) {
-                    throw new VerificationException();
-                }
-            }
-            log.debug("Token Verification succeeded!");
-        } catch (VerificationException e) {
-            log.error("failed verification of token: " + e.getMessage());
-            return challenge(403);
-        }
-        if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) {
-            deployment.setNotBefore(tokenResponse.getNotBeforePolicy());
-        }
-        if (token.getIssuedAt() < deployment.getNotBefore()) {
-            log.error("Stale token");
-            return challenge(403);
-        }
-        log.debug("successful authenticated");
-        return null;
-    }
-
-    /**
-     * strip out unwanted query parameters and redirect so bookmarks don't retain oauth protocol bits
-     */
-    protected String stripOauthParametersFromRedirect() {
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(facade.getRequest().getURI())
-                .replaceQueryParam(OAuth2Constants.CODE, null)
-                .replaceQueryParam(OAuth2Constants.STATE, null);
-        return builder.build().toString();
-    }
-
-
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.enums.TokenStore;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
+import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.UriUtils;
+
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OAuthRequestAuthenticator {
+    private static final Logger log = Logger.getLogger(OAuthRequestAuthenticator.class);
+    protected KeycloakDeployment deployment;
+    protected RequestAuthenticator reqAuthenticator;
+    protected int sslRedirectPort;
+    protected AdapterTokenStore tokenStore;
+    protected String tokenString;
+    protected String idTokenString;
+    protected IDToken idToken;
+    protected AccessToken token;
+    protected HttpFacade facade;
+    protected AuthChallenge challenge;
+    protected String refreshToken;
+    protected String strippedOauthParametersRequestUri;
+
+    public OAuthRequestAuthenticator(RequestAuthenticator requestAuthenticator, HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort, AdapterTokenStore tokenStore) {
+        this.reqAuthenticator = requestAuthenticator;
+        this.facade = facade;
+        this.deployment = deployment;
+        this.sslRedirectPort = sslRedirectPort;
+        this.tokenStore = tokenStore;
+    }
+
+    public AuthChallenge getChallenge() {
+        return challenge;
+    }
+
+    public String getTokenString() {
+        return tokenString;
+    }
+
+    public AccessToken getToken() {
+        return token;
+    }
+
+    public String getRefreshToken() {
+        return refreshToken;
+    }
+
+    public String getIdTokenString() {
+        return idTokenString;
+    }
+
+    public void setIdTokenString(String idTokenString) {
+        this.idTokenString = idTokenString;
+    }
+
+    public IDToken getIdToken() {
+        return idToken;
+    }
+
+    public void setIdToken(IDToken idToken) {
+        this.idToken = idToken;
+    }
+
+    public String getStrippedOauthParametersRequestUri() {
+        return strippedOauthParametersRequestUri;
+    }
+
+    public void setStrippedOauthParametersRequestUri(String strippedOauthParametersRequestUri) {
+        this.strippedOauthParametersRequestUri = strippedOauthParametersRequestUri;
+    }
+
+    protected String getRequestUrl() {
+        return facade.getRequest().getURI();
+    }
+
+    protected boolean isRequestSecure() {
+        return facade.getRequest().isSecure();
+    }
+
+    protected HttpFacade.Cookie getCookie(String cookieName) {
+        return facade.getRequest().getCookie(cookieName);
+    }
+
+    protected String getCookieValue(String cookieName) {
+        HttpFacade.Cookie cookie = getCookie(cookieName);
+        if (cookie == null) return null;
+        return cookie.getValue();
+    }
+
+    protected String getQueryParamValue(String paramName) {
+        return facade.getRequest().getQueryParamValue(paramName);
+    }
+
+    protected String getError() {
+        return getQueryParamValue(OAuth2Constants.ERROR);
+    }
+
+    protected String getCode() {
+        return getQueryParamValue(OAuth2Constants.CODE);
+    }
+
+    protected String getRedirectUri(String state) {
+        String url = getRequestUrl();
+        log.debugf("callback uri: %s", url);
+        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            int port = sslRedirectPort();
+            if (port < 0) {
+                // disabled?
+                return null;
+            }
+            KeycloakUriBuilder secureUrl = KeycloakUriBuilder.fromUri(url).scheme("https").port(-1);
+            if (port != 443) secureUrl.port(port);
+            url = secureUrl.build().toString();
+        }
+
+        String loginHint = getQueryParamValue("login_hint");
+        url = UriUtils.stripQueryParam(url,"login_hint");
+
+        String idpHint = getQueryParamValue(AdapterConstants.KC_IDP_HINT);
+        url = UriUtils.stripQueryParam(url, AdapterConstants.KC_IDP_HINT);
+
+        KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
+                .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
+                .queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
+                .queryParam(OAuth2Constants.REDIRECT_URI, url)
+                .queryParam(OAuth2Constants.STATE, state)
+                .queryParam("login", "true");
+        if(loginHint != null && loginHint.length() > 0){
+            redirectUriBuilder.queryParam("login_hint",loginHint);
+        }
+        if (idpHint != null && idpHint.length() > 0) {
+            redirectUriBuilder.queryParam(AdapterConstants.KC_IDP_HINT,idpHint);
+        }
+
+        return redirectUriBuilder.build().toString();
+    }
+
+    protected int sslRedirectPort() {
+        return sslRedirectPort;
+    }
+
+    protected static final AtomicLong counter = new AtomicLong();
+
+    protected String getStateCode() {
+        return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
+    }
+
+    protected AuthChallenge loginRedirect() {
+        final String state = getStateCode();
+        final String redirect = getRedirectUri(state);
+        if (redirect == null) {
+            return new AuthChallenge() {
+                @Override
+                public boolean challenge(HttpFacade exchange) {
+                    exchange.getResponse().setStatus(403);
+                    return true;
+                }
+
+                @Override
+                public boolean errorPage() {
+                    return true;
+                }
+            };
+        }
+        return new AuthChallenge() {
+
+            @Override
+            public boolean errorPage() {
+                return false;
+            }
+
+            @Override
+            public boolean challenge(HttpFacade exchange) {
+                tokenStore.saveRequest();
+                log.debug("Sending redirect to login page: " + redirect);
+                exchange.getResponse().setStatus(302);
+                exchange.getResponse().setCookie(deployment.getStateCookieName(), state, /* need to set path? */ null, null, -1, deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr()), false);
+                exchange.getResponse().setHeader("Location", redirect);
+                return true;
+            }
+        };
+    }
+
+    protected AuthChallenge checkStateCookie() {
+        HttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName());
+
+        if (stateCookie == null) {
+            log.warn("No state cookie");
+            return challenge(400);
+        }
+        // reset the cookie
+        log.debug("** reseting application state cookie");
+        facade.getResponse().resetCookie(deployment.getStateCookieName(), stateCookie.getPath());
+        String stateCookieValue = getCookieValue(deployment.getStateCookieName());
+
+        String state = getQueryParamValue(OAuth2Constants.STATE);
+        if (state == null) {
+            log.warn("state parameter was null");
+            return challenge(400);
+        }
+        if (!state.equals(stateCookieValue)) {
+            log.warn("state parameter invalid");
+            log.warn("cookie: " + stateCookieValue);
+            log.warn("queryParam: " + state);
+            return challenge(400);
+        }
+        return null;
+
+    }
+
+    public AuthOutcome authenticate() {
+        String code = getCode();
+        if (code == null) {
+            log.debug("there was no code");
+            String error = getError();
+            if (error != null) {
+                // todo how do we send a response?
+                log.warn("There was an error: " + error);
+                challenge = challenge(400);
+                return AuthOutcome.FAILED;
+            } else {
+                log.debug("redirecting to auth server");
+                challenge = loginRedirect();
+                return AuthOutcome.NOT_ATTEMPTED;
+            }
+        } else {
+            log.debug("there was a code, resolving");
+            challenge = resolveCode(code);
+            if (challenge != null) {
+                return AuthOutcome.FAILED;
+            }
+            return AuthOutcome.AUTHENTICATED;
+        }
+
+    }
+
+    protected AuthChallenge challenge(final int code) {
+        return new AuthChallenge() {
+            @Override
+            public boolean errorPage() {
+                return true;
+            }
+
+            @Override
+            public boolean challenge(HttpFacade exchange) {
+                exchange.getResponse().setStatus(code);
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Start or continue the oauth login process.
+     * <p/>
+     * if code query parameter is not present, then browser is redirected to authUrl.  The redirect URL will be
+     * the URL of the current request.
+     * <p/>
+     * If code query parameter is present, then an access token is obtained by invoking a secure request to the codeUrl.
+     * If the access token is obtained, the browser is again redirected to the current request URL, but any OAuth
+     * protocol specific query parameters are removed.
+     *
+     * @return null if an access token was obtained, otherwise a challenge is returned
+     */
+    protected AuthChallenge resolveCode(String code) {
+        // abort if not HTTPS
+        if (!isRequestSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            log.error("Adapter requires SSL. Request: " + facade.getRequest().getURI());
+            return challenge(403);
+        }
+
+        log.debug("checking state cookie for after code");
+        AuthChallenge challenge = checkStateCookie();
+        if (challenge != null) return challenge;
+
+        AccessTokenResponse tokenResponse = null;
+        strippedOauthParametersRequestUri = stripOauthParametersFromRedirect();
+        try {
+            // For COOKIE store we don't have httpSessionId and single sign-out won't be available
+            String httpSessionId = deployment.getTokenStore() == TokenStore.SESSION ? reqAuthenticator.getHttpSessionId(true) : null;
+            tokenResponse = ServerRequest.invokeAccessCodeToToken(deployment, code, strippedOauthParametersRequestUri, httpSessionId);
+        } catch (ServerRequest.HttpFailure failure) {
+            log.error("failed to turn code into token");
+            log.error("status from server: " + failure.getStatus());
+            if (failure.getStatus() == 400 && failure.getError() != null) {
+                log.error("   " + failure.getError());
+            }
+            return challenge(403);
+
+        } catch (IOException e) {
+            log.error("failed to turn code into token", e);
+            return challenge(403);
+        }
+
+        tokenString = tokenResponse.getToken();
+        refreshToken = tokenResponse.getRefreshToken();
+        idTokenString = tokenResponse.getIdToken();
+        try {
+            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+            if (idTokenString != null) {
+                JWSInput input = new JWSInput(idTokenString);
+                try {
+                    idToken = input.readJsonContent(IDToken.class);
+                } catch (IOException e) {
+                    throw new VerificationException();
+                }
+            }
+            log.debug("Token Verification succeeded!");
+        } catch (VerificationException e) {
+            log.error("failed verification of token: " + e.getMessage());
+            return challenge(403);
+        }
+        if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) {
+            deployment.setNotBefore(tokenResponse.getNotBeforePolicy());
+        }
+        if (token.getIssuedAt() < deployment.getNotBefore()) {
+            log.error("Stale token");
+            return challenge(403);
+        }
+        log.debug("successful authenticated");
+        return null;
+    }
+
+    /**
+     * strip out unwanted query parameters and redirect so bookmarks don't retain oauth protocol bits
+     */
+    protected String stripOauthParametersFromRedirect() {
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(facade.getRequest().getURI())
+                .replaceQueryParam(OAuth2Constants.CODE, null)
+                .replaceQueryParam(OAuth2Constants.STATE, null);
+        return builder.build().toString();
+    }
+
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
index aff38dc..cd5455c 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
@@ -1,224 +1,224 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Version;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.representations.adapters.action.AdminAction;
-import org.keycloak.representations.adapters.action.LogoutAction;
-import org.keycloak.representations.adapters.action.PushNotBeforeAction;
-import org.keycloak.representations.adapters.action.TestAvailabilityAction;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.StreamUtil;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class PreAuthActionsHandler {
-
-    private static final Logger log = Logger.getLogger(PreAuthActionsHandler.class);
-
-    protected UserSessionManagement userSessionManagement;
-    protected AdapterDeploymentContext deploymentContext;
-    protected KeycloakDeployment deployment;
-    protected HttpFacade facade;
-
-    public PreAuthActionsHandler(UserSessionManagement userSessionManagement, AdapterDeploymentContext deploymentContext, HttpFacade facade) {
-        this.userSessionManagement = userSessionManagement;
-        this.deploymentContext = deploymentContext;
-        this.facade = facade;
-    }
-
-    protected boolean resolveDeployment() {
-        deployment = deploymentContext.resolveDeployment(facade);
-        if (!deployment.isConfigured()) {
-            log.warn("can't take request, adapter not configured");
-            facade.getResponse().sendError(403, "adapter not configured");
-            return false;
-        }
-        return true;
-    }
-
-    public boolean handleRequest() {
-        String requestUri = facade.getRequest().getURI();
-        log.debugv("adminRequest {0}", requestUri);
-        if (preflightCors()) {
-            return true;
-        }
-        if (requestUri.endsWith(AdapterConstants.K_LOGOUT)) {
-            if (!resolveDeployment()) return true;
-            handleLogout();
-            return true;
-        } else if (requestUri.endsWith(AdapterConstants.K_PUSH_NOT_BEFORE)) {
-            if (!resolveDeployment()) return true;
-            handlePushNotBefore();
-            return true;
-        } else if (requestUri.endsWith(AdapterConstants.K_VERSION)) {
-            handleVersion();
-            return true;
-        } else if (requestUri.endsWith(AdapterConstants.K_TEST_AVAILABLE)) {
-            if (!resolveDeployment()) return true;
-            handleTestAvailable();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean preflightCors() {
-        // don't need to resolve deployment on cors requests.  Just need to know local cors config.
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (!deployment.isCors()) return false;
-        log.debugv("checkCorsPreflight {0}", facade.getRequest().getURI());
-        if (!facade.getRequest().getMethod().equalsIgnoreCase("OPTIONS")) {
-            return false;
-        }
-        if (facade.getRequest().getHeader(CorsHeaders.ORIGIN) == null) {
-            log.debug("checkCorsPreflight: no origin header");
-            return false;
-        }
-        log.debug("Preflight request returning");
-        facade.getResponse().setStatus(200);
-        String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
-        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
-        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
-        String requestMethods = facade.getRequest().getHeader(CorsHeaders.ACCESS_CONTROL_REQUEST_METHOD);
-        if (requestMethods != null) {
-            if (deployment.getCorsAllowedMethods() != null) {
-                requestMethods = deployment.getCorsAllowedMethods();
-            }
-            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethods);
-        }
-        String allowHeaders = facade.getRequest().getHeader(CorsHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
-        if (allowHeaders != null) {
-            if (deployment.getCorsAllowedHeaders() != null) {
-                allowHeaders = deployment.getCorsAllowedHeaders();
-            }
-            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_HEADERS, allowHeaders);
-        }
-        if (deployment.getCorsMaxAge() > -1) {
-            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_MAX_AGE, Integer.toString(deployment.getCorsMaxAge()));
-        }
-        return true;
-    }
-
-    protected void handleLogout()  {
-        if (log.isTraceEnabled()) {
-            log.trace("K_LOGOUT sent");
-        }
-        try {
-            JWSInput token = verifyAdminRequest();
-            if (token == null) {
-                return;
-            }
-            LogoutAction action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
-            if (!validateAction(action)) return;
-            if (action.getAdapterSessionIds() != null) {
-                userSessionManagement.logoutHttpSessions(action.getAdapterSessionIds());
-            } else {
-                log.debugf("logout of all sessions for application '%s'", action.getResource());
-                if (action.getNotBefore() > deployment.getNotBefore()) {
-                    deployment.setNotBefore(action.getNotBefore());
-                }
-                userSessionManagement.logoutAll();
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-
-    protected void handlePushNotBefore()  {
-        if (log.isTraceEnabled()) {
-            log.trace("K_PUSH_NOT_BEFORE sent");
-        }
-        try {
-            JWSInput token = verifyAdminRequest();
-            if (token == null) {
-                return;
-            }
-            PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class);
-            if (!validateAction(action)) return;
-            deployment.setNotBefore(action.getNotBefore());
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected void handleTestAvailable()  {
-        if (log.isTraceEnabled()) {
-            log.trace("K_TEST_AVAILABLE sent");
-        }
-        try {
-            JWSInput token = verifyAdminRequest();
-            if (token == null) {
-                return;
-            }
-            TestAvailabilityAction action = JsonSerialization.readValue(token.getContent(), TestAvailabilityAction.class);
-            validateAction(action);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected JWSInput verifyAdminRequest() throws Exception {
-        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            log.warn("SSL is required for adapter admin action");
-            facade.getResponse().sendError(403, "ssl required");
-            return null;
-        }
-        String token = StreamUtil.readString(facade.getRequest().getInputStream());
-        if (token == null) {
-            log.warn("admin request failed, no token");
-            facade.getResponse().sendError(403, "no token");
-            return null;
-        }
-
-        JWSInput input = new JWSInput(token);
-        boolean verified = false;
-        try {
-            verified = RSAProvider.verify(input, deployment.getRealmKey());
-        } catch (Exception ignore) {
-        }
-        if (!verified) {
-            log.warn("admin request failed, unable to verify token");
-            facade.getResponse().sendError(403, "no token");
-            return null;
-        }
-        return input;
-    }
-
-
-    protected boolean validateAction(AdminAction action)  {
-        if (!action.validate()) {
-            log.warn("admin request failed, not validated" + action.getAction());
-            facade.getResponse().sendError(400, "Not validated");
-            return false;
-        }
-        if (action.isExpired()) {
-            log.warn("admin request failed, expired token");
-            facade.getResponse().sendError(400, "Expired token");
-            return false;
-        }
-        if (!deployment.getResourceName().equals(action.getResource())) {
-            log.warn("Resource name does not match");
-            facade.getResponse().sendError(400, "Resource name does not match");
-            return false;
-
-        }
-        return true;
-    }
-
-    protected void handleVersion()  {
-        try {
-            facade.getResponse().setStatus(200);
-            facade.getResponse().setHeader("Content-Type", "application/json");
-            JsonSerialization.writeValueToStream(facade.getResponse().getOutputStream(), Version.SINGLETON);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Version;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.representations.adapters.action.AdminAction;
+import org.keycloak.representations.adapters.action.LogoutAction;
+import org.keycloak.representations.adapters.action.PushNotBeforeAction;
+import org.keycloak.representations.adapters.action.TestAvailabilityAction;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.StreamUtil;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class PreAuthActionsHandler {
+
+    private static final Logger log = Logger.getLogger(PreAuthActionsHandler.class);
+
+    protected UserSessionManagement userSessionManagement;
+    protected AdapterDeploymentContext deploymentContext;
+    protected KeycloakDeployment deployment;
+    protected HttpFacade facade;
+
+    public PreAuthActionsHandler(UserSessionManagement userSessionManagement, AdapterDeploymentContext deploymentContext, HttpFacade facade) {
+        this.userSessionManagement = userSessionManagement;
+        this.deploymentContext = deploymentContext;
+        this.facade = facade;
+    }
+
+    protected boolean resolveDeployment() {
+        deployment = deploymentContext.resolveDeployment(facade);
+        if (!deployment.isConfigured()) {
+            log.warn("can't take request, adapter not configured");
+            facade.getResponse().sendError(403, "adapter not configured");
+            return false;
+        }
+        return true;
+    }
+
+    public boolean handleRequest() {
+        String requestUri = facade.getRequest().getURI();
+        log.debugv("adminRequest {0}", requestUri);
+        if (preflightCors()) {
+            return true;
+        }
+        if (requestUri.endsWith(AdapterConstants.K_LOGOUT)) {
+            if (!resolveDeployment()) return true;
+            handleLogout();
+            return true;
+        } else if (requestUri.endsWith(AdapterConstants.K_PUSH_NOT_BEFORE)) {
+            if (!resolveDeployment()) return true;
+            handlePushNotBefore();
+            return true;
+        } else if (requestUri.endsWith(AdapterConstants.K_VERSION)) {
+            handleVersion();
+            return true;
+        } else if (requestUri.endsWith(AdapterConstants.K_TEST_AVAILABLE)) {
+            if (!resolveDeployment()) return true;
+            handleTestAvailable();
+            return true;
+        }
+        return false;
+    }
+
+    public boolean preflightCors() {
+        // don't need to resolve deployment on cors requests.  Just need to know local cors config.
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (!deployment.isCors()) return false;
+        log.debugv("checkCorsPreflight {0}", facade.getRequest().getURI());
+        if (!facade.getRequest().getMethod().equalsIgnoreCase("OPTIONS")) {
+            return false;
+        }
+        if (facade.getRequest().getHeader(CorsHeaders.ORIGIN) == null) {
+            log.debug("checkCorsPreflight: no origin header");
+            return false;
+        }
+        log.debug("Preflight request returning");
+        facade.getResponse().setStatus(200);
+        String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
+        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
+        String requestMethods = facade.getRequest().getHeader(CorsHeaders.ACCESS_CONTROL_REQUEST_METHOD);
+        if (requestMethods != null) {
+            if (deployment.getCorsAllowedMethods() != null) {
+                requestMethods = deployment.getCorsAllowedMethods();
+            }
+            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethods);
+        }
+        String allowHeaders = facade.getRequest().getHeader(CorsHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
+        if (allowHeaders != null) {
+            if (deployment.getCorsAllowedHeaders() != null) {
+                allowHeaders = deployment.getCorsAllowedHeaders();
+            }
+            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_HEADERS, allowHeaders);
+        }
+        if (deployment.getCorsMaxAge() > -1) {
+            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_MAX_AGE, Integer.toString(deployment.getCorsMaxAge()));
+        }
+        return true;
+    }
+
+    protected void handleLogout()  {
+        if (log.isTraceEnabled()) {
+            log.trace("K_LOGOUT sent");
+        }
+        try {
+            JWSInput token = verifyAdminRequest();
+            if (token == null) {
+                return;
+            }
+            LogoutAction action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
+            if (!validateAction(action)) return;
+            if (action.getAdapterSessionIds() != null) {
+                userSessionManagement.logoutHttpSessions(action.getAdapterSessionIds());
+            } else {
+                log.debugf("logout of all sessions for application '%s'", action.getResource());
+                if (action.getNotBefore() > deployment.getNotBefore()) {
+                    deployment.setNotBefore(action.getNotBefore());
+                }
+                userSessionManagement.logoutAll();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+
+    protected void handlePushNotBefore()  {
+        if (log.isTraceEnabled()) {
+            log.trace("K_PUSH_NOT_BEFORE sent");
+        }
+        try {
+            JWSInput token = verifyAdminRequest();
+            if (token == null) {
+                return;
+            }
+            PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class);
+            if (!validateAction(action)) return;
+            deployment.setNotBefore(action.getNotBefore());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected void handleTestAvailable()  {
+        if (log.isTraceEnabled()) {
+            log.trace("K_TEST_AVAILABLE sent");
+        }
+        try {
+            JWSInput token = verifyAdminRequest();
+            if (token == null) {
+                return;
+            }
+            TestAvailabilityAction action = JsonSerialization.readValue(token.getContent(), TestAvailabilityAction.class);
+            validateAction(action);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected JWSInput verifyAdminRequest() throws Exception {
+        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            log.warn("SSL is required for adapter admin action");
+            facade.getResponse().sendError(403, "ssl required");
+            return null;
+        }
+        String token = StreamUtil.readString(facade.getRequest().getInputStream());
+        if (token == null) {
+            log.warn("admin request failed, no token");
+            facade.getResponse().sendError(403, "no token");
+            return null;
+        }
+
+        JWSInput input = new JWSInput(token);
+        boolean verified = false;
+        try {
+            verified = RSAProvider.verify(input, deployment.getRealmKey());
+        } catch (Exception ignore) {
+        }
+        if (!verified) {
+            log.warn("admin request failed, unable to verify token");
+            facade.getResponse().sendError(403, "no token");
+            return null;
+        }
+        return input;
+    }
+
+
+    protected boolean validateAction(AdminAction action)  {
+        if (!action.validate()) {
+            log.warn("admin request failed, not validated" + action.getAction());
+            facade.getResponse().sendError(400, "Not validated");
+            return false;
+        }
+        if (action.isExpired()) {
+            log.warn("admin request failed, expired token");
+            facade.getResponse().sendError(400, "Expired token");
+            return false;
+        }
+        if (!deployment.getResourceName().equals(action.getResource())) {
+            log.warn("Resource name does not match");
+            facade.getResponse().sendError(400, "Resource name does not match");
+            return false;
+
+        }
+        return true;
+    }
+
+    protected void handleVersion()  {
+        try {
+            facade.getResponse().setStatus(200);
+            facade.getResponse().setHeader("Content-Type", "application/json");
+            JsonSerialization.writeValueToStream(facade.getResponse().getOutputStream(), Version.SINGLETON);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
index 342ee35..52668de 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java
@@ -1,125 +1,125 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.VerificationException;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.IDToken;
-
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext {
-
-    protected static Logger log = Logger.getLogger(RefreshableKeycloakSecurityContext.class);
-
-    protected transient KeycloakDeployment deployment;
-    protected transient AdapterTokenStore tokenStore;
-    protected String refreshToken;
-
-    public RefreshableKeycloakSecurityContext() {
-    }
-
-    public RefreshableKeycloakSecurityContext(KeycloakDeployment deployment, AdapterTokenStore tokenStore, String tokenString, AccessToken token, String idTokenString, IDToken idToken, String refreshToken) {
-        super(tokenString, token, idTokenString, idToken);
-        this.deployment = deployment;
-        this.tokenStore = tokenStore;
-        this.refreshToken = refreshToken;
-    }
-
-    @Override
-    public AccessToken getToken() {
-        refreshExpiredToken(true);
-        return super.getToken();
-    }
-
-    @Override
-    public String getTokenString() {
-        refreshExpiredToken(true);
-        return super.getTokenString();
-    }
-
-    public String getRefreshToken() {
-        return refreshToken;
-    }
-
-    public void logout(KeycloakDeployment deployment) {
-        try {
-            ServerRequest.invokeLogout(deployment, refreshToken);
-        } catch (Exception e) {
-            log.error("failed to invoke remote logout", e);
-        }
-    }
-
-    public boolean isActive() {
-        return this.token.isActive() && this.token.getIssuedAt() > deployment.getNotBefore();
-    }
-
-    public KeycloakDeployment getDeployment() {
-        return deployment;
-    }
-
-    public void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
-        this.deployment = deployment;
-        this.tokenStore = tokenStore;
-    }
-
-    /**
-     * @param checkActive if true, then we won't send refresh request if current accessToken is still active.
-     * @return true if accessToken is active or was successfully refreshed
-     */
-    public boolean refreshExpiredToken(boolean checkActive) {
-        if (checkActive) {
-            if (log.isTraceEnabled()) {
-                log.trace("checking whether to refresh.");
-            }
-            if (isActive()) return true;
-        }
-
-        if (this.deployment == null || refreshToken == null) return false; // Might be serialized in HttpSession?
-
-        if (!this.getRealm().equals(this.deployment.getRealm())) {
-            // this should not happen, but let's check it anyway
-            return false;
-        }
-
-        if (log.isTraceEnabled()) {
-            log.trace("Doing refresh");
-        }
-        AccessTokenResponse response = null;
-        try {
-            response = ServerRequest.invokeRefresh(deployment, refreshToken);
-        } catch (IOException e) {
-            log.error("Refresh token failure", e);
-            return false;
-        } catch (ServerRequest.HttpFailure httpFailure) {
-            log.error("Refresh token failure status: " + httpFailure.getStatus() + " " + httpFailure.getError());
-            return false;
-        }
-        if (log.isTraceEnabled()) {
-            log.trace("received refresh response");
-        }
-        String tokenString = response.getToken();
-        AccessToken token = null;
-        try {
-            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
-            log.debug("Token Verification succeeded!");
-        } catch (VerificationException e) {
-            log.error("failed verification of token");
-        }
-        if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
-            deployment.setNotBefore(response.getNotBeforePolicy());
-        }
-
-        this.token = token;
-        this.refreshToken = response.getRefreshToken();
-        this.tokenString = tokenString;
-        tokenStore.refreshCallback(this);
-        return true;
-    }
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext {
+
+    protected static Logger log = Logger.getLogger(RefreshableKeycloakSecurityContext.class);
+
+    protected transient KeycloakDeployment deployment;
+    protected transient AdapterTokenStore tokenStore;
+    protected String refreshToken;
+
+    public RefreshableKeycloakSecurityContext() {
+    }
+
+    public RefreshableKeycloakSecurityContext(KeycloakDeployment deployment, AdapterTokenStore tokenStore, String tokenString, AccessToken token, String idTokenString, IDToken idToken, String refreshToken) {
+        super(tokenString, token, idTokenString, idToken);
+        this.deployment = deployment;
+        this.tokenStore = tokenStore;
+        this.refreshToken = refreshToken;
+    }
+
+    @Override
+    public AccessToken getToken() {
+        refreshExpiredToken(true);
+        return super.getToken();
+    }
+
+    @Override
+    public String getTokenString() {
+        refreshExpiredToken(true);
+        return super.getTokenString();
+    }
+
+    public String getRefreshToken() {
+        return refreshToken;
+    }
+
+    public void logout(KeycloakDeployment deployment) {
+        try {
+            ServerRequest.invokeLogout(deployment, refreshToken);
+        } catch (Exception e) {
+            log.error("failed to invoke remote logout", e);
+        }
+    }
+
+    public boolean isActive() {
+        return this.token.isActive() && this.token.getIssuedAt() > deployment.getNotBefore();
+    }
+
+    public KeycloakDeployment getDeployment() {
+        return deployment;
+    }
+
+    public void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+        this.deployment = deployment;
+        this.tokenStore = tokenStore;
+    }
+
+    /**
+     * @param checkActive if true, then we won't send refresh request if current accessToken is still active.
+     * @return true if accessToken is active or was successfully refreshed
+     */
+    public boolean refreshExpiredToken(boolean checkActive) {
+        if (checkActive) {
+            if (log.isTraceEnabled()) {
+                log.trace("checking whether to refresh.");
+            }
+            if (isActive()) return true;
+        }
+
+        if (this.deployment == null || refreshToken == null) return false; // Might be serialized in HttpSession?
+
+        if (!this.getRealm().equals(this.deployment.getRealm())) {
+            // this should not happen, but let's check it anyway
+            return false;
+        }
+
+        if (log.isTraceEnabled()) {
+            log.trace("Doing refresh");
+        }
+        AccessTokenResponse response = null;
+        try {
+            response = ServerRequest.invokeRefresh(deployment, refreshToken);
+        } catch (IOException e) {
+            log.error("Refresh token failure", e);
+            return false;
+        } catch (ServerRequest.HttpFailure httpFailure) {
+            log.error("Refresh token failure status: " + httpFailure.getStatus() + " " + httpFailure.getError());
+            return false;
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("received refresh response");
+        }
+        String tokenString = response.getToken();
+        AccessToken token = null;
+        try {
+            token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealmInfoUrl());
+            log.debug("Token Verification succeeded!");
+        } catch (VerificationException e) {
+            log.error("failed verification of token");
+        }
+        if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
+            deployment.setNotBefore(response.getNotBeforePolicy());
+        }
+
+        this.token = token;
+        this.refreshToken = response.getRefreshToken();
+        this.tokenString = tokenString;
+        tokenStore.refreshCallback(this);
+        return true;
+    }
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
index bd853da..624c682 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
@@ -1,147 +1,147 @@
-package org.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakPrincipal;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class RequestAuthenticator {
-    protected static Logger log = Logger.getLogger(RequestAuthenticator.class);
-
-    protected HttpFacade facade;
-    protected KeycloakDeployment deployment;
-    protected AdapterTokenStore tokenStore;
-    protected AuthChallenge challenge;
-    protected int sslRedirectPort;
-
-    public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort) {
-        this.facade = facade;
-        this.deployment = deployment;
-        this.tokenStore = tokenStore;
-        this.sslRedirectPort = sslRedirectPort;
-    }
-
-    public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment) {
-        this.facade = facade;
-        this.deployment = deployment;
-    }
-
-    public AuthChallenge getChallenge() {
-        return challenge;
-    }
-
-    public AuthOutcome authenticate() {
-        if (log.isTraceEnabled()) {
-            log.trace("--> authenticate()");
-        }
-
-        BearerTokenRequestAuthenticator bearer = createBearerTokenAuthenticator();
-        if (log.isTraceEnabled()) {
-            log.trace("try bearer");
-        }
-        
-        AuthOutcome outcome = bearer.authenticate(facade);
-        if (outcome == AuthOutcome.FAILED) {
-            challenge = bearer.getChallenge();
-            log.debug("Bearer FAILED");
-            return AuthOutcome.FAILED;
-        } else if (outcome == AuthOutcome.AUTHENTICATED) {
-            if (verifySSL()) return AuthOutcome.FAILED;
-            completeAuthentication(bearer, "KEYCLOAK");
-            log.debug("Bearer AUTHENTICATED");
-            return AuthOutcome.AUTHENTICATED;
-        } else if (deployment.isBearerOnly()) {
-            challenge = bearer.getChallenge();
-            log.debug("NOT_ATTEMPTED: bearer only");
-            return AuthOutcome.NOT_ATTEMPTED;
-        }
-
-        if (deployment.isEnableBasicAuth()) {
-            BasicAuthRequestAuthenticator basicAuth = createBasicAuthAuthenticator();
-            if (log.isTraceEnabled()) {
-                log.trace("try basic auth");
-            }
-    
-            outcome = basicAuth.authenticate(facade);
-            if (outcome == AuthOutcome.FAILED) {
-                challenge = basicAuth.getChallenge();
-                log.debug("BasicAuth FAILED");
-                return AuthOutcome.FAILED;
-            } else if (outcome == AuthOutcome.AUTHENTICATED) {
-                log.debug("BasicAuth AUTHENTICATED");
-                completeAuthentication(basicAuth, "BASIC");
-                return AuthOutcome.AUTHENTICATED;
-            }
-        }
-
-        if (log.isTraceEnabled()) {
-            log.trace("try oauth");
-        }
-
-        if (tokenStore.isCached(this)) {
-            if (verifySSL()) return AuthOutcome.FAILED;
-            log.debug("AUTHENTICATED: was cached");
-            return AuthOutcome.AUTHENTICATED;
-        }
-
-        OAuthRequestAuthenticator oauth = createOAuthAuthenticator();
-        outcome = oauth.authenticate();
-        if (outcome == AuthOutcome.FAILED) {
-            challenge = oauth.getChallenge();
-            return AuthOutcome.FAILED;
-        } else if (outcome == AuthOutcome.NOT_ATTEMPTED) {
-            challenge = oauth.getChallenge();
-            return AuthOutcome.NOT_ATTEMPTED;
-
-        }
-
-        if (verifySSL()) return AuthOutcome.FAILED;
-
-        completeAuthentication(oauth);
-
-        // redirect to strip out access code and state query parameters
-        facade.getResponse().setHeader("Location", oauth.getStrippedOauthParametersRequestUri());
-        facade.getResponse().setStatus(302);
-        facade.getResponse().end();
-
-        log.debug("AUTHENTICATED");
-        return AuthOutcome.AUTHENTICATED;
-    }
-
-    protected boolean verifySSL() {
-        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            log.warn("SSL is required to authenticate");
-            return true;
-        }
-        return false;
-    }
-
-    protected abstract OAuthRequestAuthenticator createOAuthAuthenticator();
-
-    protected BearerTokenRequestAuthenticator createBearerTokenAuthenticator() {
-        return new BearerTokenRequestAuthenticator(deployment);
-    }
-
-    protected BasicAuthRequestAuthenticator createBasicAuthAuthenticator() {
-        return new BasicAuthRequestAuthenticator(deployment);
-    }
-
-    protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
-        RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
-        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
-        completeOAuthAuthentication(principal);
-    }
-
-    protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
-    protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
-    protected abstract String getHttpSessionId(boolean create);
-
-    protected void completeAuthentication(BearerTokenRequestAuthenticator bearer, String method) {
-        RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
-        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, bearer.getToken()), session);
-        completeBearerAuthentication(principal, method);
-    }
-
-}
+package org.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class RequestAuthenticator {
+    protected static Logger log = Logger.getLogger(RequestAuthenticator.class);
+
+    protected HttpFacade facade;
+    protected KeycloakDeployment deployment;
+    protected AdapterTokenStore tokenStore;
+    protected AuthChallenge challenge;
+    protected int sslRedirectPort;
+
+    public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort) {
+        this.facade = facade;
+        this.deployment = deployment;
+        this.tokenStore = tokenStore;
+        this.sslRedirectPort = sslRedirectPort;
+    }
+
+    public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment) {
+        this.facade = facade;
+        this.deployment = deployment;
+    }
+
+    public AuthChallenge getChallenge() {
+        return challenge;
+    }
+
+    public AuthOutcome authenticate() {
+        if (log.isTraceEnabled()) {
+            log.trace("--> authenticate()");
+        }
+
+        BearerTokenRequestAuthenticator bearer = createBearerTokenAuthenticator();
+        if (log.isTraceEnabled()) {
+            log.trace("try bearer");
+        }
+        
+        AuthOutcome outcome = bearer.authenticate(facade);
+        if (outcome == AuthOutcome.FAILED) {
+            challenge = bearer.getChallenge();
+            log.debug("Bearer FAILED");
+            return AuthOutcome.FAILED;
+        } else if (outcome == AuthOutcome.AUTHENTICATED) {
+            if (verifySSL()) return AuthOutcome.FAILED;
+            completeAuthentication(bearer, "KEYCLOAK");
+            log.debug("Bearer AUTHENTICATED");
+            return AuthOutcome.AUTHENTICATED;
+        } else if (deployment.isBearerOnly()) {
+            challenge = bearer.getChallenge();
+            log.debug("NOT_ATTEMPTED: bearer only");
+            return AuthOutcome.NOT_ATTEMPTED;
+        }
+
+        if (deployment.isEnableBasicAuth()) {
+            BasicAuthRequestAuthenticator basicAuth = createBasicAuthAuthenticator();
+            if (log.isTraceEnabled()) {
+                log.trace("try basic auth");
+            }
+    
+            outcome = basicAuth.authenticate(facade);
+            if (outcome == AuthOutcome.FAILED) {
+                challenge = basicAuth.getChallenge();
+                log.debug("BasicAuth FAILED");
+                return AuthOutcome.FAILED;
+            } else if (outcome == AuthOutcome.AUTHENTICATED) {
+                log.debug("BasicAuth AUTHENTICATED");
+                completeAuthentication(basicAuth, "BASIC");
+                return AuthOutcome.AUTHENTICATED;
+            }
+        }
+
+        if (log.isTraceEnabled()) {
+            log.trace("try oauth");
+        }
+
+        if (tokenStore.isCached(this)) {
+            if (verifySSL()) return AuthOutcome.FAILED;
+            log.debug("AUTHENTICATED: was cached");
+            return AuthOutcome.AUTHENTICATED;
+        }
+
+        OAuthRequestAuthenticator oauth = createOAuthAuthenticator();
+        outcome = oauth.authenticate();
+        if (outcome == AuthOutcome.FAILED) {
+            challenge = oauth.getChallenge();
+            return AuthOutcome.FAILED;
+        } else if (outcome == AuthOutcome.NOT_ATTEMPTED) {
+            challenge = oauth.getChallenge();
+            return AuthOutcome.NOT_ATTEMPTED;
+
+        }
+
+        if (verifySSL()) return AuthOutcome.FAILED;
+
+        completeAuthentication(oauth);
+
+        // redirect to strip out access code and state query parameters
+        facade.getResponse().setHeader("Location", oauth.getStrippedOauthParametersRequestUri());
+        facade.getResponse().setStatus(302);
+        facade.getResponse().end();
+
+        log.debug("AUTHENTICATED");
+        return AuthOutcome.AUTHENTICATED;
+    }
+
+    protected boolean verifySSL() {
+        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            log.warn("SSL is required to authenticate");
+            return true;
+        }
+        return false;
+    }
+
+    protected abstract OAuthRequestAuthenticator createOAuthAuthenticator();
+
+    protected BearerTokenRequestAuthenticator createBearerTokenAuthenticator() {
+        return new BearerTokenRequestAuthenticator(deployment);
+    }
+
+    protected BasicAuthRequestAuthenticator createBasicAuthAuthenticator() {
+        return new BasicAuthRequestAuthenticator(deployment);
+    }
+
+    protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
+        RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
+        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
+        completeOAuthAuthentication(principal);
+    }
+
+    protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
+    protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
+    protected abstract String getHttpSessionId(boolean create);
+
+    protected void completeAuthentication(BearerTokenRequestAuthenticator bearer, String method) {
+        RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
+        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, bearer.getToken()), session);
+        completeBearerAuthentication(principal, method);
+    }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
index 701dc09..0bf2cf4 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
@@ -1,289 +1,289 @@
-package org.keycloak.adapters;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-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.keycloak.OAuth2Constants;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.util.BasicAuthHelper;
-import org.keycloak.util.HostUtils;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.KeycloakUriBuilder;
-import org.keycloak.util.StreamUtil;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ServerRequest {
-
-    public static class HttpFailure extends Exception {
-        private int status;
-        private String error;
-
-        public HttpFailure(int status, String error) {
-            this.status = status;
-            this.error = error;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-
-        public String getError() {
-            return error;
-        }
-    }
-
-    public static void invokeLogout(KeycloakDeployment deployment, String refreshToken) throws IOException, HttpFailure {
-        String client_id = deployment.getResourceName();
-        Map<String, String> credentials = deployment.getResourceCredentials();
-        HttpClient client = deployment.getClient();
-        URI uri = deployment.getLogoutUrl().clone().build();
-        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-        for (Map.Entry<String, String> entry : credentials.entrySet()) {
-            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
-        }
-        formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken));
-        HttpResponse response = null;
-        HttpPost post = new HttpPost(uri);
-        if (!deployment.isPublicClient()) {
-            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
-            if (clientSecret != null) {
-                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
-                post.setHeader("Authorization", authorization);
-            }
-        } else {
-            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
-        }
-
-        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-        post.setEntity(form);
-        response = client.execute(post);
-        int status = response.getStatusLine().getStatusCode();
-        HttpEntity entity = response.getEntity();
-        if (status != 204) {
-            error(status, entity);
-        }
-        if (entity == null) {
-            return;
-        }
-        InputStream is = entity.getContent();
-        if (is != null) is.close();
-    }
-
-    public static AccessTokenResponse invokeAccessCodeToToken(KeycloakDeployment deployment, String code, String redirectUri, String sessionId) throws HttpFailure, IOException {
-        String tokenUrl = deployment.getTokenUrl();
-        String client_id = deployment.getResourceName();
-        Map<String, String> credentials = deployment.getResourceCredentials();
-        HttpClient client = deployment.getClient();
-
-        return invokeAccessCodeToToken(client, deployment.isPublicClient(), code, tokenUrl, redirectUri, client_id, credentials, sessionId);
-    }
-
-    public static AccessTokenResponse invokeAccessCodeToToken(HttpClient client, boolean publicClient, String code, String tokenUrl, String redirectUri, String client_id, Map<String, String> credentials, String sessionId) throws IOException, HttpFailure {
-        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-        redirectUri = stripOauthParametersFromRedirect(redirectUri);
-        formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "authorization_code"));
-        formparams.add(new BasicNameValuePair(OAuth2Constants.CODE, code));
-        formparams.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, redirectUri));
-        if (sessionId != null) {
-            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, sessionId));
-            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, HostUtils.getHostName()));
-        }
-        HttpResponse response = null;
-        HttpPost post = new HttpPost(tokenUrl);
-        if (!publicClient) {
-            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
-            if (clientSecret != null) {
-                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
-                post.setHeader("Authorization", authorization);
-            }
-        } else {
-            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
-        }
-
-        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-        post.setEntity(form);
-        response = client.execute(post);
-        int status = response.getStatusLine().getStatusCode();
-        HttpEntity entity = response.getEntity();
-        if (status != 200) {
-            error(status, entity);
-        }
-        if (entity == null) {
-            throw new HttpFailure(status, null);
-        }
-        InputStream is = entity.getContent();
-        try {
-            ByteArrayOutputStream os = new ByteArrayOutputStream();
-            int c;
-            while ((c = is.read()) != -1) {
-                os.write(c);
-            }
-            byte[] bytes = os.toByteArray();
-            String json = new String(bytes);
-            try {
-                return JsonSerialization.readValue(json, AccessTokenResponse.class);
-            } catch (IOException e) {
-                throw new IOException(json, e);
-            }
-        } finally {
-            try {
-                is.close();
-            } catch (IOException ignored) {
-
-            }
-        }
-    }
-
-    public static AccessTokenResponse invokeRefresh(KeycloakDeployment deployment, String refreshToken) throws IOException, HttpFailure {
-        String tokenUrl = deployment.getTokenUrl();
-        String client_id = deployment.getResourceName();
-        Map<String, String> credentials = deployment.getResourceCredentials();
-        HttpClient client = deployment.getClient();
-        return invokeRefresh(client, deployment.isPublicClient(), refreshToken, tokenUrl, client_id, credentials);
-    }
-
-
-    public static AccessTokenResponse invokeRefresh(HttpClient client, boolean publicClient, String refreshToken, String tokenUrl, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
-        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-        for (Map.Entry<String, String> entry : credentials.entrySet()) {
-            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
-        }
-        formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.REFRESH_TOKEN));
-        formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken));
-        HttpResponse response = null;
-        HttpPost post = new HttpPost(tokenUrl);
-        if (!publicClient) {
-            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
-            if (clientSecret != null) {
-                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
-                post.setHeader("Authorization", authorization);
-            }
-        } else {
-            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
-        }
-
-        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-        post.setEntity(form);
-        response = client.execute(post);
-        int status = response.getStatusLine().getStatusCode();
-        HttpEntity entity = response.getEntity();
-        if (status != 200) {
-            error(status, entity);
-        }
-        if (entity == null) {
-            throw new HttpFailure(status, null);
-        }
-        InputStream is = entity.getContent();
-        try {
-            ByteArrayOutputStream os = new ByteArrayOutputStream();
-            int c;
-            while ((c = is.read()) != -1) {
-                os.write(c);
-            }
-            byte[] bytes = os.toByteArray();
-            String json = new String(bytes);
-            try {
-                return JsonSerialization.readValue(json, AccessTokenResponse.class);
-            } catch (IOException e) {
-                throw new IOException(json, e);
-            }
-        } finally {
-            try {
-                is.close();
-            } catch (IOException ignored) {
-
-            }
-        }
-    }
-
-    public static void invokeRegisterNode(KeycloakDeployment deployment, String host) throws HttpFailure, IOException {
-        String registerNodeUrl = deployment.getRegisterNodeUrl();
-        String client_id = deployment.getResourceName();
-        Map<String, String> credentials = deployment.getResourceCredentials();
-        HttpClient client = deployment.getClient();
-
-        invokeClientManagementRequest(client, host, registerNodeUrl, client_id, credentials);
-    }
-
-    public static void invokeUnregisterNode(KeycloakDeployment deployment, String host) throws HttpFailure, IOException {
-        String unregisterNodeUrl = deployment.getUnregisterNodeUrl();
-        String client_id = deployment.getResourceName();
-        Map<String, String> credentials = deployment.getResourceCredentials();
-        HttpClient client = deployment.getClient();
-
-        invokeClientManagementRequest(client, host, unregisterNodeUrl, client_id, credentials);
-    }
-
-    public static void invokeClientManagementRequest(HttpClient client, String host, String endpointUrl, String clientId, Map<String, String> credentials) throws HttpFailure, IOException {
-        if (endpointUrl == null) {
-            throw new IOException("You need to configure URI for register/unregister node for application " + clientId);
-        }
-
-        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-        formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_CLUSTER_HOST, host));
-
-        HttpPost post = new HttpPost(endpointUrl);
-
-        String clientSecret = credentials.get(CredentialRepresentation.SECRET);
-        if (clientSecret != null) {
-            String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
-            post.setHeader("Authorization", authorization);
-        }  else {
-            throw new IOException("You need to configure clientSecret for register/unregister node for application " + clientId);
-        }
-
-        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-        post.setEntity(form);
-        HttpResponse response = client.execute(post);
-        int status = response.getStatusLine().getStatusCode();
-        if (status != 204) {
-            HttpEntity entity = response.getEntity();
-            error(status, entity);
-        }
-    }
-
-    public static void error(int status, HttpEntity entity) throws HttpFailure, IOException {
-        String body = null;
-        if (entity != null) {
-            InputStream is = entity.getContent();
-            try {
-                body = StreamUtil.readString(is);
-            } catch (IOException e) {
-
-            } finally {
-                try {
-                    is.close();
-                } catch (IOException ignored) {
-
-                }
-            }
-        }
-        throw new HttpFailure(status, body);
-    }
-
-    protected static String stripOauthParametersFromRedirect(String uri) {
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
-                .replaceQueryParam(OAuth2Constants.CODE, null)
-                .replaceQueryParam(OAuth2Constants.STATE, null);
-        return builder.build().toString();
-    }
-
-
-}
+package org.keycloak.adapters;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+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.keycloak.OAuth2Constants;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.util.BasicAuthHelper;
+import org.keycloak.util.HostUtils;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.StreamUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ServerRequest {
+
+    public static class HttpFailure extends Exception {
+        private int status;
+        private String error;
+
+        public HttpFailure(int status, String error) {
+            this.status = status;
+            this.error = error;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+
+        public String getError() {
+            return error;
+        }
+    }
+
+    public static void invokeLogout(KeycloakDeployment deployment, String refreshToken) throws IOException, HttpFailure {
+        String client_id = deployment.getResourceName();
+        Map<String, String> credentials = deployment.getResourceCredentials();
+        HttpClient client = deployment.getClient();
+        URI uri = deployment.getLogoutUrl().clone().build();
+        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+        for (Map.Entry<String, String> entry : credentials.entrySet()) {
+            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+        }
+        formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken));
+        HttpResponse response = null;
+        HttpPost post = new HttpPost(uri);
+        if (!deployment.isPublicClient()) {
+            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
+            if (clientSecret != null) {
+                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
+                post.setHeader("Authorization", authorization);
+            }
+        } else {
+            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
+        }
+
+        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+        post.setEntity(form);
+        response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        HttpEntity entity = response.getEntity();
+        if (status != 204) {
+            error(status, entity);
+        }
+        if (entity == null) {
+            return;
+        }
+        InputStream is = entity.getContent();
+        if (is != null) is.close();
+    }
+
+    public static AccessTokenResponse invokeAccessCodeToToken(KeycloakDeployment deployment, String code, String redirectUri, String sessionId) throws HttpFailure, IOException {
+        String tokenUrl = deployment.getTokenUrl();
+        String client_id = deployment.getResourceName();
+        Map<String, String> credentials = deployment.getResourceCredentials();
+        HttpClient client = deployment.getClient();
+
+        return invokeAccessCodeToToken(client, deployment.isPublicClient(), code, tokenUrl, redirectUri, client_id, credentials, sessionId);
+    }
+
+    public static AccessTokenResponse invokeAccessCodeToToken(HttpClient client, boolean publicClient, String code, String tokenUrl, String redirectUri, String client_id, Map<String, String> credentials, String sessionId) throws IOException, HttpFailure {
+        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+        redirectUri = stripOauthParametersFromRedirect(redirectUri);
+        formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "authorization_code"));
+        formparams.add(new BasicNameValuePair(OAuth2Constants.CODE, code));
+        formparams.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, redirectUri));
+        if (sessionId != null) {
+            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, sessionId));
+            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, HostUtils.getHostName()));
+        }
+        HttpResponse response = null;
+        HttpPost post = new HttpPost(tokenUrl);
+        if (!publicClient) {
+            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
+            if (clientSecret != null) {
+                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
+                post.setHeader("Authorization", authorization);
+            }
+        } else {
+            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
+        }
+
+        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+        post.setEntity(form);
+        response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        HttpEntity entity = response.getEntity();
+        if (status != 200) {
+            error(status, entity);
+        }
+        if (entity == null) {
+            throw new HttpFailure(status, null);
+        }
+        InputStream is = entity.getContent();
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            int c;
+            while ((c = is.read()) != -1) {
+                os.write(c);
+            }
+            byte[] bytes = os.toByteArray();
+            String json = new String(bytes);
+            try {
+                return JsonSerialization.readValue(json, AccessTokenResponse.class);
+            } catch (IOException e) {
+                throw new IOException(json, e);
+            }
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ignored) {
+
+            }
+        }
+    }
+
+    public static AccessTokenResponse invokeRefresh(KeycloakDeployment deployment, String refreshToken) throws IOException, HttpFailure {
+        String tokenUrl = deployment.getTokenUrl();
+        String client_id = deployment.getResourceName();
+        Map<String, String> credentials = deployment.getResourceCredentials();
+        HttpClient client = deployment.getClient();
+        return invokeRefresh(client, deployment.isPublicClient(), refreshToken, tokenUrl, client_id, credentials);
+    }
+
+
+    public static AccessTokenResponse invokeRefresh(HttpClient client, boolean publicClient, String refreshToken, String tokenUrl, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
+        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+        for (Map.Entry<String, String> entry : credentials.entrySet()) {
+            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+        }
+        formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.REFRESH_TOKEN));
+        formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken));
+        HttpResponse response = null;
+        HttpPost post = new HttpPost(tokenUrl);
+        if (!publicClient) {
+            String clientSecret = credentials.get(CredentialRepresentation.SECRET);
+            if (clientSecret != null) {
+                String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
+                post.setHeader("Authorization", authorization);
+            }
+        } else {
+            formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, client_id));
+        }
+
+        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+        post.setEntity(form);
+        response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        HttpEntity entity = response.getEntity();
+        if (status != 200) {
+            error(status, entity);
+        }
+        if (entity == null) {
+            throw new HttpFailure(status, null);
+        }
+        InputStream is = entity.getContent();
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            int c;
+            while ((c = is.read()) != -1) {
+                os.write(c);
+            }
+            byte[] bytes = os.toByteArray();
+            String json = new String(bytes);
+            try {
+                return JsonSerialization.readValue(json, AccessTokenResponse.class);
+            } catch (IOException e) {
+                throw new IOException(json, e);
+            }
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ignored) {
+
+            }
+        }
+    }
+
+    public static void invokeRegisterNode(KeycloakDeployment deployment, String host) throws HttpFailure, IOException {
+        String registerNodeUrl = deployment.getRegisterNodeUrl();
+        String client_id = deployment.getResourceName();
+        Map<String, String> credentials = deployment.getResourceCredentials();
+        HttpClient client = deployment.getClient();
+
+        invokeClientManagementRequest(client, host, registerNodeUrl, client_id, credentials);
+    }
+
+    public static void invokeUnregisterNode(KeycloakDeployment deployment, String host) throws HttpFailure, IOException {
+        String unregisterNodeUrl = deployment.getUnregisterNodeUrl();
+        String client_id = deployment.getResourceName();
+        Map<String, String> credentials = deployment.getResourceCredentials();
+        HttpClient client = deployment.getClient();
+
+        invokeClientManagementRequest(client, host, unregisterNodeUrl, client_id, credentials);
+    }
+
+    public static void invokeClientManagementRequest(HttpClient client, String host, String endpointUrl, String clientId, Map<String, String> credentials) throws HttpFailure, IOException {
+        if (endpointUrl == null) {
+            throw new IOException("You need to configure URI for register/unregister node for application " + clientId);
+        }
+
+        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+        formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_CLUSTER_HOST, host));
+
+        HttpPost post = new HttpPost(endpointUrl);
+
+        String clientSecret = credentials.get(CredentialRepresentation.SECRET);
+        if (clientSecret != null) {
+            String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
+            post.setHeader("Authorization", authorization);
+        }  else {
+            throw new IOException("You need to configure clientSecret for register/unregister node for application " + clientId);
+        }
+
+        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+        post.setEntity(form);
+        HttpResponse response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        if (status != 204) {
+            HttpEntity entity = response.getEntity();
+            error(status, entity);
+        }
+    }
+
+    public static void error(int status, HttpEntity entity) throws HttpFailure, IOException {
+        String body = null;
+        if (entity != null) {
+            InputStream is = entity.getContent();
+            try {
+                body = StreamUtil.readString(is);
+            } catch (IOException e) {
+
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ignored) {
+
+                }
+            }
+        }
+        throw new HttpFailure(status, body);
+    }
+
+    protected static String stripOauthParametersFromRedirect(String uri) {
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
+                .replaceQueryParam(OAuth2Constants.CODE, null)
+                .replaceQueryParam(OAuth2Constants.STATE, null);
+        return builder.build().toString();
+    }
+
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java
index c89e3ec..5ff908a 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java
@@ -1,14 +1,14 @@
-package org.keycloak.adapters;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserSessionManagement {
-
-    void logoutAll();
-
-    void logoutHttpSessions(List<String> ids);
-}
+package org.keycloak.adapters;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserSessionManagement {
+
+    void logoutAll();
+
+    void logoutHttpSessions(List<String> ids);
+}
diff --git a/integration/installed/pom.xml b/integration/installed/pom.xml
index 529b99f..7f0ed9e 100755
--- a/integration/installed/pom.xml
+++ b/integration/installed/pom.xml
@@ -1,64 +1,64 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-installed-adapter</artifactId>
-    <name>Keycloak Installed Application</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-installed-adapter</artifactId>
+    <name>Keycloak Installed Application</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/jaxrs-oauth-client/pom.xml b/integration/jaxrs-oauth-client/pom.xml
index fbda50c..8d91ffd 100755
--- a/integration/jaxrs-oauth-client/pom.xml
+++ b/integration/jaxrs-oauth-client/pom.xml
@@ -1,84 +1,84 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-jaxrs-oauth-client</artifactId>
-    <name>Keycloak JAX-RS OAuth Client</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <version>${resteasy.latest.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-            <version>${resteasy.latest.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-jaxrs-oauth-client</artifactId>
+    <name>Keycloak JAX-RS OAuth Client</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <version>${resteasy.latest.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+            <version>${resteasy.latest.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
index c731bbb..5a8fae2 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilterImpl.java
@@ -1,297 +1,297 @@
-package org.keycloak.jaxrs;
-
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.AuthChallenge;
-import org.keycloak.adapters.AuthOutcome;
-import org.keycloak.adapters.AuthenticatedActionsHandler;
-import org.keycloak.adapters.BasicAuthRequestAuthenticator;
-import org.keycloak.adapters.BearerTokenRequestAuthenticator;
-import org.keycloak.adapters.KeycloakConfigResolver;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.PreAuthActionsHandler;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.UserSessionManagement;
-import org.keycloak.constants.GenericConstants;
-
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.PreMatching;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.Principal;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Logger;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@PreMatching
-@Priority(Priorities.AUTHENTICATION)
-public class JaxrsBearerTokenFilterImpl implements JaxrsBearerTokenFilter {
-
-    private final static Logger log = Logger.getLogger("" + JaxrsBearerTokenFilterImpl.class);
-
-    private String keycloakConfigFile;
-    private String keycloakConfigResolverClass;
-    protected volatile boolean started;
-
-    protected AdapterDeploymentContext deploymentContext;
-
-    // TODO: Should also somehow handle stop lifecycle for de-registration
-    protected NodesRegistrationManagement nodesRegistrationManagement;
-    protected UserSessionManagement userSessionManagement = new EmptyUserSessionManagement();
-
-    public void setKeycloakConfigFile(String configFile) {
-        this.keycloakConfigFile = configFile;
-        attemptStart();
-    }
-
-    public String getKeycloakConfigFile() {
-        return this.keycloakConfigFile;
-    }
-
-    public String getKeycloakConfigResolverClass() {
-        return keycloakConfigResolverClass;
-    }
-
-    public void setKeycloakConfigResolverClass(String keycloakConfigResolverClass) {
-        this.keycloakConfigResolverClass = keycloakConfigResolverClass;
-        attemptStart();
-    }
-
-    // INITIALIZATION AND STARTUP
-
-    protected void attemptStart() {
-        if (started) {
-            throw new IllegalStateException("Filter already started. Make sure to specify just keycloakConfigResolver or keycloakConfigFile but not both");
-        }
-
-        if (isInitialized()) {
-            start();
-        } else {
-            log.fine("Not yet initialized");
-        }
-    }
-
-    protected boolean isInitialized() {
-        return this.keycloakConfigFile != null || this.keycloakConfigResolverClass != null;
-    }
-
-    protected void start() {
-        if (started) {
-            throw new IllegalStateException("Filter already started. Make sure to specify just keycloakConfigResolver or keycloakConfigFile but not both");
-        }
-
-        if (keycloakConfigResolverClass != null) {
-            Class<? extends KeycloakConfigResolver> resolverClass = loadResolverClass();
-
-            try {
-                KeycloakConfigResolver resolver = resolverClass.newInstance();
-                log.info("Using " + resolver + " to resolve Keycloak configuration on a per-request basis.");
-                this.deploymentContext = new AdapterDeploymentContext(resolver);
-            } catch (Exception e) {
-                throw new RuntimeException("Unable to instantiate resolver " + resolverClass);
-            }
-        } else {
-            if (keycloakConfigFile == null) {
-                throw new IllegalArgumentException("You need to specify either keycloakConfigResolverClass or keycloakConfigFile in configuration");
-            }
-            InputStream is = loadKeycloakConfigFile();
-            KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
-            deploymentContext = new AdapterDeploymentContext(kd);
-            log.info("Keycloak is using a per-deployment configuration loaded from: " + keycloakConfigFile);
-        }
-
-        nodesRegistrationManagement = new NodesRegistrationManagement();
-        started = true;
-    }
-
-    // TODO: Use 'Reflections.classForName'
-    protected Class<? extends KeycloakConfigResolver> loadResolverClass() {
-        try {
-            return (Class<? extends KeycloakConfigResolver>)getClass().getClassLoader().loadClass(keycloakConfigResolverClass);
-        } catch (ClassNotFoundException cnfe) {
-            // Fallback to tccl
-            try {
-                return (Class<? extends KeycloakConfigResolver>)Thread.currentThread().getContextClassLoader().loadClass(keycloakConfigResolverClass);
-            } catch (ClassNotFoundException cnfe2) {
-                throw new RuntimeException("Unable to find resolver class: " + keycloakConfigResolverClass);
-            }
-        }
-    }
-
-    protected InputStream loadKeycloakConfigFile() {
-        if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
-            String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
-            log.fine("Loading config from classpath on location: " + classPathLocation);
-            // Try current class classloader first
-            InputStream is = getClass().getClassLoader().getResourceAsStream(classPathLocation);
-            if (is == null) {
-                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
-            }
-
-            if (is != null) {
-                return is;
-            } else {
-                throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
-            }
-        } else {
-            // Fallback to file
-            try {
-                log.fine("Loading config from file: " + keycloakConfigFile);
-                return new FileInputStream(keycloakConfigFile);
-            } catch (FileNotFoundException fnfe) {
-                log.severe("Config not found on " + keycloakConfigFile);
-                throw new RuntimeException(fnfe);
-            }
-        }
-    }
-
-    // REQUEST HANDLING
-
-    @Override
-    public void filter(ContainerRequestContext request) throws IOException {
-        SecurityContext securityContext = getRequestSecurityContext(request);
-        JaxrsHttpFacade facade = new JaxrsHttpFacade(request, securityContext);
-        if (handlePreauth(facade)) {
-            return;
-        }
-
-        KeycloakDeployment resolvedDeployment = deploymentContext.resolveDeployment(facade);
-
-        nodesRegistrationManagement.tryRegister(resolvedDeployment);
-
-        bearerAuthentication(facade, request, resolvedDeployment);
-    }
-
-    protected boolean handlePreauth(JaxrsHttpFacade facade) {
-        PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade);
-        if (handler.handleRequest()) {
-            // Send response now (if not already sent)
-            if (!facade.isResponseFinished()) {
-                facade.getResponse().end();
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    protected void bearerAuthentication(JaxrsHttpFacade facade, ContainerRequestContext request, KeycloakDeployment resolvedDeployment) {
-        BearerTokenRequestAuthenticator authenticator = new BearerTokenRequestAuthenticator(resolvedDeployment);
-        AuthOutcome outcome = authenticator.authenticate(facade);
-        
-        if (outcome == AuthOutcome.NOT_ATTEMPTED && resolvedDeployment.isEnableBasicAuth()) {
-            authenticator = new BasicAuthRequestAuthenticator(resolvedDeployment);
-            outcome = authenticator.authenticate(facade);
-        }
-        
-        if (outcome == AuthOutcome.FAILED || outcome == AuthOutcome.NOT_ATTEMPTED) {
-            AuthChallenge challenge = authenticator.getChallenge();
-            log.fine("Authentication outcome: " + outcome);
-            boolean challengeSent = challenge.challenge(facade);
-            if (!challengeSent) {
-                // Use some default status code
-                facade.getResponse().setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
-            }
-
-            // Send response now (if not already sent)
-            if (!facade.isResponseFinished()) {
-                facade.getResponse().end();
-            }
-            return;
-        } else {
-            if (verifySslFailed(facade, resolvedDeployment)) {
-                return;
-            }
-        }
-
-        propagateSecurityContext(facade, request, resolvedDeployment, authenticator);
-        handleAuthActions(facade, resolvedDeployment);
-    }
-
-    protected void propagateSecurityContext(JaxrsHttpFacade facade, ContainerRequestContext request, KeycloakDeployment resolvedDeployment, BearerTokenRequestAuthenticator bearer) {
-        RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(resolvedDeployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
-
-        // Not needed to do resteasy specifics as KeycloakSecurityContext can be always retrieved from SecurityContext by typecast SecurityContext.getUserPrincipal to KeycloakPrincipal
-        // ResteasyProviderFactory.pushContext(KeycloakSecurityContext.class, skSession);
-
-        facade.setSecurityContext(skSession);
-        String principalName = AdapterUtils.getPrincipalName(resolvedDeployment, bearer.getToken());
-        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(principalName, skSession);
-        SecurityContext anonymousSecurityContext = getRequestSecurityContext(request);
-        final boolean isSecure = anonymousSecurityContext.isSecure();
-        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(skSession);
-
-        SecurityContext ctx = new SecurityContext() {
-            @Override
-            public Principal getUserPrincipal() {
-                return principal;
-            }
-
-            @Override
-            public boolean isUserInRole(String role) {
-                return roles.contains(role);
-            }
-
-            @Override
-            public boolean isSecure() {
-                return isSecure;
-            }
-
-            @Override
-            public String getAuthenticationScheme() {
-                return "OAUTH_BEARER";
-            }
-        };
-        request.setSecurityContext(ctx);
-    }
-
-    protected boolean verifySslFailed(JaxrsHttpFacade facade, KeycloakDeployment deployment) {
-        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
-            log.warning("SSL is required to authenticate, but request is not secured");
-            facade.getResponse().sendError(403, "SSL required!");
-            return true;
-        }
-        return false;
-    }
-
-    protected SecurityContext getRequestSecurityContext(ContainerRequestContext request) {
-        return request.getSecurityContext();
-    }
-
-    protected void handleAuthActions(JaxrsHttpFacade facade, KeycloakDeployment deployment) {
-        AuthenticatedActionsHandler authActionsHandler = new AuthenticatedActionsHandler(deployment, facade);
-        if (authActionsHandler.handledRequest()) {
-            // Send response now (if not already sent)
-            if (!facade.isResponseFinished()) {
-                facade.getResponse().end();
-            }
-        }
-    }
-
-    // We don't have any sessions to manage with pure jaxrs filter
-    private static class EmptyUserSessionManagement implements UserSessionManagement {
-
-        @Override
-        public void logoutAll() {
-        }
-
-        @Override
-        public void logoutHttpSessions(List<String> ids) {
-        }
-    }
-
-}
+package org.keycloak.jaxrs;
+
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.AuthChallenge;
+import org.keycloak.adapters.AuthOutcome;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.BasicAuthRequestAuthenticator;
+import org.keycloak.adapters.BearerTokenRequestAuthenticator;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.PreAuthActionsHandler;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.UserSessionManagement;
+import org.keycloak.constants.GenericConstants;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Principal;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@PreMatching
+@Priority(Priorities.AUTHENTICATION)
+public class JaxrsBearerTokenFilterImpl implements JaxrsBearerTokenFilter {
+
+    private final static Logger log = Logger.getLogger("" + JaxrsBearerTokenFilterImpl.class);
+
+    private String keycloakConfigFile;
+    private String keycloakConfigResolverClass;
+    protected volatile boolean started;
+
+    protected AdapterDeploymentContext deploymentContext;
+
+    // TODO: Should also somehow handle stop lifecycle for de-registration
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+    protected UserSessionManagement userSessionManagement = new EmptyUserSessionManagement();
+
+    public void setKeycloakConfigFile(String configFile) {
+        this.keycloakConfigFile = configFile;
+        attemptStart();
+    }
+
+    public String getKeycloakConfigFile() {
+        return this.keycloakConfigFile;
+    }
+
+    public String getKeycloakConfigResolverClass() {
+        return keycloakConfigResolverClass;
+    }
+
+    public void setKeycloakConfigResolverClass(String keycloakConfigResolverClass) {
+        this.keycloakConfigResolverClass = keycloakConfigResolverClass;
+        attemptStart();
+    }
+
+    // INITIALIZATION AND STARTUP
+
+    protected void attemptStart() {
+        if (started) {
+            throw new IllegalStateException("Filter already started. Make sure to specify just keycloakConfigResolver or keycloakConfigFile but not both");
+        }
+
+        if (isInitialized()) {
+            start();
+        } else {
+            log.fine("Not yet initialized");
+        }
+    }
+
+    protected boolean isInitialized() {
+        return this.keycloakConfigFile != null || this.keycloakConfigResolverClass != null;
+    }
+
+    protected void start() {
+        if (started) {
+            throw new IllegalStateException("Filter already started. Make sure to specify just keycloakConfigResolver or keycloakConfigFile but not both");
+        }
+
+        if (keycloakConfigResolverClass != null) {
+            Class<? extends KeycloakConfigResolver> resolverClass = loadResolverClass();
+
+            try {
+                KeycloakConfigResolver resolver = resolverClass.newInstance();
+                log.info("Using " + resolver + " to resolve Keycloak configuration on a per-request basis.");
+                this.deploymentContext = new AdapterDeploymentContext(resolver);
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to instantiate resolver " + resolverClass);
+            }
+        } else {
+            if (keycloakConfigFile == null) {
+                throw new IllegalArgumentException("You need to specify either keycloakConfigResolverClass or keycloakConfigFile in configuration");
+            }
+            InputStream is = loadKeycloakConfigFile();
+            KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
+            deploymentContext = new AdapterDeploymentContext(kd);
+            log.info("Keycloak is using a per-deployment configuration loaded from: " + keycloakConfigFile);
+        }
+
+        nodesRegistrationManagement = new NodesRegistrationManagement();
+        started = true;
+    }
+
+    // TODO: Use 'Reflections.classForName'
+    protected Class<? extends KeycloakConfigResolver> loadResolverClass() {
+        try {
+            return (Class<? extends KeycloakConfigResolver>)getClass().getClassLoader().loadClass(keycloakConfigResolverClass);
+        } catch (ClassNotFoundException cnfe) {
+            // Fallback to tccl
+            try {
+                return (Class<? extends KeycloakConfigResolver>)Thread.currentThread().getContextClassLoader().loadClass(keycloakConfigResolverClass);
+            } catch (ClassNotFoundException cnfe2) {
+                throw new RuntimeException("Unable to find resolver class: " + keycloakConfigResolverClass);
+            }
+        }
+    }
+
+    protected InputStream loadKeycloakConfigFile() {
+        if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
+            String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
+            log.fine("Loading config from classpath on location: " + classPathLocation);
+            // Try current class classloader first
+            InputStream is = getClass().getClassLoader().getResourceAsStream(classPathLocation);
+            if (is == null) {
+                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
+            }
+
+            if (is != null) {
+                return is;
+            } else {
+                throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
+            }
+        } else {
+            // Fallback to file
+            try {
+                log.fine("Loading config from file: " + keycloakConfigFile);
+                return new FileInputStream(keycloakConfigFile);
+            } catch (FileNotFoundException fnfe) {
+                log.severe("Config not found on " + keycloakConfigFile);
+                throw new RuntimeException(fnfe);
+            }
+        }
+    }
+
+    // REQUEST HANDLING
+
+    @Override
+    public void filter(ContainerRequestContext request) throws IOException {
+        SecurityContext securityContext = getRequestSecurityContext(request);
+        JaxrsHttpFacade facade = new JaxrsHttpFacade(request, securityContext);
+        if (handlePreauth(facade)) {
+            return;
+        }
+
+        KeycloakDeployment resolvedDeployment = deploymentContext.resolveDeployment(facade);
+
+        nodesRegistrationManagement.tryRegister(resolvedDeployment);
+
+        bearerAuthentication(facade, request, resolvedDeployment);
+    }
+
+    protected boolean handlePreauth(JaxrsHttpFacade facade) {
+        PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade);
+        if (handler.handleRequest()) {
+            // Send response now (if not already sent)
+            if (!facade.isResponseFinished()) {
+                facade.getResponse().end();
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    protected void bearerAuthentication(JaxrsHttpFacade facade, ContainerRequestContext request, KeycloakDeployment resolvedDeployment) {
+        BearerTokenRequestAuthenticator authenticator = new BearerTokenRequestAuthenticator(resolvedDeployment);
+        AuthOutcome outcome = authenticator.authenticate(facade);
+        
+        if (outcome == AuthOutcome.NOT_ATTEMPTED && resolvedDeployment.isEnableBasicAuth()) {
+            authenticator = new BasicAuthRequestAuthenticator(resolvedDeployment);
+            outcome = authenticator.authenticate(facade);
+        }
+        
+        if (outcome == AuthOutcome.FAILED || outcome == AuthOutcome.NOT_ATTEMPTED) {
+            AuthChallenge challenge = authenticator.getChallenge();
+            log.fine("Authentication outcome: " + outcome);
+            boolean challengeSent = challenge.challenge(facade);
+            if (!challengeSent) {
+                // Use some default status code
+                facade.getResponse().setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
+            }
+
+            // Send response now (if not already sent)
+            if (!facade.isResponseFinished()) {
+                facade.getResponse().end();
+            }
+            return;
+        } else {
+            if (verifySslFailed(facade, resolvedDeployment)) {
+                return;
+            }
+        }
+
+        propagateSecurityContext(facade, request, resolvedDeployment, authenticator);
+        handleAuthActions(facade, resolvedDeployment);
+    }
+
+    protected void propagateSecurityContext(JaxrsHttpFacade facade, ContainerRequestContext request, KeycloakDeployment resolvedDeployment, BearerTokenRequestAuthenticator bearer) {
+        RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(resolvedDeployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
+
+        // Not needed to do resteasy specifics as KeycloakSecurityContext can be always retrieved from SecurityContext by typecast SecurityContext.getUserPrincipal to KeycloakPrincipal
+        // ResteasyProviderFactory.pushContext(KeycloakSecurityContext.class, skSession);
+
+        facade.setSecurityContext(skSession);
+        String principalName = AdapterUtils.getPrincipalName(resolvedDeployment, bearer.getToken());
+        final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(principalName, skSession);
+        SecurityContext anonymousSecurityContext = getRequestSecurityContext(request);
+        final boolean isSecure = anonymousSecurityContext.isSecure();
+        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(skSession);
+
+        SecurityContext ctx = new SecurityContext() {
+            @Override
+            public Principal getUserPrincipal() {
+                return principal;
+            }
+
+            @Override
+            public boolean isUserInRole(String role) {
+                return roles.contains(role);
+            }
+
+            @Override
+            public boolean isSecure() {
+                return isSecure;
+            }
+
+            @Override
+            public String getAuthenticationScheme() {
+                return "OAUTH_BEARER";
+            }
+        };
+        request.setSecurityContext(ctx);
+    }
+
+    protected boolean verifySslFailed(JaxrsHttpFacade facade, KeycloakDeployment deployment) {
+        if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
+            log.warning("SSL is required to authenticate, but request is not secured");
+            facade.getResponse().sendError(403, "SSL required!");
+            return true;
+        }
+        return false;
+    }
+
+    protected SecurityContext getRequestSecurityContext(ContainerRequestContext request) {
+        return request.getSecurityContext();
+    }
+
+    protected void handleAuthActions(JaxrsHttpFacade facade, KeycloakDeployment deployment) {
+        AuthenticatedActionsHandler authActionsHandler = new AuthenticatedActionsHandler(deployment, facade);
+        if (authActionsHandler.handledRequest()) {
+            // Send response now (if not already sent)
+            if (!facade.isResponseFinished()) {
+                facade.getResponse().end();
+            }
+        }
+    }
+
+    // We don't have any sessions to manage with pure jaxrs filter
+    private static class EmptyUserSessionManagement implements UserSessionManagement {
+
+        @Override
+        public void logoutAll() {
+        }
+
+        @Override
+        public void logoutHttpSessions(List<String> ids) {
+        }
+    }
+
+}
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
index 04ef9a2..684f268 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
@@ -1,121 +1,121 @@
-package org.keycloak.jaxrs;
-
-import org.keycloak.AbstractOAuthClient;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.representations.AccessTokenResponse;
-
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.InternalServerErrorException;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.NewCookie;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.net.URI;
-import java.util.Map;
-import java.util.logging.Logger;
-
-/**
- * Helper code to obtain oauth access tokens via browser redirects
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JaxrsOAuthClient extends AbstractOAuthClient {
-    private final static Logger logger = Logger.getLogger("" + JaxrsOAuthClient.class);
-    protected Client client;
-
-    /**
-     * closes client
-     */
-    public void stop() {
-        if (client != null) client.close();
-    }
-    public Client getClient() {
-        return client;
-    }
-
-    public void setClient(Client client) {
-        this.client = client;
-    }
-
-    public String resolveBearerToken(String redirectUri, String code) {
-        redirectUri = stripOauthParametersFromRedirect(redirectUri);
-        Form codeForm = new Form()
-                .param(OAuth2Constants.GRANT_TYPE, "authorization_code")
-                .param(OAuth2Constants.CODE, code)
-                .param(OAuth2Constants.CLIENT_ID, clientId)
-                .param(OAuth2Constants.REDIRECT_URI, redirectUri);
-        for (Map.Entry<String, String> entry : credentials.entrySet()) {
-            codeForm.param(entry.getKey(), entry.getValue());
-        }
-        Response res = client.target(tokenUrl).request().post(Entity.form(codeForm));
-        try {
-            if (res.getStatus() == 400) {
-                throw new BadRequestException();
-            } else if (res.getStatus() != 200) {
-                throw new InternalServerErrorException(new Exception("Unknown error when getting acess token"));
-            }
-            AccessTokenResponse tokenResponse = res.readEntity(AccessTokenResponse.class);
-            return tokenResponse.getToken();
-        } finally {
-            res.close();
-        }
-    }
-    public Response redirect(UriInfo uriInfo, String redirectUri) {
-        String state = getStateCode();
-
-        UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
-                .queryParam(OAuth2Constants.CLIENT_ID, clientId)
-                .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
-                .queryParam(OAuth2Constants.STATE, state);
-        if (scope != null) {
-            uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
-        }
-
-        URI url = uriBuilder.build();
-
-        NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
-        logger.fine("NewCookie: " + cookie.toString());
-        logger.fine("Oauth Redirect to: " + url);
-        return Response.status(302)
-                .location(url)
-                .cookie(cookie).build();
-    }
-
-    public String getStateCookiePath(UriInfo uriInfo) {
-        if (stateCookiePath != null) return stateCookiePath;
-        return uriInfo.getBaseUri().getRawPath();
-    }
-
-    public String getBearerToken(UriInfo uriInfo, HttpHeaders headers) throws BadRequestException, InternalServerErrorException {
-        String error = getError(uriInfo);
-        if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
-        checkStateCookie(uriInfo, headers);
-        String code = getAccessCode(uriInfo);
-        if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
-        return resolveBearerToken(uriInfo.getRequestUri().toString(), code);
-    }
-
-    public String getError(UriInfo uriInfo) {
-        return uriInfo.getQueryParameters().getFirst(OAuth2Constants.ERROR);
-    }
-
-    public String getAccessCode(UriInfo uriInfo) {
-        return uriInfo.getQueryParameters().getFirst(OAuth2Constants.CODE);
-    }
-
-    public void checkStateCookie(UriInfo uriInfo, HttpHeaders headers) {
-        Cookie stateCookie = headers.getCookies().get(stateCookieName);
-        if (stateCookie == null) throw new BadRequestException("state cookie not set");
-        String state = uriInfo.getQueryParameters().getFirst(OAuth2Constants.STATE);
-        if (state == null) throw new BadRequestException("state parameter was null");
-        if (!state.equals(stateCookie.getValue())) {
-            throw new BadRequestException("state parameter invalid");
-        }
-    }
-}
+package org.keycloak.jaxrs;
+
+import org.keycloak.AbstractOAuthClient;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.representations.AccessTokenResponse;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Helper code to obtain oauth access tokens via browser redirects
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JaxrsOAuthClient extends AbstractOAuthClient {
+    private final static Logger logger = Logger.getLogger("" + JaxrsOAuthClient.class);
+    protected Client client;
+
+    /**
+     * closes client
+     */
+    public void stop() {
+        if (client != null) client.close();
+    }
+    public Client getClient() {
+        return client;
+    }
+
+    public void setClient(Client client) {
+        this.client = client;
+    }
+
+    public String resolveBearerToken(String redirectUri, String code) {
+        redirectUri = stripOauthParametersFromRedirect(redirectUri);
+        Form codeForm = new Form()
+                .param(OAuth2Constants.GRANT_TYPE, "authorization_code")
+                .param(OAuth2Constants.CODE, code)
+                .param(OAuth2Constants.CLIENT_ID, clientId)
+                .param(OAuth2Constants.REDIRECT_URI, redirectUri);
+        for (Map.Entry<String, String> entry : credentials.entrySet()) {
+            codeForm.param(entry.getKey(), entry.getValue());
+        }
+        Response res = client.target(tokenUrl).request().post(Entity.form(codeForm));
+        try {
+            if (res.getStatus() == 400) {
+                throw new BadRequestException();
+            } else if (res.getStatus() != 200) {
+                throw new InternalServerErrorException(new Exception("Unknown error when getting acess token"));
+            }
+            AccessTokenResponse tokenResponse = res.readEntity(AccessTokenResponse.class);
+            return tokenResponse.getToken();
+        } finally {
+            res.close();
+        }
+    }
+    public Response redirect(UriInfo uriInfo, String redirectUri) {
+        String state = getStateCode();
+
+        UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
+                .queryParam(OAuth2Constants.CLIENT_ID, clientId)
+                .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
+                .queryParam(OAuth2Constants.STATE, state);
+        if (scope != null) {
+            uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
+        }
+
+        URI url = uriBuilder.build();
+
+        NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
+        logger.fine("NewCookie: " + cookie.toString());
+        logger.fine("Oauth Redirect to: " + url);
+        return Response.status(302)
+                .location(url)
+                .cookie(cookie).build();
+    }
+
+    public String getStateCookiePath(UriInfo uriInfo) {
+        if (stateCookiePath != null) return stateCookiePath;
+        return uriInfo.getBaseUri().getRawPath();
+    }
+
+    public String getBearerToken(UriInfo uriInfo, HttpHeaders headers) throws BadRequestException, InternalServerErrorException {
+        String error = getError(uriInfo);
+        if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
+        checkStateCookie(uriInfo, headers);
+        String code = getAccessCode(uriInfo);
+        if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
+        return resolveBearerToken(uriInfo.getRequestUri().toString(), code);
+    }
+
+    public String getError(UriInfo uriInfo) {
+        return uriInfo.getQueryParameters().getFirst(OAuth2Constants.ERROR);
+    }
+
+    public String getAccessCode(UriInfo uriInfo) {
+        return uriInfo.getQueryParameters().getFirst(OAuth2Constants.CODE);
+    }
+
+    public void checkStateCookie(UriInfo uriInfo, HttpHeaders headers) {
+        Cookie stateCookie = headers.getCookies().get(stateCookieName);
+        if (stateCookie == null) throw new BadRequestException("state cookie not set");
+        String state = uriInfo.getQueryParameters().getFirst(OAuth2Constants.STATE);
+        if (state == null) throw new BadRequestException("state parameter was null");
+        if (!state.equals(stateCookie.getValue())) {
+            throw new BadRequestException("state parameter invalid");
+        }
+    }
+}
diff --git a/integration/jboss-adapter-core/pom.xml b/integration/jboss-adapter-core/pom.xml
index 0e6cb1e..a3a8dcc 100755
--- a/integration/jboss-adapter-core/pom.xml
+++ b/integration/jboss-adapter-core/pom.xml
@@ -1,81 +1,81 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-jboss-adapter-core</artifactId>
-    <name>Common JBoss/Wildfly Core Classes</name>
-    <description/>
-
-    <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-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.picketbox</groupId>
-            <artifactId>picketbox</artifactId>
-            <version>4.0.20.Final</version>
-            <scope>provided</scope>
-        </dependency>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-jboss-adapter-core</artifactId>
+    <name>Common JBoss/Wildfly Core Classes</name>
+    <description/>
+
+    <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-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.picketbox</groupId>
+            <artifactId>picketbox</artifactId>
+            <version>4.0.20.Final</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java b/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java
index f32b2b8..8271b39 100755
--- a/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java
+++ b/integration/jboss-adapter-core/src/main/java/org/keycloak/adapters/jboss/KeycloakLoginModule.java
@@ -1,100 +1,100 @@
-package org.keycloak.adapters.jboss;
-
-import org.jboss.logging.Logger;
-import org.jboss.security.SimpleGroup;
-import org.jboss.security.SimplePrincipal;
-import org.jboss.security.auth.callback.ObjectCallback;
-import org.jboss.security.auth.spi.AbstractServerLoginModule;
-import org.keycloak.adapters.KeycloakAccount;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginException;
-import java.io.IOException;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakLoginModule extends AbstractServerLoginModule {
-    protected static Logger log = Logger.getLogger(KeycloakLoginModule.class);
-    protected Set<String> roleSet;
-    protected Principal identity;
-
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public boolean login() throws LoginException {
-        log.debug("KeycloakLoginModule.login()");
-        if (super.login() == true) {
-            log.debug("super.login()==true");
-            return true;
-        }
-
-        Object credential = getCredential();
-        if (credential != null && (credential instanceof KeycloakAccount)) {
-            log.debug("Found Account");
-            KeycloakAccount account = (KeycloakAccount)credential;
-            roleSet = account.getRoles();
-            identity = account.getPrincipal();
-            sharedState.put("javax.security.auth.login.name", identity);
-            sharedState.put("javax.security.auth.login.password", credential);
-            loginOk = true;
-            return true;
-        }
-
-        // We return false to allow the next module to attempt authentication, maybe a
-        // username and password has been supplied to a web auth.
-        return false;
-    }
-
-
-    @Override
-    protected Principal getIdentity() {
-        return identity;
-    }
-
-    /*
-    @Override
-    protected Group[] getRoleSets() throws LoginException {
-        return new Group[0];
-    }
-    */
-
-    @Override
-    protected Group[] getRoleSets() throws LoginException {
-        //log.info("getRoleSets");
-        SimpleGroup roles = new SimpleGroup("Roles");
-        Group[] roleSets = {roles};
-        for (String role : roleSet) {
-            //log.info("   adding role: " + role);
-            roles.addMember(new SimplePrincipal(role));
-        }
-        return roleSets;
-    }
-
-    protected Object getCredential() throws LoginException {
-        NameCallback nc = new NameCallback("Alias: ");
-        ObjectCallback oc = new ObjectCallback("Credential: ");
-        Callback[] callbacks = { nc, oc };
-
-        try {
-            callbackHandler.handle(callbacks);
-
-            return oc.getCredential();
-        } catch (IOException ioe) {
-            LoginException le = new LoginException();
-            le.initCause(ioe);
-            throw le;
-        } catch (UnsupportedCallbackException uce) {
-            LoginException le = new LoginException();
-            le.initCause(uce);
-            throw le;
-        }
-    }
-
-}
+package org.keycloak.adapters.jboss;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.callback.ObjectCallback;
+import org.jboss.security.auth.spi.AbstractServerLoginModule;
+import org.keycloak.adapters.KeycloakAccount;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakLoginModule extends AbstractServerLoginModule {
+    protected static Logger log = Logger.getLogger(KeycloakLoginModule.class);
+    protected Set<String> roleSet;
+    protected Principal identity;
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean login() throws LoginException {
+        log.debug("KeycloakLoginModule.login()");
+        if (super.login() == true) {
+            log.debug("super.login()==true");
+            return true;
+        }
+
+        Object credential = getCredential();
+        if (credential != null && (credential instanceof KeycloakAccount)) {
+            log.debug("Found Account");
+            KeycloakAccount account = (KeycloakAccount)credential;
+            roleSet = account.getRoles();
+            identity = account.getPrincipal();
+            sharedState.put("javax.security.auth.login.name", identity);
+            sharedState.put("javax.security.auth.login.password", credential);
+            loginOk = true;
+            return true;
+        }
+
+        // We return false to allow the next module to attempt authentication, maybe a
+        // username and password has been supplied to a web auth.
+        return false;
+    }
+
+
+    @Override
+    protected Principal getIdentity() {
+        return identity;
+    }
+
+    /*
+    @Override
+    protected Group[] getRoleSets() throws LoginException {
+        return new Group[0];
+    }
+    */
+
+    @Override
+    protected Group[] getRoleSets() throws LoginException {
+        //log.info("getRoleSets");
+        SimpleGroup roles = new SimpleGroup("Roles");
+        Group[] roleSets = {roles};
+        for (String role : roleSet) {
+            //log.info("   adding role: " + role);
+            roles.addMember(new SimplePrincipal(role));
+        }
+        return roleSets;
+    }
+
+    protected Object getCredential() throws LoginException {
+        NameCallback nc = new NameCallback("Alias: ");
+        ObjectCallback oc = new ObjectCallback("Credential: ");
+        Callback[] callbacks = { nc, oc };
+
+        try {
+            callbackHandler.handle(callbacks);
+
+            return oc.getCredential();
+        } catch (IOException ioe) {
+            LoginException le = new LoginException();
+            le.initCause(ioe);
+            throw le;
+        } catch (UnsupportedCallbackException uce) {
+            LoginException le = new LoginException();
+            le.initCause(uce);
+            throw le;
+        }
+    }
+
+}
diff --git a/integration/jetty/jetty8.1/pom.xml b/integration/jetty/jetty8.1/pom.xml
index a6d49d7..3f0149f 100755
--- a/integration/jetty/jetty8.1/pom.xml
+++ b/integration/jetty/jetty8.1/pom.xml
@@ -1,142 +1,142 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-jetty81-adapter</artifactId>
-	<name>Keycloak Jetty 8.1.x Integration</name>
-    <properties>
-        <jetty9.version>8.1.16.v20140903</jetty9.version>
-        <keycloak.osgi.export>
-            org.keycloak.adapters.jetty.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            javax.servlet.*;version="[2.5,4)";resolution:=optional,
-            org.keycloak.*;version="${project.version}",
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty-core</artifactId>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-security</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-jetty81-adapter</artifactId>
+	<name>Keycloak Jetty 8.1.x Integration</name>
+    <properties>
+        <jetty9.version>8.1.16.v20140903</jetty9.version>
+        <keycloak.osgi.export>
+            org.keycloak.adapters.jetty.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            javax.servlet.*;version="[2.5,4)";resolution:=optional,
+            org.keycloak.*;version="${project.version}",
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty-core</artifactId>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-security</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
index 38180aa..82ae807 100755
--- a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
+++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
@@ -1,94 +1,94 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.util.MultiMap;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
-import org.keycloak.util.MultivaluedHashMap;
-
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
-    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
-    protected Request myRequest;
-
-    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
-        super(request, deployment);
-        this.myRequest = request; // for IDE/compilation purposes
-    }
-
-    protected MultiMap<String> extractFormParameters(Request base_request) {
-        MultiMap<String> formParameters = new MultiMap<String>();
-        base_request.extractParameters();
-        return base_request.getParameters();
-    }
-    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
-        base_request.setParameters(j_post);
-    }
-
-    public boolean restoreRequest() {
-        HttpSession session = myRequest.getSession(false);
-        if (session == null) return false;
-        synchronized (session) {
-            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
-            if (j_uri != null) {
-                // check if the request is for the same url as the original and restore
-                // params if it was a post
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                if (j_uri.equals(buf.toString())) {
-                    String method = (String)session.getAttribute(__J_METHOD);
-                    myRequest.setMethod(method);
-                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
-                    if (j_post != null) {
-                        MultiMap<String> map = new MultiMap<String>();
-                        for (String key : j_post.keySet()) {
-                            for (String val : j_post.getList(key)) {
-                                map.add(key, val);
-                            }
-                        }
-                        restoreFormParameters(map, myRequest);
-                    }
-                    session.removeAttribute(FormAuthenticator.__J_URI);
-                    session.removeAttribute(__J_METHOD);
-                    session.removeAttribute(FormAuthenticator.__J_POST);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void saveRequest() {
-        // remember the current URI
-        HttpSession session = myRequest.getSession();
-        synchronized (session) {
-            // But only if it is not set already, or we save every uri that leads to a login form redirect
-            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
-                session.setAttribute(__J_METHOD, myRequest.getMethod());
-
-                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
-                    MultiMap<String> formParameters = extractFormParameters(myRequest);
-                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
-                    for (String key : formParameters.keySet()) {
-                        for (Object value : formParameters.getValues(key)) {
-                            map.add(key, (String) value);
-                        }
-                    }
-                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
-                }
-            }
-        }
-    }
-
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.util.MultiMap;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
+import org.keycloak.util.MultivaluedHashMap;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
+    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
+    protected Request myRequest;
+
+    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
+        super(request, deployment);
+        this.myRequest = request; // for IDE/compilation purposes
+    }
+
+    protected MultiMap<String> extractFormParameters(Request base_request) {
+        MultiMap<String> formParameters = new MultiMap<String>();
+        base_request.extractParameters();
+        return base_request.getParameters();
+    }
+    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
+        base_request.setParameters(j_post);
+    }
+
+    public boolean restoreRequest() {
+        HttpSession session = myRequest.getSession(false);
+        if (session == null) return false;
+        synchronized (session) {
+            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
+            if (j_uri != null) {
+                // check if the request is for the same url as the original and restore
+                // params if it was a post
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                if (j_uri.equals(buf.toString())) {
+                    String method = (String)session.getAttribute(__J_METHOD);
+                    myRequest.setMethod(method);
+                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
+                    if (j_post != null) {
+                        MultiMap<String> map = new MultiMap<String>();
+                        for (String key : j_post.keySet()) {
+                            for (String val : j_post.getList(key)) {
+                                map.add(key, val);
+                            }
+                        }
+                        restoreFormParameters(map, myRequest);
+                    }
+                    session.removeAttribute(FormAuthenticator.__J_URI);
+                    session.removeAttribute(__J_METHOD);
+                    session.removeAttribute(FormAuthenticator.__J_POST);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void saveRequest() {
+        // remember the current URI
+        HttpSession session = myRequest.getSession();
+        synchronized (session) {
+            // But only if it is not set already, or we save every uri that leads to a login form redirect
+            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
+                session.setAttribute(__J_METHOD, myRequest.getMethod());
+
+                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
+                    MultiMap<String> formParameters = extractFormParameters(myRequest);
+                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+                    for (String key : formParameters.keySet()) {
+                        for (Object value : formParameters.getValues(key)) {
+                            map.add(key, (String) value);
+                        }
+                    }
+                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
+                }
+            }
+        }
+    }
+
+}
diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
index a3a5572..243de1c 100755
--- a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
@@ -1,45 +1,45 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.server.AbstractHttpConnection;
-import org.eclipse.jetty.server.Authentication;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.UserIdentity;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
-
-import javax.servlet.ServletRequest;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
-
-    public KeycloakJettyAuthenticator() {
-        super();
-    }
-
-
-    @Override
-    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
-        return new JettySessionTokenStore(request, resolvedDeployment);
-    }
-
-    @Override
-    protected Request resolveRequest(ServletRequest req) {
-        return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
-    }
-
-    @Override
-    protected Authentication createAuthentication(UserIdentity userIdentity) {
-        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
-            @Override
-            public void logout() {
-                logoutCurrent(AbstractHttpConnection.getCurrentConnection().getRequest());
-            }
-        };
-    }
-
-
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.server.AbstractHttpConnection;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.UserIdentity;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
+
+import javax.servlet.ServletRequest;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
+
+    public KeycloakJettyAuthenticator() {
+        super();
+    }
+
+
+    @Override
+    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
+        return new JettySessionTokenStore(request, resolvedDeployment);
+    }
+
+    @Override
+    protected Request resolveRequest(ServletRequest req) {
+        return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
+    }
+
+    @Override
+    protected Authentication createAuthentication(UserIdentity userIdentity) {
+        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
+            @Override
+            public void logout() {
+                logoutCurrent(AbstractHttpConnection.getCurrentConnection().getRequest());
+            }
+        };
+    }
+
+
+}
diff --git a/integration/jetty/jetty9.1/pom.xml b/integration/jetty/jetty9.1/pom.xml
index 27e7c06..9bcc9b4 100755
--- a/integration/jetty/jetty9.1/pom.xml
+++ b/integration/jetty/jetty9.1/pom.xml
@@ -1,157 +1,157 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-jetty91-adapter</artifactId>
-	<name>Keycloak Jetty 9.1.x Integration</name>
-    <properties>
-        <jetty9.version>9.1.5.v20140505</jetty9.version>
-        <keycloak.osgi.export>
-            org.keycloak.adapters.jetty.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            org.eclipse.jetty.*;version="[9.1,9.2)";resolution:=optional,
-            javax.servlet.*;version="[3.0,4)";resolution:=optional,
-            org.keycloak.*;version="${project.version}",
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty-core</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-server</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-util</artifactId>
-               </exclusion>
-                <exclusion>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-security</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-security</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-jetty91-adapter</artifactId>
+	<name>Keycloak Jetty 9.1.x Integration</name>
+    <properties>
+        <jetty9.version>9.1.5.v20140505</jetty9.version>
+        <keycloak.osgi.export>
+            org.keycloak.adapters.jetty.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            org.eclipse.jetty.*;version="[9.1,9.2)";resolution:=optional,
+            javax.servlet.*;version="[3.0,4)";resolution:=optional,
+            org.keycloak.*;version="${project.version}",
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-server</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+               </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-security</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-security</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
index 6d4cb92..b9707e4 100755
--- a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
+++ b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
@@ -1,95 +1,95 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.util.MultiMap;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
-import org.keycloak.util.MultivaluedHashMap;
-
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
-    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
-    protected Request myRequest;
-
-    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
-        super(request, deployment);
-        this.myRequest = request; // for IDE/compilation purposes
-    }
-
-    protected MultiMap<String> extractFormParameters(Request base_request) {
-        MultiMap<String> formParameters = new MultiMap<String>();
-        base_request.extractParameters();
-        return base_request.getParameters();
-    }
-    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
-        base_request.setParameters(j_post);
-    }
-
-    public boolean restoreRequest() {
-        HttpSession session = myRequest.getSession(false);
-        if (session == null) return false;
-        synchronized (session) {
-            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
-            if (j_uri != null) {
-                // check if the request is for the same url as the original and restore
-                // params if it was a post
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                if (j_uri.equals(buf.toString())) {
-                    String method = (String)session.getAttribute(__J_METHOD);
-                    myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
-                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
-                    if (j_post != null) {
-                        MultiMap<String> map = new MultiMap<String>();
-                        for (String key : j_post.keySet()) {
-                            for (String val : j_post.getList(key)) {
-                                map.add(key, val);
-                            }
-                        }
-                        restoreFormParameters(map, myRequest);
-                    }
-                    session.removeAttribute(FormAuthenticator.__J_URI);
-                    session.removeAttribute(__J_METHOD);
-                    session.removeAttribute(FormAuthenticator.__J_POST);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void saveRequest() {
-        // remember the current URI
-        HttpSession session = myRequest.getSession();
-        synchronized (session) {
-            // But only if it is not set already, or we save every uri that leads to a login form redirect
-            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
-                session.setAttribute(__J_METHOD, myRequest.getMethod());
-
-                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
-                    MultiMap<String> formParameters = extractFormParameters(myRequest);
-                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
-                    for (String key : formParameters.keySet()) {
-                        for (Object value : formParameters.getValues(key)) {
-                            map.add(key, (String) value);
-                        }
-                    }
-                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
-                }
-            }
-        }
-    }
-
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.util.MultiMap;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
+import org.keycloak.util.MultivaluedHashMap;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
+    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
+    protected Request myRequest;
+
+    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
+        super(request, deployment);
+        this.myRequest = request; // for IDE/compilation purposes
+    }
+
+    protected MultiMap<String> extractFormParameters(Request base_request) {
+        MultiMap<String> formParameters = new MultiMap<String>();
+        base_request.extractParameters();
+        return base_request.getParameters();
+    }
+    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
+        base_request.setParameters(j_post);
+    }
+
+    public boolean restoreRequest() {
+        HttpSession session = myRequest.getSession(false);
+        if (session == null) return false;
+        synchronized (session) {
+            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
+            if (j_uri != null) {
+                // check if the request is for the same url as the original and restore
+                // params if it was a post
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                if (j_uri.equals(buf.toString())) {
+                    String method = (String)session.getAttribute(__J_METHOD);
+                    myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
+                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
+                    if (j_post != null) {
+                        MultiMap<String> map = new MultiMap<String>();
+                        for (String key : j_post.keySet()) {
+                            for (String val : j_post.getList(key)) {
+                                map.add(key, val);
+                            }
+                        }
+                        restoreFormParameters(map, myRequest);
+                    }
+                    session.removeAttribute(FormAuthenticator.__J_URI);
+                    session.removeAttribute(__J_METHOD);
+                    session.removeAttribute(FormAuthenticator.__J_POST);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void saveRequest() {
+        // remember the current URI
+        HttpSession session = myRequest.getSession();
+        synchronized (session) {
+            // But only if it is not set already, or we save every uri that leads to a login form redirect
+            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
+                session.setAttribute(__J_METHOD, myRequest.getMethod());
+
+                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
+                    MultiMap<String> formParameters = extractFormParameters(myRequest);
+                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+                    for (String key : formParameters.keySet()) {
+                        for (Object value : formParameters.getValues(key)) {
+                            map.add(key, (String) value);
+                        }
+                    }
+                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
+                }
+            }
+        }
+    }
+
+}
diff --git a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
index d1ab5f3..0d1bf3b 100755
--- a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
@@ -1,45 +1,45 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.server.Authentication;
-import org.eclipse.jetty.server.HttpChannel;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.UserIdentity;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
-
-import javax.servlet.ServletRequest;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
-
-    public KeycloakJettyAuthenticator() {
-        super();
-    }
-
-
-    @Override
-    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
-        return new JettySessionTokenStore(request, resolvedDeployment);
-    }
-
-    @Override
-    protected Request resolveRequest(ServletRequest req) {
-        return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
-    }
-
-    @Override
-    protected Authentication createAuthentication(UserIdentity userIdentity) {
-        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
-            @Override
-            public void logout() {
-                logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest());
-            }
-        };
-    }
-
-
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.UserIdentity;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
+
+import javax.servlet.ServletRequest;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
+
+    public KeycloakJettyAuthenticator() {
+        super();
+    }
+
+
+    @Override
+    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
+        return new JettySessionTokenStore(request, resolvedDeployment);
+    }
+
+    @Override
+    protected Request resolveRequest(ServletRequest req) {
+        return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
+    }
+
+    @Override
+    protected Authentication createAuthentication(UserIdentity userIdentity) {
+        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
+            @Override
+            public void logout() {
+                logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest());
+            }
+        };
+    }
+
+
+}
diff --git a/integration/jetty/jetty9.2/pom.xml b/integration/jetty/jetty9.2/pom.xml
index 13104d5..eb60ef5 100755
--- a/integration/jetty/jetty9.2/pom.xml
+++ b/integration/jetty/jetty9.2/pom.xml
@@ -1,143 +1,143 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-jetty92-adapter</artifactId>
-	<name>Keycloak Jetty 9.2.x Integration</name>
-    <properties>
-        <jetty9.version>9.2.4.v20141103</jetty9.version>
-        <keycloak.osgi.export>
-            org.keycloak.adapters.jetty.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            org.eclipse.jetty.*;resolution:=optional,
-            javax.servlet.*;version="[3.0,4)";resolution:=optional,
-            org.keycloak.*;version="${project.version}",
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jetty-core</artifactId>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-security</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-jetty92-adapter</artifactId>
+	<name>Keycloak Jetty 9.2.x Integration</name>
+    <properties>
+        <jetty9.version>9.2.4.v20141103</jetty9.version>
+        <keycloak.osgi.export>
+            org.keycloak.adapters.jetty.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            org.eclipse.jetty.*;resolution:=optional,
+            javax.servlet.*;version="[3.0,4)";resolution:=optional,
+            org.keycloak.*;version="${project.version}",
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty-core</artifactId>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-security</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
index f48a0d8..2f46975 100755
--- a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
+++ b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java
@@ -1,95 +1,95 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.util.MultiMap;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
-import org.keycloak.util.MultivaluedHashMap;
-
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
-    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
-    protected Request myRequest;
-
-    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
-        super(request, deployment);
-        this.myRequest = request; // for IDE/compilation purposes
-    }
-
-    protected MultiMap<String> extractFormParameters(Request base_request) {
-        MultiMap<String> formParameters = new MultiMap<String>();
-        base_request.extractFormParameters(formParameters);
-        return formParameters;
-    }
-    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
-        base_request.setContentParameters(j_post);
-    }
-
-    public boolean restoreRequest() {
-        HttpSession session = myRequest.getSession(false);
-        if (session == null) return false;
-        synchronized (session) {
-            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
-            if (j_uri != null) {
-                // check if the request is for the same url as the original and restore
-                // params if it was a post
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                if (j_uri.equals(buf.toString())) {
-                    String method = (String)session.getAttribute(__J_METHOD);
-                    myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
-                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
-                    if (j_post != null) {
-                        MultiMap<String> map = new MultiMap<String>();
-                        for (String key : j_post.keySet()) {
-                            for (String val : j_post.getList(key)) {
-                                map.add(key, val);
-                            }
-                        }
-                        restoreFormParameters(map, myRequest);
-                    }
-                    session.removeAttribute(FormAuthenticator.__J_URI);
-                    session.removeAttribute(__J_METHOD);
-                    session.removeAttribute(FormAuthenticator.__J_POST);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void saveRequest() {
-        // remember the current URI
-        HttpSession session = myRequest.getSession();
-        synchronized (session) {
-            // But only if it is not set already, or we save every uri that leads to a login form redirect
-            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
-                StringBuffer buf = myRequest.getRequestURL();
-                if (myRequest.getQueryString() != null)
-                    buf.append("?").append(myRequest.getQueryString());
-                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
-                session.setAttribute(__J_METHOD, myRequest.getMethod());
-
-                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
-                    MultiMap<String> formParameters = extractFormParameters(myRequest);
-                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
-                    for (String key : formParameters.keySet()) {
-                        for (Object value : formParameters.getValues(key)) {
-                            map.add(key, (String) value);
-                        }
-                    }
-                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
-                }
-            }
-        }
-    }
-
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.util.MultiMap;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
+import org.keycloak.util.MultivaluedHashMap;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
+    public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
+    protected Request myRequest;
+
+    public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
+        super(request, deployment);
+        this.myRequest = request; // for IDE/compilation purposes
+    }
+
+    protected MultiMap<String> extractFormParameters(Request base_request) {
+        MultiMap<String> formParameters = new MultiMap<String>();
+        base_request.extractFormParameters(formParameters);
+        return formParameters;
+    }
+    protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
+        base_request.setContentParameters(j_post);
+    }
+
+    public boolean restoreRequest() {
+        HttpSession session = myRequest.getSession(false);
+        if (session == null) return false;
+        synchronized (session) {
+            String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
+            if (j_uri != null) {
+                // check if the request is for the same url as the original and restore
+                // params if it was a post
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                if (j_uri.equals(buf.toString())) {
+                    String method = (String)session.getAttribute(__J_METHOD);
+                    myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
+                    MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
+                    if (j_post != null) {
+                        MultiMap<String> map = new MultiMap<String>();
+                        for (String key : j_post.keySet()) {
+                            for (String val : j_post.getList(key)) {
+                                map.add(key, val);
+                            }
+                        }
+                        restoreFormParameters(map, myRequest);
+                    }
+                    session.removeAttribute(FormAuthenticator.__J_URI);
+                    session.removeAttribute(__J_METHOD);
+                    session.removeAttribute(FormAuthenticator.__J_POST);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void saveRequest() {
+        // remember the current URI
+        HttpSession session = myRequest.getSession();
+        synchronized (session) {
+            // But only if it is not set already, or we save every uri that leads to a login form redirect
+            if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
+                StringBuffer buf = myRequest.getRequestURL();
+                if (myRequest.getQueryString() != null)
+                    buf.append("?").append(myRequest.getQueryString());
+                session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
+                session.setAttribute(__J_METHOD, myRequest.getMethod());
+
+                if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
+                    MultiMap<String> formParameters = extractFormParameters(myRequest);
+                    MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+                    for (String key : formParameters.keySet()) {
+                        for (Object value : formParameters.getValues(key)) {
+                            map.add(key, (String) value);
+                        }
+                    }
+                    session.setAttribute(CACHED_FORM_PARAMETERS, map);
+                }
+            }
+        }
+    }
+
+}
diff --git a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
index 6cd1e07..90b3c6a 100755
--- a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java
@@ -1,43 +1,43 @@
-package org.keycloak.adapters.jetty;
-
-import org.eclipse.jetty.server.Authentication;
-import org.eclipse.jetty.server.HttpChannel;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.UserIdentity;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
-
-import javax.servlet.ServletRequest;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
-
-    public KeycloakJettyAuthenticator() {
-        super();
-    }
-
-
-   @Override
-    protected Request resolveRequest(ServletRequest req) {
-        return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
-    }
-
-    @Override
-    protected Authentication createAuthentication(UserIdentity userIdentity) {
-        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
-            @Override
-            public void logout() {
-                logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest());
-            }
-        };
-    }
-
-    @Override
-    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
-        return new JettySessionTokenStore(request, resolvedDeployment);
-    }
-}
+package org.keycloak.adapters.jetty;
+
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.UserIdentity;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
+
+import javax.servlet.ServletRequest;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
+
+    public KeycloakJettyAuthenticator() {
+        super();
+    }
+
+
+   @Override
+    protected Request resolveRequest(ServletRequest req) {
+        return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
+    }
+
+    @Override
+    protected Authentication createAuthentication(UserIdentity userIdentity) {
+        return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
+            @Override
+            public void logout() {
+                logoutCurrent(HttpChannel.getCurrentHttpChannel().getRequest());
+            }
+        };
+    }
+
+    @Override
+    public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
+        return new JettySessionTokenStore(request, resolvedDeployment);
+    }
+}
diff --git a/integration/jetty/jetty-core/pom.xml b/integration/jetty/jetty-core/pom.xml
index 1919434..286f9cc 100755
--- a/integration/jetty/jetty-core/pom.xml
+++ b/integration/jetty/jetty-core/pom.xml
@@ -1,139 +1,139 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-jetty-core</artifactId>
-	<name>Keycloak Jetty Core Integration</name>
-    <properties>
-        <jetty9.version>8.1.16.v20140903</jetty9.version>
-        <keycloak.osgi.export>
-            org.keycloak.adapters.jetty.core.*
-        </keycloak.osgi.export>
-        <keycloak.osgi.import>
-            org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
-            javax.servlet.*;version="[2.5,4)";resolution:=optional,
-            org.keycloak.*;version="${project.version}",
-            *;resolution:=optional
-        </keycloak.osgi.import>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-adapter-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-security</artifactId>
-            <version>${jetty9.version}</version>
-            <scope>compile</scope>
-        </dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-
-            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <executions>
-                    <execution>
-                        <id>bundle-manifest</id>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>manifest</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <instructions>
-                        <Bundle-ClassPath>.</Bundle-ClassPath>
-                        <Bundle-Name>${project.name}</Bundle-Name>
-                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>${keycloak.osgi.import}</Import-Package>
-                        <Export-Package>${keycloak.osgi.export}</Export-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-jetty-core</artifactId>
+	<name>Keycloak Jetty Core Integration</name>
+    <properties>
+        <jetty9.version>8.1.16.v20140903</jetty9.version>
+        <keycloak.osgi.export>
+            org.keycloak.adapters.jetty.core.*
+        </keycloak.osgi.export>
+        <keycloak.osgi.import>
+            org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
+            javax.servlet.*;version="[2.5,4)";resolution:=optional,
+            org.keycloak.*;version="${project.version}",
+            *;resolution:=optional
+        </keycloak.osgi.import>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-adapter-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-security</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+            <!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-ClassPath>.</Bundle-ClassPath>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>${keycloak.osgi.import}</Import-Package>
+                        <Export-Package>${keycloak.osgi.export}</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java
index e1b0739..5c62a2d 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java
@@ -1,96 +1,96 @@
-package org.keycloak.adapters.jetty.core;
-
-import org.eclipse.jetty.server.Request;
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.KeycloakAccount;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.RequestAuthenticator;
-
-import javax.servlet.http.HttpSession;
-
-/**
- * Handle storage of token info in HTTP Session. Per-request object
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public abstract class AbstractJettySessionTokenStore implements AdapterTokenStore {
-    public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD";
-
-    private static final Logger log = Logger.getLogger(AbstractJettySessionTokenStore.class);
-
-    private Request request;
-    protected KeycloakDeployment deployment;
-
-    public AbstractJettySessionTokenStore(Request request, KeycloakDeployment deployment) {
-        this.request = request;
-        this.deployment = deployment;
-    }
-
-    @Override
-    public void checkCurrentToken() {
-        if (request.getSession(false) == null) return;
-        RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
-        if (session == null) return;
-
-        // just in case session got serialized
-        if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
-
-        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
-
-        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
-        // not be updated
-        boolean success = session.refreshExpiredToken(false);
-        if (success && session.isActive()) return;
-
-        // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
-        request.getSession().removeAttribute(KeycloakSecurityContext.class.getName());
-        request.getSession().invalidate();
-    }
-
-    @Override
-    public boolean isCached(RequestAuthenticator authenticator) {
-        if (request.getSession(false) == null || request.getSession().getAttribute(KeycloakSecurityContext.class.getName()) == null)
-            return false;
-        log.debug("remote logged in already. Establish state from session");
-
-        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
-        if (!deployment.getRealm().equals(securityContext.getRealm())) {
-            log.debug("Account from cookie is from a different realm than for the request.");
-            return false;
-        }
-
-        securityContext.setCurrentRequestInfo(deployment, this);
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-
-        JettyRequestAuthenticator jettyAuthenticator = (JettyRequestAuthenticator) authenticator;
-        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = AdapterUtils.createPrincipal(deployment, securityContext);
-        jettyAuthenticator.principal = principal;
-        restoreRequest();
-        return true;
-    }
-
-    @Override
-    public void saveAccountInfo(KeycloakAccount account) {
-        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
-        request.getSession().setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-    }
-
-    @Override
-    public void logout() {
-        HttpSession session = request.getSession(false);
-        if (session != null) {
-            session.removeAttribute(KeycloakSecurityContext.class.getName());
-        }
-    }
-
-    @Override
-    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
-        // no-op
-    }
-
-}
+package org.keycloak.adapters.jetty.core;
+
+import org.eclipse.jetty.server.Request;
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * Handle storage of token info in HTTP Session. Per-request object
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public abstract class AbstractJettySessionTokenStore implements AdapterTokenStore {
+    public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD";
+
+    private static final Logger log = Logger.getLogger(AbstractJettySessionTokenStore.class);
+
+    private Request request;
+    protected KeycloakDeployment deployment;
+
+    public AbstractJettySessionTokenStore(Request request, KeycloakDeployment deployment) {
+        this.request = request;
+        this.deployment = deployment;
+    }
+
+    @Override
+    public void checkCurrentToken() {
+        if (request.getSession(false) == null) return;
+        RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
+        if (session == null) return;
+
+        // just in case session got serialized
+        if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
+
+        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
+
+        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
+        // not be updated
+        boolean success = session.refreshExpiredToken(false);
+        if (success && session.isActive()) return;
+
+        // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
+        request.getSession().removeAttribute(KeycloakSecurityContext.class.getName());
+        request.getSession().invalidate();
+    }
+
+    @Override
+    public boolean isCached(RequestAuthenticator authenticator) {
+        if (request.getSession(false) == null || request.getSession().getAttribute(KeycloakSecurityContext.class.getName()) == null)
+            return false;
+        log.debug("remote logged in already. Establish state from session");
+
+        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) request.getSession().getAttribute(KeycloakSecurityContext.class.getName());
+        if (!deployment.getRealm().equals(securityContext.getRealm())) {
+            log.debug("Account from cookie is from a different realm than for the request.");
+            return false;
+        }
+
+        securityContext.setCurrentRequestInfo(deployment, this);
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+
+        JettyRequestAuthenticator jettyAuthenticator = (JettyRequestAuthenticator) authenticator;
+        KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = AdapterUtils.createPrincipal(deployment, securityContext);
+        jettyAuthenticator.principal = principal;
+        restoreRequest();
+        return true;
+    }
+
+    @Override
+    public void saveAccountInfo(KeycloakAccount account) {
+        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
+        request.getSession().setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+    }
+
+    @Override
+    public void logout() {
+        HttpSession session = request.getSession(false);
+        if (session != null) {
+            session.removeAttribute(KeycloakSecurityContext.class.getName());
+        }
+    }
+
+    @Override
+    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
+        // no-op
+    }
+
+}
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
index cb3ee3f..bde5ad0 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java
@@ -1,311 +1,311 @@
-package org.keycloak.adapters.jetty.core;
-
-import org.eclipse.jetty.security.DefaultUserIdentity;
-import org.eclipse.jetty.security.ServerAuthException;
-import org.eclipse.jetty.security.UserAuthentication;
-import org.eclipse.jetty.security.authentication.DeferredAuthentication;
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.security.authentication.LoginAuthenticator;
-import org.eclipse.jetty.server.Authentication;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.server.UserIdentity;
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.util.URIUtil;
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.AuthChallenge;
-import org.keycloak.adapters.AuthOutcome;
-import org.keycloak.adapters.AuthenticatedActionsHandler;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakConfigResolver;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.PreAuthActionsHandler;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.enums.TokenStore;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-
-import javax.security.auth.Subject;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthenticator {
-    public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
-    protected static final org.jboss.logging.Logger log = Logger.getLogger(AbstractKeycloakJettyAuthenticator.class);
-    protected AdapterDeploymentContext deploymentContext;
-    protected NodesRegistrationManagement nodesRegistrationManagement;
-    protected AdapterConfig adapterConfig;
-    protected KeycloakConfigResolver configResolver;
-    protected String errorPage;
-
-    public AbstractKeycloakJettyAuthenticator() {
-        super();
-    }
-
-    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
-        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
-        if (json == null) {
-            return null;
-        }
-        return new ByteArrayInputStream(json.getBytes());
-    }
-
-    public AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
-        AdapterTokenStore store = (AdapterTokenStore) request.getAttribute(TOKEN_STORE_NOTE);
-        if (store != null) {
-            return store;
-        }
-
-        if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
-            store = createSessionTokenStore(request, resolvedDeployment);
-        } else {
-            store = new JettyCookieTokenStore(request, facade, resolvedDeployment);
-        }
-
-        request.setAttribute(TOKEN_STORE_NOTE, store);
-        return store;
-    }
-
-    public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
-
-    public void logoutCurrent(Request request) {
-        AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
-        KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
-        if (ksc != null) {
-            JettyHttpFacade facade = new JettyHttpFacade(request, null);
-            KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-            if (ksc instanceof RefreshableKeycloakSecurityContext) {
-                ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
-            }
-
-            AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
-            tokenStore.logout();
-            request.removeAttribute(KeycloakSecurityContext.class.getName());
-        }
-    }
-
-    public static UserIdentity createIdentity(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(principal.getKeycloakSecurityContext());
-        if (roles == null) {
-            roles = new HashSet<String>();
-        }
-        Subject theSubject = new Subject();
-        String[] theRoles = new String[roles.size()];
-        roles.toArray(theRoles);
-
-        return new DefaultUserIdentity(theSubject, principal, theRoles);
-    }
-
-    @Override
-    public void setConfiguration(AuthConfiguration configuration) {
-        //super.setConfiguration(configuration);
-        initializeKeycloak();
-        String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
-        setErrorPage(error);
-    }
-
-    private void setErrorPage(String path) {
-        if (path == null || path.trim().length() == 0) {
-        } else {
-            if (!path.startsWith("/")) {
-                path = "/" + path;
-            }
-            errorPage = path;
-
-            if (errorPage.indexOf('?') > 0)
-                errorPage = errorPage.substring(0, errorPage.indexOf('?'));
-        }
-    }
-
-    @Override
-    public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException {
-        return true;
-    }
-
-    public AdapterConfig getAdapterConfig() {
-        return adapterConfig;
-    }
-
-    public void setAdapterConfig(AdapterConfig adapterConfig) {
-        this.adapterConfig = adapterConfig;
-    }
-
-    public KeycloakConfigResolver getConfigResolver() {
-        return configResolver;
-    }
-
-    public void setConfigResolver(KeycloakConfigResolver configResolver) {
-        this.configResolver = configResolver;
-    }
-
-    @SuppressWarnings("UseSpecificCatch")
-    public void initializeKeycloak() {
-        nodesRegistrationManagement = new NodesRegistrationManagement();
-
-        ServletContext theServletContext = null;
-        ContextHandler.Context currentContext = ContextHandler.getCurrentContext();
-        if (currentContext != null) {
-            String contextPath = currentContext.getContextPath();
-
-            if ("".equals(contextPath)) {
-                // This could be the case in osgi environment when deploying apps through pax whiteboard extension.
-                theServletContext = currentContext;
-            } else {
-                theServletContext = currentContext.getContext(contextPath);
-            }
-        }
-
-        // Jetty 9.1.x servlet context will be null :(
-        if (configResolver == null && theServletContext != null) {
-            String configResolverClass = theServletContext.getInitParameter("keycloak.config.resolver");
-            if (configResolverClass != null) {
-                try {
-                    configResolver = (KeycloakConfigResolver) ContextHandler.getCurrentContext().getClassLoader().loadClass(configResolverClass).newInstance();
-                    log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
-                } catch (Exception ex) {
-                    log.infov("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
-                }
-            }
-        }
-
-        if (configResolver != null) {
-            deploymentContext = new AdapterDeploymentContext(configResolver);
-        } else if (adapterConfig != null) {
-            KeycloakDeployment kd = KeycloakDeploymentBuilder.build(adapterConfig);
-            deploymentContext = new AdapterDeploymentContext(kd);
-        } else if (theServletContext != null) {
-            InputStream configInputStream = getConfigInputStream(theServletContext);
-            if (configInputStream != null) {
-                deploymentContext = new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(configInputStream));
-            }
-        }
-        if (deploymentContext == null) {
-            deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
-        }
-        if (theServletContext != null)
-            theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
-    }
-
-    private InputStream getConfigInputStream(ServletContext servletContext) {
-        InputStream is = getJSONFromServletContext(servletContext);
-        if (is == null) {
-            String path = servletContext.getInitParameter("keycloak.config.file");
-            if (path == null) {
-                is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
-            } else {
-                try {
-                    is = new FileInputStream(path);
-                } catch (FileNotFoundException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-        return is;
-    }
-
-    @Override
-    public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException {
-        if (log.isTraceEnabled()) {
-            log.trace("*** authenticate");
-        }
-        Request request = resolveRequest(req);
-        JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (deployment == null || !deployment.isConfigured()) {
-            log.debug("*** deployment isn't configured return false");
-            return Authentication.UNAUTHENTICATED;
-        }
-        PreAuthActionsHandler handler = new PreAuthActionsHandler(new JettyUserSessionManagement(request.getSessionManager()), deploymentContext, facade);
-        if (handler.handleRequest()) {
-            return Authentication.SEND_SUCCESS;
-        }
-        if (!mandatory)
-            return new DeferredAuthentication(this);
-        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
-        nodesRegistrationManagement.tryRegister(deployment);
-
-        tokenStore.checkCurrentToken();
-        JettyRequestAuthenticator authenticator = createRequestAuthenticator(request, facade, deployment, tokenStore);
-        AuthOutcome outcome = authenticator.authenticate();
-        if (outcome == AuthOutcome.AUTHENTICATED) {
-            if (facade.isEnded()) {
-                return Authentication.SEND_SUCCESS;
-            }
-
-            Authentication authentication = register(request, authenticator.principal);
-            AuthenticatedActionsHandler authenticatedActionsHandler = new AuthenticatedActionsHandler(deployment, facade);
-            if (authenticatedActionsHandler.handledRequest()) {
-                return Authentication.SEND_SUCCESS;
-            }
-            return authentication;
-
-        }
-        AuthChallenge challenge = authenticator.getChallenge();
-        if (challenge != null) {
-            if (challenge.errorPage() && errorPage != null) {
-                Response response = (Response)res;
-                try {
-                    response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), errorPage)));
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
-
-            }
-            challenge.challenge(facade);
-        }
-        return Authentication.SEND_CONTINUE;
-    }
-
-
-    protected abstract Request resolveRequest(ServletRequest req);
-
-    protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
-                                                                   KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
-        return new JettyRequestAuthenticator(facade, deployment, tokenStore, -1, request);
-    }
-
-    @Override
-    public String getAuthMethod() {
-        return "KEYCLOAK";
-    }
-
-    protected Authentication register(Request request, KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        request.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
-        Authentication authentication = request.getAuthentication();
-        if (!(authentication instanceof KeycloakAuthentication)) {
-            UserIdentity userIdentity = createIdentity(principal);
-            authentication = createAuthentication(userIdentity);
-            request.setAuthentication(authentication);
-        }
-        return authentication;
-    }
-
-    protected abstract Authentication createAuthentication(UserIdentity userIdentity);
-
-    public static abstract class KeycloakAuthentication extends UserAuthentication {
-        public KeycloakAuthentication(String method, UserIdentity userIdentity) {
-            super(method, userIdentity);
-        }
-
-    }
-}
+package org.keycloak.adapters.jetty.core;
+
+import org.eclipse.jetty.security.DefaultUserIdentity;
+import org.eclipse.jetty.security.ServerAuthException;
+import org.eclipse.jetty.security.UserAuthentication;
+import org.eclipse.jetty.security.authentication.DeferredAuthentication;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.security.authentication.LoginAuthenticator;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.URIUtil;
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.AuthChallenge;
+import org.keycloak.adapters.AuthOutcome;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.PreAuthActionsHandler;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.enums.TokenStore;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+
+import javax.security.auth.Subject;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthenticator {
+    public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
+    protected static final org.jboss.logging.Logger log = Logger.getLogger(AbstractKeycloakJettyAuthenticator.class);
+    protected AdapterDeploymentContext deploymentContext;
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+    protected AdapterConfig adapterConfig;
+    protected KeycloakConfigResolver configResolver;
+    protected String errorPage;
+
+    public AbstractKeycloakJettyAuthenticator() {
+        super();
+    }
+
+    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        if (json == null) {
+            return null;
+        }
+        return new ByteArrayInputStream(json.getBytes());
+    }
+
+    public AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
+        AdapterTokenStore store = (AdapterTokenStore) request.getAttribute(TOKEN_STORE_NOTE);
+        if (store != null) {
+            return store;
+        }
+
+        if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
+            store = createSessionTokenStore(request, resolvedDeployment);
+        } else {
+            store = new JettyCookieTokenStore(request, facade, resolvedDeployment);
+        }
+
+        request.setAttribute(TOKEN_STORE_NOTE, store);
+        return store;
+    }
+
+    public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
+
+    public void logoutCurrent(Request request) {
+        AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
+        KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
+        if (ksc != null) {
+            JettyHttpFacade facade = new JettyHttpFacade(request, null);
+            KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+            if (ksc instanceof RefreshableKeycloakSecurityContext) {
+                ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
+            }
+
+            AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
+            tokenStore.logout();
+            request.removeAttribute(KeycloakSecurityContext.class.getName());
+        }
+    }
+
+    public static UserIdentity createIdentity(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(principal.getKeycloakSecurityContext());
+        if (roles == null) {
+            roles = new HashSet<String>();
+        }
+        Subject theSubject = new Subject();
+        String[] theRoles = new String[roles.size()];
+        roles.toArray(theRoles);
+
+        return new DefaultUserIdentity(theSubject, principal, theRoles);
+    }
+
+    @Override
+    public void setConfiguration(AuthConfiguration configuration) {
+        //super.setConfiguration(configuration);
+        initializeKeycloak();
+        String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
+        setErrorPage(error);
+    }
+
+    private void setErrorPage(String path) {
+        if (path == null || path.trim().length() == 0) {
+        } else {
+            if (!path.startsWith("/")) {
+                path = "/" + path;
+            }
+            errorPage = path;
+
+            if (errorPage.indexOf('?') > 0)
+                errorPage = errorPage.substring(0, errorPage.indexOf('?'));
+        }
+    }
+
+    @Override
+    public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException {
+        return true;
+    }
+
+    public AdapterConfig getAdapterConfig() {
+        return adapterConfig;
+    }
+
+    public void setAdapterConfig(AdapterConfig adapterConfig) {
+        this.adapterConfig = adapterConfig;
+    }
+
+    public KeycloakConfigResolver getConfigResolver() {
+        return configResolver;
+    }
+
+    public void setConfigResolver(KeycloakConfigResolver configResolver) {
+        this.configResolver = configResolver;
+    }
+
+    @SuppressWarnings("UseSpecificCatch")
+    public void initializeKeycloak() {
+        nodesRegistrationManagement = new NodesRegistrationManagement();
+
+        ServletContext theServletContext = null;
+        ContextHandler.Context currentContext = ContextHandler.getCurrentContext();
+        if (currentContext != null) {
+            String contextPath = currentContext.getContextPath();
+
+            if ("".equals(contextPath)) {
+                // This could be the case in osgi environment when deploying apps through pax whiteboard extension.
+                theServletContext = currentContext;
+            } else {
+                theServletContext = currentContext.getContext(contextPath);
+            }
+        }
+
+        // Jetty 9.1.x servlet context will be null :(
+        if (configResolver == null && theServletContext != null) {
+            String configResolverClass = theServletContext.getInitParameter("keycloak.config.resolver");
+            if (configResolverClass != null) {
+                try {
+                    configResolver = (KeycloakConfigResolver) ContextHandler.getCurrentContext().getClassLoader().loadClass(configResolverClass).newInstance();
+                    log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
+                } catch (Exception ex) {
+                    log.infov("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
+                }
+            }
+        }
+
+        if (configResolver != null) {
+            deploymentContext = new AdapterDeploymentContext(configResolver);
+        } else if (adapterConfig != null) {
+            KeycloakDeployment kd = KeycloakDeploymentBuilder.build(adapterConfig);
+            deploymentContext = new AdapterDeploymentContext(kd);
+        } else if (theServletContext != null) {
+            InputStream configInputStream = getConfigInputStream(theServletContext);
+            if (configInputStream != null) {
+                deploymentContext = new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(configInputStream));
+            }
+        }
+        if (deploymentContext == null) {
+            deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+        }
+        if (theServletContext != null)
+            theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+    }
+
+    private InputStream getConfigInputStream(ServletContext servletContext) {
+        InputStream is = getJSONFromServletContext(servletContext);
+        if (is == null) {
+            String path = servletContext.getInitParameter("keycloak.config.file");
+            if (path == null) {
+                is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
+            } else {
+                try {
+                    is = new FileInputStream(path);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return is;
+    }
+
+    @Override
+    public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException {
+        if (log.isTraceEnabled()) {
+            log.trace("*** authenticate");
+        }
+        Request request = resolveRequest(req);
+        JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment == null || !deployment.isConfigured()) {
+            log.debug("*** deployment isn't configured return false");
+            return Authentication.UNAUTHENTICATED;
+        }
+        PreAuthActionsHandler handler = new PreAuthActionsHandler(new JettyUserSessionManagement(request.getSessionManager()), deploymentContext, facade);
+        if (handler.handleRequest()) {
+            return Authentication.SEND_SUCCESS;
+        }
+        if (!mandatory)
+            return new DeferredAuthentication(this);
+        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
+        nodesRegistrationManagement.tryRegister(deployment);
+
+        tokenStore.checkCurrentToken();
+        JettyRequestAuthenticator authenticator = createRequestAuthenticator(request, facade, deployment, tokenStore);
+        AuthOutcome outcome = authenticator.authenticate();
+        if (outcome == AuthOutcome.AUTHENTICATED) {
+            if (facade.isEnded()) {
+                return Authentication.SEND_SUCCESS;
+            }
+
+            Authentication authentication = register(request, authenticator.principal);
+            AuthenticatedActionsHandler authenticatedActionsHandler = new AuthenticatedActionsHandler(deployment, facade);
+            if (authenticatedActionsHandler.handledRequest()) {
+                return Authentication.SEND_SUCCESS;
+            }
+            return authentication;
+
+        }
+        AuthChallenge challenge = authenticator.getChallenge();
+        if (challenge != null) {
+            if (challenge.errorPage() && errorPage != null) {
+                Response response = (Response)res;
+                try {
+                    response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), errorPage)));
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+
+            }
+            challenge.challenge(facade);
+        }
+        return Authentication.SEND_CONTINUE;
+    }
+
+
+    protected abstract Request resolveRequest(ServletRequest req);
+
+    protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
+                                                                   KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+        return new JettyRequestAuthenticator(facade, deployment, tokenStore, -1, request);
+    }
+
+    @Override
+    public String getAuthMethod() {
+        return "KEYCLOAK";
+    }
+
+    protected Authentication register(Request request, KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        request.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+        Authentication authentication = request.getAuthentication();
+        if (!(authentication instanceof KeycloakAuthentication)) {
+            UserIdentity userIdentity = createIdentity(principal);
+            authentication = createAuthentication(userIdentity);
+            request.setAuthentication(authentication);
+        }
+        return authentication;
+    }
+
+    protected abstract Authentication createAuthentication(UserIdentity userIdentity);
+
+    public static abstract class KeycloakAuthentication extends UserAuthentication {
+        public KeycloakAuthentication(String method, UserIdentity userIdentity) {
+            super(method, userIdentity);
+        }
+
+    }
+}
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java
index c294106..c25629e 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java
@@ -1,191 +1,191 @@
-package org.keycloak.adapters.jetty.core;
-
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.util.MultivaluedHashMap;
-import org.keycloak.util.UriUtils;
-
-import javax.security.cert.X509Certificate;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettyHttpFacade implements HttpFacade {
-    protected org.eclipse.jetty.server.Request request;
-    protected HttpServletResponse response;
-    protected RequestFacade requestFacade = new RequestFacade();
-    protected ResponseFacade responseFacade = new ResponseFacade();
-    protected MultivaluedHashMap<String, String> queryParameters;
-
-    protected class RequestFacade implements Request {
-        @Override
-        public String getURI() {
-            StringBuffer buf = request.getRequestURL();
-            if (request.getQueryString() != null) {
-                buf.append('?').append(request.getQueryString());
-            }
-            return buf.toString();
-        }
-
-        @Override
-        public boolean isSecure() {
-            return request.isSecure();
-        }
-
-        @Override
-        public String getQueryParamValue(String paramName) {
-            if (queryParameters == null) {
-                queryParameters = UriUtils.decodeQueryString(request.getQueryString());
-            }
-            return queryParameters.getFirst(paramName);
-        }
-
-        @Override
-        public Cookie getCookie(String cookieName) {
-            if (request.getCookies() == null) return null;
-            javax.servlet.http.Cookie cookie = null;
-            for (javax.servlet.http.Cookie c : request.getCookies()) {
-                if (c.getName().equals(cookieName)) {
-                    cookie = c;
-                    break;
-                }
-            }
-            if (cookie == null) return null;
-            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
-        }
-
-        @Override
-        public List<String> getHeaders(String name) {
-            Enumeration<String> headers = request.getHeaders(name);
-            if (headers == null) return null;
-            List<String> list = new ArrayList<String>();
-            while (headers.hasMoreElements()) {
-                list.add(headers.nextElement());
-            }
-            return list;
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            try {
-                return request.getInputStream();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public String getMethod() {
-            return request.getMethod();
-        }
-
-        @Override
-        public String getHeader(String name) {
-            return request.getHeader(name);
-        }
-
-        @Override
-        public String getRemoteAddr() {
-            return request.getRemoteAddr();
-        }
-    }
-
-    protected class ResponseFacade implements Response {
-        protected boolean ended;
-
-        @Override
-        public void setStatus(int status) {
-            response.setStatus(status);
-        }
-
-        @Override
-        public void addHeader(String name, String value) {
-            response.addHeader(name, value);
-        }
-
-        @Override
-        public void setHeader(String name, String value) {
-            response.setHeader(name, value);
-        }
-
-        @Override
-        public void resetCookie(String name, String path) {
-            setCookie(name, "", null, path, 0, false, false);
-        }
-
-        @Override
-        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
-            javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(name, value);
-            if (domain != null) cookie.setDomain(domain);
-            if (path != null) cookie.setPath(path);
-            if (secure) cookie.setSecure(true);
-            if (httpOnly) cookie.setHttpOnly(httpOnly);
-            cookie.setMaxAge(maxAge);
-            response.addCookie(cookie);
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            try {
-                return response.getOutputStream();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public void sendError(int code, String message) {
-            try {
-                response.sendError(code, message);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public void end() {
-            ended = true;
-        }
-
-        public boolean isEnded() {
-            return ended;
-        }
-    }
-
-    public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
-        this.request = request;
-        this.response = response;
-    }
-
-    @Override
-    public Request getRequest() {
-        return requestFacade;
-    }
-
-    @Override
-    public Response getResponse() {
-        return responseFacade;
-    }
-
-    @Override
-    public KeycloakSecurityContext getSecurityContext() {
-        return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
-    }
-
-    @Override
-    public X509Certificate[] getCertificateChain() {
-        throw new IllegalStateException("Not supported yet");
-    }
-
-    public boolean isEnded() {
-        return responseFacade.isEnded();
-    }
-}
+package org.keycloak.adapters.jetty.core;
+
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.util.MultivaluedHashMap;
+import org.keycloak.util.UriUtils;
+
+import javax.security.cert.X509Certificate;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettyHttpFacade implements HttpFacade {
+    protected org.eclipse.jetty.server.Request request;
+    protected HttpServletResponse response;
+    protected RequestFacade requestFacade = new RequestFacade();
+    protected ResponseFacade responseFacade = new ResponseFacade();
+    protected MultivaluedHashMap<String, String> queryParameters;
+
+    protected class RequestFacade implements Request {
+        @Override
+        public String getURI() {
+            StringBuffer buf = request.getRequestURL();
+            if (request.getQueryString() != null) {
+                buf.append('?').append(request.getQueryString());
+            }
+            return buf.toString();
+        }
+
+        @Override
+        public boolean isSecure() {
+            return request.isSecure();
+        }
+
+        @Override
+        public String getQueryParamValue(String paramName) {
+            if (queryParameters == null) {
+                queryParameters = UriUtils.decodeQueryString(request.getQueryString());
+            }
+            return queryParameters.getFirst(paramName);
+        }
+
+        @Override
+        public Cookie getCookie(String cookieName) {
+            if (request.getCookies() == null) return null;
+            javax.servlet.http.Cookie cookie = null;
+            for (javax.servlet.http.Cookie c : request.getCookies()) {
+                if (c.getName().equals(cookieName)) {
+                    cookie = c;
+                    break;
+                }
+            }
+            if (cookie == null) return null;
+            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
+        }
+
+        @Override
+        public List<String> getHeaders(String name) {
+            Enumeration<String> headers = request.getHeaders(name);
+            if (headers == null) return null;
+            List<String> list = new ArrayList<String>();
+            while (headers.hasMoreElements()) {
+                list.add(headers.nextElement());
+            }
+            return list;
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            try {
+                return request.getInputStream();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public String getMethod() {
+            return request.getMethod();
+        }
+
+        @Override
+        public String getHeader(String name) {
+            return request.getHeader(name);
+        }
+
+        @Override
+        public String getRemoteAddr() {
+            return request.getRemoteAddr();
+        }
+    }
+
+    protected class ResponseFacade implements Response {
+        protected boolean ended;
+
+        @Override
+        public void setStatus(int status) {
+            response.setStatus(status);
+        }
+
+        @Override
+        public void addHeader(String name, String value) {
+            response.addHeader(name, value);
+        }
+
+        @Override
+        public void setHeader(String name, String value) {
+            response.setHeader(name, value);
+        }
+
+        @Override
+        public void resetCookie(String name, String path) {
+            setCookie(name, "", null, path, 0, false, false);
+        }
+
+        @Override
+        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
+            javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(name, value);
+            if (domain != null) cookie.setDomain(domain);
+            if (path != null) cookie.setPath(path);
+            if (secure) cookie.setSecure(true);
+            if (httpOnly) cookie.setHttpOnly(httpOnly);
+            cookie.setMaxAge(maxAge);
+            response.addCookie(cookie);
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            try {
+                return response.getOutputStream();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void sendError(int code, String message) {
+            try {
+                response.sendError(code, message);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void end() {
+            ended = true;
+        }
+
+        public boolean isEnded() {
+            return ended;
+        }
+    }
+
+    public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
+        this.request = request;
+        this.response = response;
+    }
+
+    @Override
+    public Request getRequest() {
+        return requestFacade;
+    }
+
+    @Override
+    public Response getResponse() {
+        return responseFacade;
+    }
+
+    @Override
+    public KeycloakSecurityContext getSecurityContext() {
+        return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain() {
+        throw new IllegalStateException("Not supported yet");
+    }
+
+    public boolean isEnded() {
+        return responseFacade.isEnded();
+    }
+}
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java
index 4b0db24..fbe20ba 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java
@@ -1,85 +1,85 @@
-package org.keycloak.adapters.jetty.core;
-
-import org.eclipse.jetty.server.Request;
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakAccount;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.OAuthRequestAuthenticator;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.RequestAuthenticator;
-
-import javax.servlet.http.HttpSession;
-import java.security.Principal;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettyRequestAuthenticator extends RequestAuthenticator {
-    protected static final Logger log = Logger.getLogger(JettyRequestAuthenticator.class);
-    protected Request request;
-    protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
-
-    public JettyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
-        super(facade, deployment, tokenStore, sslRedirectPort);
-        this.request = request;
-    }
-
-    @Override
-    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
-        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
-    }
-
-    @Override
-    protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
-        principal = skp;
-        final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
-        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
-        KeycloakAccount account = new KeycloakAccount() {
-
-            @Override
-            public Principal getPrincipal() {
-                return skp;
-            }
-
-            @Override
-            public Set<String> getRoles() {
-                return roles;
-            }
-
-            @Override
-            public KeycloakSecurityContext getKeycloakSecurityContext() {
-                return securityContext;
-            }
-
-        };
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-        this.tokenStore.saveAccountInfo(account);
-    }
-
-    @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
-        this.principal = principal;
-        RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
-        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
-        if (log.isDebugEnabled()) {
-            log.debug("Completing bearer authentication. Bearer roles: " + roles);
-        }
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-    }
-
-
-    @Override
-    protected String getHttpSessionId(boolean create) {
-        HttpSession session = request.getSession(create);
-        return session != null ? session.getId() : null;
-    }
-
-
-}
+package org.keycloak.adapters.jetty.core;
+
+import org.eclipse.jetty.server.Request;
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OAuthRequestAuthenticator;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+
+import javax.servlet.http.HttpSession;
+import java.security.Principal;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettyRequestAuthenticator extends RequestAuthenticator {
+    protected static final Logger log = Logger.getLogger(JettyRequestAuthenticator.class);
+    protected Request request;
+    protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
+
+    public JettyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
+        super(facade, deployment, tokenStore, sslRedirectPort);
+        this.request = request;
+    }
+
+    @Override
+    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
+        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
+    }
+
+    @Override
+    protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
+        principal = skp;
+        final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
+        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
+        KeycloakAccount account = new KeycloakAccount() {
+
+            @Override
+            public Principal getPrincipal() {
+                return skp;
+            }
+
+            @Override
+            public Set<String> getRoles() {
+                return roles;
+            }
+
+            @Override
+            public KeycloakSecurityContext getKeycloakSecurityContext() {
+                return securityContext;
+            }
+
+        };
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+        this.tokenStore.saveAccountInfo(account);
+    }
+
+    @Override
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
+        this.principal = principal;
+        RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
+        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
+        if (log.isDebugEnabled()) {
+            log.debug("Completing bearer authentication. Bearer roles: " + roles);
+        }
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+    }
+
+
+    @Override
+    protected String getHttpSessionId(boolean create) {
+        HttpSession session = request.getSession(create);
+        return session != null ? session.getId() : null;
+    }
+
+
+}
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java
index ca226d4..4158503 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java
@@ -1,36 +1,36 @@
-package org.keycloak.adapters.jetty.core;
-
-import org.eclipse.jetty.server.SessionManager;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.UserSessionManagement;
-
-import javax.servlet.http.HttpSession;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JettyUserSessionManagement implements UserSessionManagement {
-    private static final org.jboss.logging.Logger log = Logger.getLogger(JettyUserSessionManagement.class);
-    protected SessionManager sessionManager;
-
-    public JettyUserSessionManagement(SessionManager sessionManager) {
-        this.sessionManager = sessionManager;
-    }
-
-    @Override
-    public void logoutAll() {
-        // todo not implemented yet
-    }
-
-    @Override
-    public void logoutHttpSessions(List<String> ids) {
-        log.trace("---> logoutHttpSessions");
-        for (String id : ids) {
-            HttpSession httpSession = sessionManager.getHttpSession(id);
-            if (httpSession != null) httpSession.invalidate();
-        }
-
-    }
-}
+package org.keycloak.adapters.jetty.core;
+
+import org.eclipse.jetty.server.SessionManager;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.UserSessionManagement;
+
+import javax.servlet.http.HttpSession;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JettyUserSessionManagement implements UserSessionManagement {
+    private static final org.jboss.logging.Logger log = Logger.getLogger(JettyUserSessionManagement.class);
+    protected SessionManager sessionManager;
+
+    public JettyUserSessionManagement(SessionManager sessionManager) {
+        this.sessionManager = sessionManager;
+    }
+
+    @Override
+    public void logoutAll() {
+        // todo not implemented yet
+    }
+
+    @Override
+    public void logoutHttpSessions(List<String> ids) {
+        log.trace("---> logoutHttpSessions");
+        for (String id : ids) {
+            HttpSession httpSession = sessionManager.getHttpSession(id);
+            if (httpSession != null) httpSession.invalidate();
+        }
+
+    }
+}
diff --git a/integration/jetty/pom.xml b/integration/jetty/pom.xml
index c3eb1f3..52a0033 100755
--- a/integration/jetty/pom.xml
+++ b/integration/jetty/pom.xml
@@ -1,22 +1,22 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak Jetty Integration</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-jetty-integration-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>jetty-core</module>
-        <module>jetty8.1</module>
-        <module>jetty9.2</module>
-        <module>jetty9.1</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak Jetty Integration</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-jetty-integration-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>jetty-core</module>
+        <module>jetty8.1</module>
+        <module>jetty9.2</module>
+        <module>jetty9.1</module>
+    </modules>
+</project>
diff --git a/integration/js/pom.xml b/integration/js/pom.xml
index a3c747b..dd1c5e5 100755
--- a/integration/js/pom.xml
+++ b/integration/js/pom.xml
@@ -1,49 +1,49 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-js-adapter</artifactId>
-	<name>Keycloak JS Integration</name>
-	<description />
-
-	<dependencies>
-	</dependencies>
-
-	<build>
-        <plugins>
-            <plugin>
-                <groupId>com.samaxes.maven</groupId>
-                <artifactId>minify-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>min-js</id>
-                        <phase>compile</phase>
-                        <configuration>
-                            <charset>utf-8</charset>
-                            <webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
-                            <jsSourceDir>.</jsSourceDir>
-                            <jsSourceFiles>
-                                <jsSourceFile>keycloak.js</jsSourceFile>
-                            </jsSourceFiles>
-
-                            <webappTargetDir>${project.build.directory}/classes</webappTargetDir>
-                            <jsTargetDir>.</jsTargetDir>
-                            <jsFinalFile>keycloak.js</jsFinalFile>
-                        </configuration>
-                        <goals>
-                            <goal>minify</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-js-adapter</artifactId>
+	<name>Keycloak JS Integration</name>
+	<description />
+
+	<dependencies>
+	</dependencies>
+
+	<build>
+        <plugins>
+            <plugin>
+                <groupId>com.samaxes.maven</groupId>
+                <artifactId>minify-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>min-js</id>
+                        <phase>compile</phase>
+                        <configuration>
+                            <charset>utf-8</charset>
+                            <webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
+                            <jsSourceDir>.</jsSourceDir>
+                            <jsSourceFiles>
+                                <jsSourceFile>keycloak.js</jsSourceFile>
+                            </jsSourceFiles>
+
+                            <webappTargetDir>${project.build.directory}/classes</webappTargetDir>
+                            <jsTargetDir>.</jsTargetDir>
+                            <jsFinalFile>keycloak.js</jsFinalFile>
+                        </configuration>
+                        <goals>
+                            <goal>minify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/js/src/main/resources/keycloak.js b/integration/js/src/main/resources/keycloak.js
index 7ff1959..798bfdd 100755
--- a/integration/js/src/main/resources/keycloak.js
+++ b/integration/js/src/main/resources/keycloak.js
@@ -1,872 +1,872 @@
-(function( window, undefined ) {
-
-    var Keycloak = function (config) {
-        if (!(this instanceof Keycloak)) {
-            return new Keycloak(config);
-        }
-
-        var kc = this;
-        var adapter;
-        var refreshQueue = [];
-
-        var loginIframe = {
-            enable: true,
-            callbackMap: [],
-            interval: 5
-        };
-
-        kc.init = function (initOptions) {
-            kc.authenticated = false;
-
-            if (window.Cordova) {
-                adapter = loadAdapter('cordova');
-            } else {
-                adapter = loadAdapter();
-            }
-
-            if (initOptions) {
-                if (typeof initOptions.checkLoginIframe !== 'undefined') {
-                    loginIframe.enable = initOptions.checkLoginIframe;
-                }
-
-                if (initOptions.checkLoginIframeInterval) {
-                    loginIframe.interval = initOptions.checkLoginIframeInterval;
-                }
-
-                if (initOptions.onLoad === 'login-required') {
-                    kc.loginRequired = true;
-                }
-            }
-
-            var promise = createPromise();
-
-            var initPromise = createPromise();
-            initPromise.promise.success(function() {
-                kc.onReady && kc.onReady(kc.authenticated);
-                promise.setSuccess(kc.authenticated);
-            }).error(function() {
-                promise.setError();
-            });
-
-            var configPromise = loadConfig(config);
-
-            function onLoad() {
-                var doLogin = function(prompt) {
-                    if (!prompt) {
-                        options.prompt = 'none';
-                    }
-                    kc.login(options).success(function () {
-                        initPromise.setSuccess();
-                    }).error(function () {
-                        initPromise.setError();
-                    });
-                }
-
-                var options = {};
-                switch (initOptions.onLoad) {
-                    case 'check-sso':
-                        if (loginIframe.enable) {
-                            setupCheckLoginIframe().success(function() {
-                                checkLoginIframe().success(function () {
-                                    doLogin(false);
-                                }).error(function () {
-                                    initPromise.setSuccess();
-                                });
-                            });
-                        } else {
-                            doLogin(false);
-                        }
-                        break;
-                    case 'login-required':
-                        doLogin(true);
-                        break;
-                    default:
-                        throw 'Invalid value for onLoad';
-                }
-            }
-
-            function processInit() {
-                var callback = parseCallback(window.location.href);
-
-                if (callback) {
-                    setupCheckLoginIframe();
-                    window.history.replaceState({}, null, callback.newUrl);
-                    processCallback(callback, initPromise);
-                    return;
-                } else if (initOptions) {
-                    if (initOptions.token || initOptions.refreshToken) {
-                        setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
-
-                        if (loginIframe.enable) {
-                            setupCheckLoginIframe().success(function() {
-                                checkLoginIframe().success(function () {
-                                    initPromise.setSuccess();
-                                }).error(function () {
-                                    if (initOptions.onLoad) {
-                                        onLoad();
-                                    }
-                                });
-                            });
-                        } else {
-                            initPromise.setSuccess();
-                        }
-                    } else if (initOptions.onLoad) {
-                        onLoad();
-                    }
-                } else {
-                    initPromise.setSuccess();
-                }
-            }
-
-            configPromise.success(processInit);
-            configPromise.error(function() {
-                promise.setError();
-            });
-
-            return promise.promise;
-        }
-
-        kc.login = function (options) {
-            return adapter.login(options);
-        }
-
-        kc.createLoginUrl = function(options) {
-            var state = createUUID();
-
-            var redirectUri = adapter.redirectUri(options);
-            if (options && options.prompt) {
-                redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
-            }
-
-            sessionStorage.oauthState = JSON.stringify({ state: state, redirectUri: encodeURIComponent(redirectUri) });
-
-            var action = 'auth';
-            if (options && options.action == 'register') {
-                action = 'registrations';
-            }
-
-            var url = getRealmUrl()
-                + '/protocol/openid-connect/' + action
-                + '?client_id=' + encodeURIComponent(kc.clientId)
-                + '&redirect_uri=' + encodeURIComponent(redirectUri)
-                + '&state=' + encodeURIComponent(state)
-                + '&response_type=code';
-
-            if (options && options.prompt) {
-                url += '&prompt=' + options.prompt;
-            }
-
-            if (options && options.loginHint) {
-                url += '&login_hint=' + options.loginHint;
-            }
-
-            if (options && options.idpHint) {
-                url += '&kc_idp_hint=' + options.idpHint;
-            }
-
-            return url;
-        }
-
-        kc.logout = function(options) {
-            return adapter.logout(options);
-        }
-
-        kc.createLogoutUrl = function(options) {
-            var url = getRealmUrl()
-                + '/protocol/openid-connect/logout'
-                + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options));
-
-            return url;
-        }
-
-        kc.createAccountUrl = function(options) {
-            var url = getRealmUrl()
-                + '/account'
-                + '?referrer=' + encodeURIComponent(kc.clientId)
-                + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
-
-            return url;
-        }
-
-        kc.accountManagement = function() {
-            return adapter.accountManagement();
-        }
-
-        kc.hasRealmRole = function (role) {
-            var access = kc.realmAccess;
-            return !!access && access.roles.indexOf(role) >= 0;
-        }
-
-        kc.hasResourceRole = function(role, resource) {
-            if (!kc.resourceAccess) {
-                return false;
-            }
-
-            var access = kc.resourceAccess[resource || kc.clientId];
-            return !!access && access.roles.indexOf(role) >= 0;
-        }
-
-        kc.loadUserProfile = function() {
-            var url = getRealmUrl() + '/account';
-            var req = new XMLHttpRequest();
-            req.open('GET', url, true);
-            req.setRequestHeader('Accept', 'application/json');
-            req.setRequestHeader('Authorization', 'bearer ' + kc.token);
-
-            var promise = createPromise();
-
-            req.onreadystatechange = function () {
-                if (req.readyState == 4) {
-                    if (req.status == 200) {
-                        kc.profile = JSON.parse(req.responseText);
-                        promise.setSuccess(kc.profile);
-                    } else {
-                        promise.setError();
-                    }
-                }
-            }
-
-            req.send();
-
-            return promise.promise;
-        }
-
-        kc.loadUserInfo = function() {
-            var url = getRealmUrl() + '/protocol/openid-connect/userinfo';
-            var req = new XMLHttpRequest();
-            req.open('GET', url, true);
-            req.setRequestHeader('Accept', 'application/json');
-            req.setRequestHeader('Authorization', 'bearer ' + kc.token);
-
-            var promise = createPromise();
-
-            req.onreadystatechange = function () {
-                if (req.readyState == 4) {
-                    if (req.status == 200) {
-                        kc.userInfo = JSON.parse(req.responseText);
-                        promise.setSuccess(kc.userInfo);
-                    } else {
-                        promise.setError();
-                    }
-                }
-            }
-
-            req.send();
-
-            return promise.promise;
-        }
-
-        kc.isTokenExpired = function(minValidity) {
-            if (!kc.tokenParsed || !kc.refreshToken) {
-                throw 'Not authenticated';
-            }
-
-            var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000);
-            if (minValidity) {
-                expiresIn -= minValidity;
-            }
-
-            return expiresIn < 0;
-        }
-
-        kc.updateToken = function(minValidity) {
-            var promise = createPromise();
-
-            if (!kc.tokenParsed || !kc.refreshToken) {
-                promise.setError();
-                return promise.promise;
-            }
-
-            minValidity = minValidity || 5;
-
-            var exec = function() {
-                if (!kc.isTokenExpired(minValidity)) {
-                    promise.setSuccess(false);
-                } else {
-                    var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
-                    var url = getRealmUrl() + '/protocol/openid-connect/token';
-
-                    refreshQueue.push(promise);
-
-                    if (refreshQueue.length == 1) {
-                        var req = new XMLHttpRequest();
-                        req.open('POST', url, true);
-                        req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
-
-                        if (kc.clientId && kc.clientSecret) {
-                            req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
-                        } else {
-                            params += '&client_id=' + encodeURIComponent(kc.clientId);
-                        }
-
-                        req.onreadystatechange = function () {
-                            if (req.readyState == 4) {
-                                if (req.status == 200) {
-                                    var tokenResponse = JSON.parse(req.responseText);
-                                    setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
-                                    kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
-                                    for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
-                                        p.setSuccess(true);
-                                    }
-                                } else {
-                                    kc.onAuthRefreshError && kc.onAuthRefreshError();
-                                    for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
-                                        p.setError(true);
-                                    }
-                                }
-                            }
-                        };
-
-                        req.send(params);
-                    }
-                }
-            }
-
-            if (loginIframe.enable) {
-                var iframePromise = checkLoginIframe();
-                iframePromise.success(function() {
-                    exec();
-                }).error(function() {
-                    promise.setError();
-                });
-            } else {
-                exec();
-            }
-
-            return promise.promise;
-        }
-
-        kc.clearToken = function() {
-            if (kc.token) {
-                setToken(null, null, null);
-                kc.onAuthLogout && kc.onAuthLogout();
-                if (kc.loginRequired) {
-                    kc.login();
-                }
-            }
-        }
-
-        function getRealmUrl() {
-            if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') {
-                return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm);
-            } else {
-                return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm);
-            }
-        }
-
-        function getOrigin() {
-            if (!window.location.origin) {
-                return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
-            } else {
-                return window.location.origin;
-            }
-        }
-
-        function processCallback(oauth, promise) {
-            var code = oauth.code;
-            var error = oauth.error;
-            var prompt = oauth.prompt;
-
-            if (code) {
-                var params = 'code=' + code + '&grant_type=authorization_code';
-                var url = getRealmUrl() + '/protocol/openid-connect/token';
-
-                var req = new XMLHttpRequest();
-                req.open('POST', url, true);
-                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
-
-                if (kc.clientId && kc.clientSecret) {
-                    req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
-                } else {
-                    params += '&client_id=' + encodeURIComponent(kc.clientId);
-                }
-
-                params += '&redirect_uri=' + oauth.redirectUri;
-
-                req.withCredentials = true;
-
-                req.onreadystatechange = function() {
-                    if (req.readyState == 4) {
-                        if (req.status == 200) {
-                            var tokenResponse = JSON.parse(req.responseText);
-                            setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
-                            kc.onAuthSuccess && kc.onAuthSuccess();
-                            promise && promise.setSuccess();
-                        } else {
-                            kc.onAuthError && kc.onAuthError();
-                            promise && promise.setError();
-                        }
-                    }
-                };
-
-                req.send(params);
-            } else if (error) {
-                if (prompt != 'none') {
-                    kc.onAuthError && kc.onAuthError();
-                    promise && promise.setError();
-                } else {
-                    promise && promise.setSuccess();
-                }
-            }
-        }
-
-        function loadConfig(url) {
-            var promise = createPromise();
-            var configUrl;
-
-            if (!config) {
-                configUrl = 'keycloak.json';
-            } else if (typeof config === 'string') {
-                configUrl = config;
-            }
-
-            if (configUrl) {
-                var req = new XMLHttpRequest();
-                req.open('GET', configUrl, true);
-                req.setRequestHeader('Accept', 'application/json');
-
-                req.onreadystatechange = function () {
-                    if (req.readyState == 4) {
-                        if (req.status == 200) {
-                            var config = JSON.parse(req.responseText);
-
-                            kc.authServerUrl = config['auth-server-url'];
-                            kc.realm = config['realm'];
-                            kc.clientId = config['resource'];
-                            kc.clientSecret = (config['credentials'] || {})['secret'];
-
-                            promise.setSuccess();
-                        } else {
-                            promise.setError();
-                        }
-                    }
-                };
-
-                req.send();
-            } else {
-                if (!config['url']) {
-                    var scripts = document.getElementsByTagName('script');
-                    for (var i = 0; i < scripts.length; i++) {
-                        if (scripts[i].src.match(/.*keycloak\.js/)) {
-                            config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
-                            break;
-                        }
-                    }
-                }
-
-                if (!config.realm) {
-                    throw 'realm missing';
-                }
-
-                if (!config.clientId) {
-                    throw 'clientId missing';
-                }
-
-                kc.authServerUrl = config.url;
-                kc.realm = config.realm;
-                kc.clientId = config.clientId;
-                kc.clientSecret = (config.credentials || {}).secret;
-
-                promise.setSuccess();
-            }
-
-            return promise.promise;
-        }
-
-        function setToken(token, refreshToken, idToken) {
-            if (token) {
-                kc.token = token;
-                kc.tokenParsed = decodeToken(token);
-                var sessionId = kc.realm + '/' + kc.tokenParsed.sub;
-                if (kc.tokenParsed.session_state) {
-                    sessionId = sessionId + '/' + kc.tokenParsed.session_state;
-                }
-                kc.sessionId = sessionId;
-                kc.authenticated = true;
-                kc.subject = kc.tokenParsed.sub;
-                kc.realmAccess = kc.tokenParsed.realm_access;
-                kc.resourceAccess = kc.tokenParsed.resource_access;
-            } else {
-                delete kc.token;
-                delete kc.tokenParsed;
-                delete kc.subject;
-                delete kc.realmAccess;
-                delete kc.resourceAccess;
-
-                kc.authenticated = false;
-            }
-
-            if (refreshToken) {
-                kc.refreshToken = refreshToken;
-                kc.refreshTokenParsed = decodeToken(refreshToken);
-            } else {
-                delete kc.refreshToken;
-                delete kc.refreshTokenParsed;
-            }
-
-            if (idToken) {
-                kc.idToken = idToken;
-                kc.idTokenParsed = decodeToken(idToken);
-            } else {
-                delete kc.idToken;
-                delete kc.idTokenParsed;
-            }
-        }
-
-        function decodeToken(str) {
-            str = str.split('.')[1];
-
-            str = str.replace('/-/g', '+');
-            str = str.replace('/_/g', '/');
-            switch (str.length % 4)
-            {
-                case 0:
-                    break;
-                case 2:
-                    str += '==';
-                    break;
-                case 3:
-                    str += '=';
-                    break;
-                default:
-                    throw 'Invalid token';
-            }
-
-            str = (str + '===').slice(0, str.length + (str.length % 4));
-            str = str.replace(/-/g, '+').replace(/_/g, '/');
-
-            str = decodeURIComponent(escape(atob(str)));
-
-            str = JSON.parse(str);
-            return str;
-        }
-
-        function createUUID() {
-            var s = [];
-            var hexDigits = '0123456789abcdef';
-            for (var i = 0; i < 36; i++) {
-                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
-            }
-            s[14] = '4';
-            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
-            s[8] = s[13] = s[18] = s[23] = '-';
-            var uuid = s.join('');
-            return uuid;
-        }
-
-        kc.callback_id = 0;
-
-        function createCallbackId() {
-            var id = '<id: ' + (kc.callback_id++) + (Math.random()) + '>';
-            return id;
-
-        }
-
-        function parseCallback(url) {
-            if (url.indexOf('?') != -1) {
-                var oauth = {};
-
-                oauth.newUrl = url.split('?')[0];
-                var paramString = url.split('?')[1];
-                var fragIndex = paramString.indexOf('#');
-                if (fragIndex != -1) {
-                    paramString = paramString.substring(0, fragIndex);
-                }
-                var params = paramString.split('&');
-                for (var i = 0; i < params.length; i++) {
-                    var p = params[i].split('=');
-                    switch (decodeURIComponent(p[0])) {
-                        case 'code':
-                            oauth.code = p[1];
-                            break;
-                        case 'error':
-                            oauth.error = p[1];
-                            break;
-                        case 'state':
-                            oauth.state = decodeURIComponent(p[1]);
-                            break;
-                        case 'redirect_fragment':
-                            oauth.fragment = decodeURIComponent(p[1]);
-                            break;
-                        case 'prompt':
-                            oauth.prompt = p[1];
-                            break;
-                        default:
-                            oauth.newUrl += (oauth.newUrl.indexOf('?') == -1 ? '?' : '&') + p[0] + '=' + p[1];
-                            break;
-                    }
-                }
-
-                var sessionState = sessionStorage.oauthState && JSON.parse(sessionStorage.oauthState);
-
-                if (sessionState && (oauth.code || oauth.error) && oauth.state && oauth.state == sessionState.state) {
-                    delete sessionStorage.oauthState;
-
-                    oauth.redirectUri = sessionState.redirectUri;
-
-                    if (oauth.fragment) {
-                        oauth.newUrl += '#' + oauth.fragment;
-                    }
-
-                    return oauth;
-                }
-            }
-        }
-
-        function createPromise() {
-            var p = {
-                setSuccess: function(result) {
-                    p.success = true;
-                    p.result = result;
-                    if (p.successCallback) {
-                        p.successCallback(result);
-                    }
-                },
-
-                setError: function(result) {
-                    p.error = true;
-                    p.result = result;
-                    if (p.errorCallback) {
-                        p.errorCallback(result);
-                    }
-                },
-
-                promise: {
-                    success: function(callback) {
-                        if (p.success) {
-                            callback(p.result);
-                        } else if (!p.error) {
-                            p.successCallback = callback;
-                        }
-                        return p.promise;
-                    },
-                    error: function(callback) {
-                        if (p.error) {
-                            callback(p.result);
-                        } else if (!p.success) {
-                            p.errorCallback = callback;
-                        }
-                        return p.promise;
-                    }
-                }
-            }
-            return p;
-        }
-
-        function setupCheckLoginIframe() {
-            var promise = createPromise();
-
-            if (!loginIframe.enable) {
-                promise.setSuccess();
-                return promise.promise;
-            }
-
-            if (loginIframe.iframe) {
-                promise.setSuccess();
-                return promise.promise;
-            }
-
-            var iframe = document.createElement('iframe');
-            loginIframe.iframe = iframe;
-
-            iframe.onload = function() {
-                var realmUrl = getRealmUrl();
-                if (realmUrl.charAt(0) === '/') {
-                    loginIframe.iframeOrigin = getOrigin();
-                } else {
-                    loginIframe.iframeOrigin = realmUrl.substring(0, realmUrl.indexOf('/', 8));
-                }
-                promise.setSuccess();
-
-                setTimeout(check, loginIframe.interval * 1000);
-            }
-
-            var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId) + '&origin=' + getOrigin();
-            iframe.setAttribute('src', src );
-            iframe.style.display = 'none';
-            document.body.appendChild(iframe);
-
-            var messageCallback = function(event) {
-                if (event.origin !== loginIframe.iframeOrigin) {
-                    return;
-                }
-                var data = JSON.parse(event.data);
-                var promise = loginIframe.callbackMap[data.callbackId];
-                delete loginIframe.callbackMap[data.callbackId];
-
-                if ((!kc.sessionId || kc.sessionId == data.session) && data.loggedIn) {
-                    promise.setSuccess();
-                } else {
-                    kc.clearToken();
-                    promise.setError();
-                }
-            };
-            window.addEventListener('message', messageCallback, false);
-
-            var check = function() {
-                checkLoginIframe();
-                if (kc.token) {
-                    setTimeout(check, loginIframe.interval * 1000);
-                }
-            };
-
-            return promise.promise;
-        }
-
-        function checkLoginIframe() {
-            var promise = createPromise();
-
-            if (loginIframe.iframe && loginIframe.iframeOrigin) {
-                var msg = {};
-                msg.callbackId = createCallbackId();
-                loginIframe.callbackMap[msg.callbackId] = promise;
-                var origin = loginIframe.iframeOrigin;
-                loginIframe.iframe.contentWindow.postMessage(JSON.stringify(msg), origin);
-            } else {
-                promise.setSuccess();
-            }
-
-            return promise.promise;
-        }
-
-        function loadAdapter(type) {
-            if (!type || type == 'default') {
-                return {
-                    login: function(options) {
-                        window.location.href = kc.createLoginUrl(options);
-                        return createPromise().promise;
-                    },
-
-                    logout: function(options) {
-                        window.location.href = kc.createLogoutUrl(options);
-                        return createPromise().promise;
-                    },
-
-                    accountManagement : function() {
-                        window.location.href = kc.createAccountUrl();
-                        return createPromise().promise;
-                    },
-
-                    redirectUri: function(options) {
-                        if (options && options.redirectUri) {
-                            return options.redirectUri;
-                        } else if (kc.redirectUri) {
-                            return kc.redirectUri;
-                        } else {
-                            var redirectUri = location.href;
-                            if (location.hash) {
-                                redirectUri = redirectUri.substring(0, location.href.indexOf('#'));
-                                redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
-                            }
-                            return redirectUri;
-                        }
-                    }
-                };
-            }
-
-            if (type == 'cordova') {
-                loginIframe.enable = false;
-
-                return {
-                    login: function(options) {
-                        var promise = createPromise();
-
-                        var o = 'location=no';
-                        if (options && options.prompt == 'none') {
-                            o += ',hidden=yes';
-                        }
-
-                        var loginUrl = kc.createLoginUrl(options);
-                        var ref = window.open(loginUrl, '_blank', o);
-
-                        var callback;
-                        var error;
-
-                        ref.addEventListener('loadstart', function(event) {
-                            if (event.url.indexOf('http://localhost') == 0) {
-                                callback = parseCallback(event.url);
-                                ref.close();
-                            }
-                        });
-
-                        ref.addEventListener('loaderror', function(event) {
-                            if (event.url.indexOf('http://localhost') != 0) {
-                                error = true;
-                                ref.close();
-                            }
-                        });
-
-                        ref.addEventListener('exit', function(event) {
-                            if (error || !callback) {
-                                promise.setError();
-                            } else {
-                                processCallback(callback, promise);
-                            }
-                        });
-
-                        return promise.promise;
-                    },
-
-                    logout: function(options) {
-                        var promise = createPromise();
-
-                        var logoutUrl = kc.createLogoutUrl(options);
-                        var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
-
-                        var error;
-
-                        ref.addEventListener('loadstart', function(event) {
-                            if (event.url.indexOf('http://localhost') == 0) {
-                                ref.close();
-                            }
-                        });
-
-                        ref.addEventListener('loaderror', function(event) {
-                            if (event.url.indexOf('http://localhost') != 0) {
-                                error = true;
-                                ref.close();
-                            }
-                        });
-
-                        ref.addEventListener('exit', function(event) {
-                            if (error) {
-                                promise.setError();
-                            } else {
-                                kc.clearToken();
-                                promise.setSuccess();
-                            }
-                        });
-
-                        return promise.promise;
-                    },
-
-                    accountManagement : function() {
-                        var accountUrl = kc.createAccountUrl();
-                        var ref = window.open(accountUrl, '_blank', 'location=no');
-                        ref.addEventListener('loadstart', function(event) {
-                            if (event.url.indexOf('http://localhost') == 0) {
-                                ref.close();
-                            }
-                        });
-                    },
-
-                    redirectUri: function(options) {
-                        return 'http://localhost';
-                    }
-                }
-            }
-
-            throw 'invalid adapter type: ' + type;
-        }
-    }
-
-    if ( typeof module === "object" && module && typeof module.exports === "object" ) {
-        module.exports = Keycloak;
-    } else {
-        window.Keycloak = Keycloak;
-
-        if ( typeof define === "function" && define.amd ) {
-            define( "keycloak", [], function () { return Keycloak; } );
-        }
-    }
-})( window );
+(function( window, undefined ) {
+
+    var Keycloak = function (config) {
+        if (!(this instanceof Keycloak)) {
+            return new Keycloak(config);
+        }
+
+        var kc = this;
+        var adapter;
+        var refreshQueue = [];
+
+        var loginIframe = {
+            enable: true,
+            callbackMap: [],
+            interval: 5
+        };
+
+        kc.init = function (initOptions) {
+            kc.authenticated = false;
+
+            if (window.Cordova) {
+                adapter = loadAdapter('cordova');
+            } else {
+                adapter = loadAdapter();
+            }
+
+            if (initOptions) {
+                if (typeof initOptions.checkLoginIframe !== 'undefined') {
+                    loginIframe.enable = initOptions.checkLoginIframe;
+                }
+
+                if (initOptions.checkLoginIframeInterval) {
+                    loginIframe.interval = initOptions.checkLoginIframeInterval;
+                }
+
+                if (initOptions.onLoad === 'login-required') {
+                    kc.loginRequired = true;
+                }
+            }
+
+            var promise = createPromise();
+
+            var initPromise = createPromise();
+            initPromise.promise.success(function() {
+                kc.onReady && kc.onReady(kc.authenticated);
+                promise.setSuccess(kc.authenticated);
+            }).error(function() {
+                promise.setError();
+            });
+
+            var configPromise = loadConfig(config);
+
+            function onLoad() {
+                var doLogin = function(prompt) {
+                    if (!prompt) {
+                        options.prompt = 'none';
+                    }
+                    kc.login(options).success(function () {
+                        initPromise.setSuccess();
+                    }).error(function () {
+                        initPromise.setError();
+                    });
+                }
+
+                var options = {};
+                switch (initOptions.onLoad) {
+                    case 'check-sso':
+                        if (loginIframe.enable) {
+                            setupCheckLoginIframe().success(function() {
+                                checkLoginIframe().success(function () {
+                                    doLogin(false);
+                                }).error(function () {
+                                    initPromise.setSuccess();
+                                });
+                            });
+                        } else {
+                            doLogin(false);
+                        }
+                        break;
+                    case 'login-required':
+                        doLogin(true);
+                        break;
+                    default:
+                        throw 'Invalid value for onLoad';
+                }
+            }
+
+            function processInit() {
+                var callback = parseCallback(window.location.href);
+
+                if (callback) {
+                    setupCheckLoginIframe();
+                    window.history.replaceState({}, null, callback.newUrl);
+                    processCallback(callback, initPromise);
+                    return;
+                } else if (initOptions) {
+                    if (initOptions.token || initOptions.refreshToken) {
+                        setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
+
+                        if (loginIframe.enable) {
+                            setupCheckLoginIframe().success(function() {
+                                checkLoginIframe().success(function () {
+                                    initPromise.setSuccess();
+                                }).error(function () {
+                                    if (initOptions.onLoad) {
+                                        onLoad();
+                                    }
+                                });
+                            });
+                        } else {
+                            initPromise.setSuccess();
+                        }
+                    } else if (initOptions.onLoad) {
+                        onLoad();
+                    }
+                } else {
+                    initPromise.setSuccess();
+                }
+            }
+
+            configPromise.success(processInit);
+            configPromise.error(function() {
+                promise.setError();
+            });
+
+            return promise.promise;
+        }
+
+        kc.login = function (options) {
+            return adapter.login(options);
+        }
+
+        kc.createLoginUrl = function(options) {
+            var state = createUUID();
+
+            var redirectUri = adapter.redirectUri(options);
+            if (options && options.prompt) {
+                redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
+            }
+
+            sessionStorage.oauthState = JSON.stringify({ state: state, redirectUri: encodeURIComponent(redirectUri) });
+
+            var action = 'auth';
+            if (options && options.action == 'register') {
+                action = 'registrations';
+            }
+
+            var url = getRealmUrl()
+                + '/protocol/openid-connect/' + action
+                + '?client_id=' + encodeURIComponent(kc.clientId)
+                + '&redirect_uri=' + encodeURIComponent(redirectUri)
+                + '&state=' + encodeURIComponent(state)
+                + '&response_type=code';
+
+            if (options && options.prompt) {
+                url += '&prompt=' + options.prompt;
+            }
+
+            if (options && options.loginHint) {
+                url += '&login_hint=' + options.loginHint;
+            }
+
+            if (options && options.idpHint) {
+                url += '&kc_idp_hint=' + options.idpHint;
+            }
+
+            return url;
+        }
+
+        kc.logout = function(options) {
+            return adapter.logout(options);
+        }
+
+        kc.createLogoutUrl = function(options) {
+            var url = getRealmUrl()
+                + '/protocol/openid-connect/logout'
+                + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options));
+
+            return url;
+        }
+
+        kc.createAccountUrl = function(options) {
+            var url = getRealmUrl()
+                + '/account'
+                + '?referrer=' + encodeURIComponent(kc.clientId)
+                + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
+
+            return url;
+        }
+
+        kc.accountManagement = function() {
+            return adapter.accountManagement();
+        }
+
+        kc.hasRealmRole = function (role) {
+            var access = kc.realmAccess;
+            return !!access && access.roles.indexOf(role) >= 0;
+        }
+
+        kc.hasResourceRole = function(role, resource) {
+            if (!kc.resourceAccess) {
+                return false;
+            }
+
+            var access = kc.resourceAccess[resource || kc.clientId];
+            return !!access && access.roles.indexOf(role) >= 0;
+        }
+
+        kc.loadUserProfile = function() {
+            var url = getRealmUrl() + '/account';
+            var req = new XMLHttpRequest();
+            req.open('GET', url, true);
+            req.setRequestHeader('Accept', 'application/json');
+            req.setRequestHeader('Authorization', 'bearer ' + kc.token);
+
+            var promise = createPromise();
+
+            req.onreadystatechange = function () {
+                if (req.readyState == 4) {
+                    if (req.status == 200) {
+                        kc.profile = JSON.parse(req.responseText);
+                        promise.setSuccess(kc.profile);
+                    } else {
+                        promise.setError();
+                    }
+                }
+            }
+
+            req.send();
+
+            return promise.promise;
+        }
+
+        kc.loadUserInfo = function() {
+            var url = getRealmUrl() + '/protocol/openid-connect/userinfo';
+            var req = new XMLHttpRequest();
+            req.open('GET', url, true);
+            req.setRequestHeader('Accept', 'application/json');
+            req.setRequestHeader('Authorization', 'bearer ' + kc.token);
+
+            var promise = createPromise();
+
+            req.onreadystatechange = function () {
+                if (req.readyState == 4) {
+                    if (req.status == 200) {
+                        kc.userInfo = JSON.parse(req.responseText);
+                        promise.setSuccess(kc.userInfo);
+                    } else {
+                        promise.setError();
+                    }
+                }
+            }
+
+            req.send();
+
+            return promise.promise;
+        }
+
+        kc.isTokenExpired = function(minValidity) {
+            if (!kc.tokenParsed || !kc.refreshToken) {
+                throw 'Not authenticated';
+            }
+
+            var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000);
+            if (minValidity) {
+                expiresIn -= minValidity;
+            }
+
+            return expiresIn < 0;
+        }
+
+        kc.updateToken = function(minValidity) {
+            var promise = createPromise();
+
+            if (!kc.tokenParsed || !kc.refreshToken) {
+                promise.setError();
+                return promise.promise;
+            }
+
+            minValidity = minValidity || 5;
+
+            var exec = function() {
+                if (!kc.isTokenExpired(minValidity)) {
+                    promise.setSuccess(false);
+                } else {
+                    var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
+                    var url = getRealmUrl() + '/protocol/openid-connect/token';
+
+                    refreshQueue.push(promise);
+
+                    if (refreshQueue.length == 1) {
+                        var req = new XMLHttpRequest();
+                        req.open('POST', url, true);
+                        req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+
+                        if (kc.clientId && kc.clientSecret) {
+                            req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
+                        } else {
+                            params += '&client_id=' + encodeURIComponent(kc.clientId);
+                        }
+
+                        req.onreadystatechange = function () {
+                            if (req.readyState == 4) {
+                                if (req.status == 200) {
+                                    var tokenResponse = JSON.parse(req.responseText);
+                                    setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
+                                    kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
+                                    for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
+                                        p.setSuccess(true);
+                                    }
+                                } else {
+                                    kc.onAuthRefreshError && kc.onAuthRefreshError();
+                                    for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
+                                        p.setError(true);
+                                    }
+                                }
+                            }
+                        };
+
+                        req.send(params);
+                    }
+                }
+            }
+
+            if (loginIframe.enable) {
+                var iframePromise = checkLoginIframe();
+                iframePromise.success(function() {
+                    exec();
+                }).error(function() {
+                    promise.setError();
+                });
+            } else {
+                exec();
+            }
+
+            return promise.promise;
+        }
+
+        kc.clearToken = function() {
+            if (kc.token) {
+                setToken(null, null, null);
+                kc.onAuthLogout && kc.onAuthLogout();
+                if (kc.loginRequired) {
+                    kc.login();
+                }
+            }
+        }
+
+        function getRealmUrl() {
+            if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') {
+                return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm);
+            } else {
+                return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm);
+            }
+        }
+
+        function getOrigin() {
+            if (!window.location.origin) {
+                return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
+            } else {
+                return window.location.origin;
+            }
+        }
+
+        function processCallback(oauth, promise) {
+            var code = oauth.code;
+            var error = oauth.error;
+            var prompt = oauth.prompt;
+
+            if (code) {
+                var params = 'code=' + code + '&grant_type=authorization_code';
+                var url = getRealmUrl() + '/protocol/openid-connect/token';
+
+                var req = new XMLHttpRequest();
+                req.open('POST', url, true);
+                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+
+                if (kc.clientId && kc.clientSecret) {
+                    req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
+                } else {
+                    params += '&client_id=' + encodeURIComponent(kc.clientId);
+                }
+
+                params += '&redirect_uri=' + oauth.redirectUri;
+
+                req.withCredentials = true;
+
+                req.onreadystatechange = function() {
+                    if (req.readyState == 4) {
+                        if (req.status == 200) {
+                            var tokenResponse = JSON.parse(req.responseText);
+                            setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token']);
+                            kc.onAuthSuccess && kc.onAuthSuccess();
+                            promise && promise.setSuccess();
+                        } else {
+                            kc.onAuthError && kc.onAuthError();
+                            promise && promise.setError();
+                        }
+                    }
+                };
+
+                req.send(params);
+            } else if (error) {
+                if (prompt != 'none') {
+                    kc.onAuthError && kc.onAuthError();
+                    promise && promise.setError();
+                } else {
+                    promise && promise.setSuccess();
+                }
+            }
+        }
+
+        function loadConfig(url) {
+            var promise = createPromise();
+            var configUrl;
+
+            if (!config) {
+                configUrl = 'keycloak.json';
+            } else if (typeof config === 'string') {
+                configUrl = config;
+            }
+
+            if (configUrl) {
+                var req = new XMLHttpRequest();
+                req.open('GET', configUrl, true);
+                req.setRequestHeader('Accept', 'application/json');
+
+                req.onreadystatechange = function () {
+                    if (req.readyState == 4) {
+                        if (req.status == 200) {
+                            var config = JSON.parse(req.responseText);
+
+                            kc.authServerUrl = config['auth-server-url'];
+                            kc.realm = config['realm'];
+                            kc.clientId = config['resource'];
+                            kc.clientSecret = (config['credentials'] || {})['secret'];
+
+                            promise.setSuccess();
+                        } else {
+                            promise.setError();
+                        }
+                    }
+                };
+
+                req.send();
+            } else {
+                if (!config['url']) {
+                    var scripts = document.getElementsByTagName('script');
+                    for (var i = 0; i < scripts.length; i++) {
+                        if (scripts[i].src.match(/.*keycloak\.js/)) {
+                            config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
+                            break;
+                        }
+                    }
+                }
+
+                if (!config.realm) {
+                    throw 'realm missing';
+                }
+
+                if (!config.clientId) {
+                    throw 'clientId missing';
+                }
+
+                kc.authServerUrl = config.url;
+                kc.realm = config.realm;
+                kc.clientId = config.clientId;
+                kc.clientSecret = (config.credentials || {}).secret;
+
+                promise.setSuccess();
+            }
+
+            return promise.promise;
+        }
+
+        function setToken(token, refreshToken, idToken) {
+            if (token) {
+                kc.token = token;
+                kc.tokenParsed = decodeToken(token);
+                var sessionId = kc.realm + '/' + kc.tokenParsed.sub;
+                if (kc.tokenParsed.session_state) {
+                    sessionId = sessionId + '/' + kc.tokenParsed.session_state;
+                }
+                kc.sessionId = sessionId;
+                kc.authenticated = true;
+                kc.subject = kc.tokenParsed.sub;
+                kc.realmAccess = kc.tokenParsed.realm_access;
+                kc.resourceAccess = kc.tokenParsed.resource_access;
+            } else {
+                delete kc.token;
+                delete kc.tokenParsed;
+                delete kc.subject;
+                delete kc.realmAccess;
+                delete kc.resourceAccess;
+
+                kc.authenticated = false;
+            }
+
+            if (refreshToken) {
+                kc.refreshToken = refreshToken;
+                kc.refreshTokenParsed = decodeToken(refreshToken);
+            } else {
+                delete kc.refreshToken;
+                delete kc.refreshTokenParsed;
+            }
+
+            if (idToken) {
+                kc.idToken = idToken;
+                kc.idTokenParsed = decodeToken(idToken);
+            } else {
+                delete kc.idToken;
+                delete kc.idTokenParsed;
+            }
+        }
+
+        function decodeToken(str) {
+            str = str.split('.')[1];
+
+            str = str.replace('/-/g', '+');
+            str = str.replace('/_/g', '/');
+            switch (str.length % 4)
+            {
+                case 0:
+                    break;
+                case 2:
+                    str += '==';
+                    break;
+                case 3:
+                    str += '=';
+                    break;
+                default:
+                    throw 'Invalid token';
+            }
+
+            str = (str + '===').slice(0, str.length + (str.length % 4));
+            str = str.replace(/-/g, '+').replace(/_/g, '/');
+
+            str = decodeURIComponent(escape(atob(str)));
+
+            str = JSON.parse(str);
+            return str;
+        }
+
+        function createUUID() {
+            var s = [];
+            var hexDigits = '0123456789abcdef';
+            for (var i = 0; i < 36; i++) {
+                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
+            }
+            s[14] = '4';
+            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
+            s[8] = s[13] = s[18] = s[23] = '-';
+            var uuid = s.join('');
+            return uuid;
+        }
+
+        kc.callback_id = 0;
+
+        function createCallbackId() {
+            var id = '<id: ' + (kc.callback_id++) + (Math.random()) + '>';
+            return id;
+
+        }
+
+        function parseCallback(url) {
+            if (url.indexOf('?') != -1) {
+                var oauth = {};
+
+                oauth.newUrl = url.split('?')[0];
+                var paramString = url.split('?')[1];
+                var fragIndex = paramString.indexOf('#');
+                if (fragIndex != -1) {
+                    paramString = paramString.substring(0, fragIndex);
+                }
+                var params = paramString.split('&');
+                for (var i = 0; i < params.length; i++) {
+                    var p = params[i].split('=');
+                    switch (decodeURIComponent(p[0])) {
+                        case 'code':
+                            oauth.code = p[1];
+                            break;
+                        case 'error':
+                            oauth.error = p[1];
+                            break;
+                        case 'state':
+                            oauth.state = decodeURIComponent(p[1]);
+                            break;
+                        case 'redirect_fragment':
+                            oauth.fragment = decodeURIComponent(p[1]);
+                            break;
+                        case 'prompt':
+                            oauth.prompt = p[1];
+                            break;
+                        default:
+                            oauth.newUrl += (oauth.newUrl.indexOf('?') == -1 ? '?' : '&') + p[0] + '=' + p[1];
+                            break;
+                    }
+                }
+
+                var sessionState = sessionStorage.oauthState && JSON.parse(sessionStorage.oauthState);
+
+                if (sessionState && (oauth.code || oauth.error) && oauth.state && oauth.state == sessionState.state) {
+                    delete sessionStorage.oauthState;
+
+                    oauth.redirectUri = sessionState.redirectUri;
+
+                    if (oauth.fragment) {
+                        oauth.newUrl += '#' + oauth.fragment;
+                    }
+
+                    return oauth;
+                }
+            }
+        }
+
+        function createPromise() {
+            var p = {
+                setSuccess: function(result) {
+                    p.success = true;
+                    p.result = result;
+                    if (p.successCallback) {
+                        p.successCallback(result);
+                    }
+                },
+
+                setError: function(result) {
+                    p.error = true;
+                    p.result = result;
+                    if (p.errorCallback) {
+                        p.errorCallback(result);
+                    }
+                },
+
+                promise: {
+                    success: function(callback) {
+                        if (p.success) {
+                            callback(p.result);
+                        } else if (!p.error) {
+                            p.successCallback = callback;
+                        }
+                        return p.promise;
+                    },
+                    error: function(callback) {
+                        if (p.error) {
+                            callback(p.result);
+                        } else if (!p.success) {
+                            p.errorCallback = callback;
+                        }
+                        return p.promise;
+                    }
+                }
+            }
+            return p;
+        }
+
+        function setupCheckLoginIframe() {
+            var promise = createPromise();
+
+            if (!loginIframe.enable) {
+                promise.setSuccess();
+                return promise.promise;
+            }
+
+            if (loginIframe.iframe) {
+                promise.setSuccess();
+                return promise.promise;
+            }
+
+            var iframe = document.createElement('iframe');
+            loginIframe.iframe = iframe;
+
+            iframe.onload = function() {
+                var realmUrl = getRealmUrl();
+                if (realmUrl.charAt(0) === '/') {
+                    loginIframe.iframeOrigin = getOrigin();
+                } else {
+                    loginIframe.iframeOrigin = realmUrl.substring(0, realmUrl.indexOf('/', 8));
+                }
+                promise.setSuccess();
+
+                setTimeout(check, loginIframe.interval * 1000);
+            }
+
+            var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId) + '&origin=' + getOrigin();
+            iframe.setAttribute('src', src );
+            iframe.style.display = 'none';
+            document.body.appendChild(iframe);
+
+            var messageCallback = function(event) {
+                if (event.origin !== loginIframe.iframeOrigin) {
+                    return;
+                }
+                var data = JSON.parse(event.data);
+                var promise = loginIframe.callbackMap[data.callbackId];
+                delete loginIframe.callbackMap[data.callbackId];
+
+                if ((!kc.sessionId || kc.sessionId == data.session) && data.loggedIn) {
+                    promise.setSuccess();
+                } else {
+                    kc.clearToken();
+                    promise.setError();
+                }
+            };
+            window.addEventListener('message', messageCallback, false);
+
+            var check = function() {
+                checkLoginIframe();
+                if (kc.token) {
+                    setTimeout(check, loginIframe.interval * 1000);
+                }
+            };
+
+            return promise.promise;
+        }
+
+        function checkLoginIframe() {
+            var promise = createPromise();
+
+            if (loginIframe.iframe && loginIframe.iframeOrigin) {
+                var msg = {};
+                msg.callbackId = createCallbackId();
+                loginIframe.callbackMap[msg.callbackId] = promise;
+                var origin = loginIframe.iframeOrigin;
+                loginIframe.iframe.contentWindow.postMessage(JSON.stringify(msg), origin);
+            } else {
+                promise.setSuccess();
+            }
+
+            return promise.promise;
+        }
+
+        function loadAdapter(type) {
+            if (!type || type == 'default') {
+                return {
+                    login: function(options) {
+                        window.location.href = kc.createLoginUrl(options);
+                        return createPromise().promise;
+                    },
+
+                    logout: function(options) {
+                        window.location.href = kc.createLogoutUrl(options);
+                        return createPromise().promise;
+                    },
+
+                    accountManagement : function() {
+                        window.location.href = kc.createAccountUrl();
+                        return createPromise().promise;
+                    },
+
+                    redirectUri: function(options) {
+                        if (options && options.redirectUri) {
+                            return options.redirectUri;
+                        } else if (kc.redirectUri) {
+                            return kc.redirectUri;
+                        } else {
+                            var redirectUri = location.href;
+                            if (location.hash) {
+                                redirectUri = redirectUri.substring(0, location.href.indexOf('#'));
+                                redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
+                            }
+                            return redirectUri;
+                        }
+                    }
+                };
+            }
+
+            if (type == 'cordova') {
+                loginIframe.enable = false;
+
+                return {
+                    login: function(options) {
+                        var promise = createPromise();
+
+                        var o = 'location=no';
+                        if (options && options.prompt == 'none') {
+                            o += ',hidden=yes';
+                        }
+
+                        var loginUrl = kc.createLoginUrl(options);
+                        var ref = window.open(loginUrl, '_blank', o);
+
+                        var callback;
+                        var error;
+
+                        ref.addEventListener('loadstart', function(event) {
+                            if (event.url.indexOf('http://localhost') == 0) {
+                                callback = parseCallback(event.url);
+                                ref.close();
+                            }
+                        });
+
+                        ref.addEventListener('loaderror', function(event) {
+                            if (event.url.indexOf('http://localhost') != 0) {
+                                error = true;
+                                ref.close();
+                            }
+                        });
+
+                        ref.addEventListener('exit', function(event) {
+                            if (error || !callback) {
+                                promise.setError();
+                            } else {
+                                processCallback(callback, promise);
+                            }
+                        });
+
+                        return promise.promise;
+                    },
+
+                    logout: function(options) {
+                        var promise = createPromise();
+
+                        var logoutUrl = kc.createLogoutUrl(options);
+                        var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
+
+                        var error;
+
+                        ref.addEventListener('loadstart', function(event) {
+                            if (event.url.indexOf('http://localhost') == 0) {
+                                ref.close();
+                            }
+                        });
+
+                        ref.addEventListener('loaderror', function(event) {
+                            if (event.url.indexOf('http://localhost') != 0) {
+                                error = true;
+                                ref.close();
+                            }
+                        });
+
+                        ref.addEventListener('exit', function(event) {
+                            if (error) {
+                                promise.setError();
+                            } else {
+                                kc.clearToken();
+                                promise.setSuccess();
+                            }
+                        });
+
+                        return promise.promise;
+                    },
+
+                    accountManagement : function() {
+                        var accountUrl = kc.createAccountUrl();
+                        var ref = window.open(accountUrl, '_blank', 'location=no');
+                        ref.addEventListener('loadstart', function(event) {
+                            if (event.url.indexOf('http://localhost') == 0) {
+                                ref.close();
+                            }
+                        });
+                    },
+
+                    redirectUri: function(options) {
+                        return 'http://localhost';
+                    }
+                }
+            }
+
+            throw 'invalid adapter type: ' + type;
+        }
+    }
+
+    if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+        module.exports = Keycloak;
+    } else {
+        window.Keycloak = Keycloak;
+
+        if ( typeof define === "function" && define.amd ) {
+            define( "keycloak", [], function () { return Keycloak; } );
+        }
+    }
+})( window );
diff --git a/integration/js/src/main/resources/login-status-iframe.html b/integration/js/src/main/resources/login-status-iframe.html
index 8261065..cc6ff18 100755
--- a/integration/js/src/main/resources/login-status-iframe.html
+++ b/integration/js/src/main/resources/login-status-iframe.html
@@ -1,32 +1,32 @@
-<script>
-    function getCookie(cname)
-    {
-        var name = cname + "=";
-        var ca = document.cookie.split(';');
-        for(var i=0; i<ca.length; i++)
-        {
-            var c = ca[i].trim();
-            if (c.indexOf(name)==0) return c.substring(name.length,c.length);
-        }
-        return null;
-    }
-    function receiveMessage(event)
-    {
-        if (event.origin !== "ORIGIN") {
-            console.log(event.origin + " does not match built origin");
-            return;
-
-        }
-        var data = JSON.parse(event.data);
-        data.loggedIn = false;
-        var cookie = getCookie('KEYCLOAK_SESSION');
-        if (cookie) {
-            data.loggedIn = true;
-            data.session = cookie;
-        }
-
-        event.source.postMessage(JSON.stringify(data),
-                event.origin);
-    }
-    window.addEventListener("message", receiveMessage, false);
+<script>
+    function getCookie(cname)
+    {
+        var name = cname + "=";
+        var ca = document.cookie.split(';');
+        for(var i=0; i<ca.length; i++)
+        {
+            var c = ca[i].trim();
+            if (c.indexOf(name)==0) return c.substring(name.length,c.length);
+        }
+        return null;
+    }
+    function receiveMessage(event)
+    {
+        if (event.origin !== "ORIGIN") {
+            console.log(event.origin + " does not match built origin");
+            return;
+
+        }
+        var data = JSON.parse(event.data);
+        data.loggedIn = false;
+        var cookie = getCookie('KEYCLOAK_SESSION');
+        if (cookie) {
+            data.loggedIn = true;
+            data.session = cookie;
+        }
+
+        event.source.postMessage(JSON.stringify(data),
+                event.origin);
+    }
+    window.addEventListener("message", receiveMessage, false);
 </script>
\ No newline at end of file

integration/pom.xml 66(+33 -33)

diff --git a/integration/pom.xml b/integration/pom.xml
index a7c8675..e12b351 100755
--- a/integration/pom.xml
+++ b/integration/pom.xml
@@ -1,33 +1,33 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak Integration</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-integration-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>adapter-core</module>
-        <module>jaxrs-oauth-client</module>
-        <module>servlet-oauth-client</module>
-        <module>jboss-adapter-core</module>
-        <module>tomcat</module>
-        <module>as7-eap6</module>
-        <module>jetty</module>
-        <module>undertow</module>
-        <module>wildfly</module>
-        <module>js</module>
-        <module>installed</module>
-        <module>admin-client</module>
-        <module>osgi-adapter</module>
-        <module>spring-boot</module>
-        <module>spring-security</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak Integration</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-integration-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>adapter-core</module>
+        <module>jaxrs-oauth-client</module>
+        <module>servlet-oauth-client</module>
+        <module>jboss-adapter-core</module>
+        <module>tomcat</module>
+        <module>as7-eap6</module>
+        <module>jetty</module>
+        <module>undertow</module>
+        <module>wildfly</module>
+        <module>js</module>
+        <module>installed</module>
+        <module>admin-client</module>
+        <module>osgi-adapter</module>
+        <module>spring-boot</module>
+        <module>spring-security</module>
+    </modules>
+</project>
diff --git a/integration/servlet-oauth-client/pom.xml b/integration/servlet-oauth-client/pom.xml
index 983ccff..5b3633e 100755
--- a/integration/servlet-oauth-client/pom.xml
+++ b/integration/servlet-oauth-client/pom.xml
@@ -1,66 +1,66 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-servlet-oauth-client</artifactId>
-    <name>Keycloak Servlet OAuth Client</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-servlet-oauth-client</artifactId>
+    <name>Keycloak Servlet OAuth Client</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
index 668bb02..5f5daaa 100755
--- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
+++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java
@@ -1,174 +1,174 @@
-package org.keycloak.servlet;
-
-import org.apache.http.client.HttpClient;
-import org.keycloak.AbstractOAuthClient;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.adapters.HttpClientBuilder;
-import org.keycloak.adapters.ServerRequest;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.IDToken;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.KeycloakUriBuilder;
-import org.keycloak.util.UriUtils;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.URI;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ServletOAuthClient extends AbstractOAuthClient {
-    protected HttpClient client;
-    protected AdapterConfig adapterConfig;
-
-    public void start() {
-        client = new HttpClientBuilder().build(adapterConfig);
-    }
-
-    /**
-     * closes client
-     */
-    public void stop() {
-        client.getConnectionManager().shutdown();
-    }
-
-    private AccessTokenResponse resolveBearerToken(HttpServletRequest request, String redirectUri, String code) throws IOException, ServerRequest.HttpFailure {
-        // Don't send sessionId in oauth clients for now
-        return ServerRequest.invokeAccessCodeToToken(client, publicClient, code, getUrl(request, tokenUrl, false), redirectUri, clientId, credentials, null);
-    }
-
-    /**
-     * Start the process of obtaining an access token by redirecting the browser
-     * to the authentication server
-     *
-     * @param relativePath path relative to context root you want auth server to redirect back to
-     * @param request
-     * @param response
-     * @throws IOException
-     */
-    public void redirectRelative(String relativePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
-        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(request.getRequestURL().toString())
-                .replacePath(request.getContextPath())
-                .replaceQuery(null)
-                .path(relativePath);
-        String redirect = builder.toTemplate();
-        redirect(redirect, request, response);
-    }
-
-
-    /**
-     * Start the process of obtaining an access token by redirecting the browser
-     * to the authentication server
-     *
-     * @param redirectUri full URI you want auth server to redirect back to
-     * @param request
-     * @param response
-     * @throws IOException
-     */
-    public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
-        String state = getStateCode();
-
-        KeycloakUriBuilder uriBuilder =  KeycloakUriBuilder.fromUri(getUrl(request, authUrl, true))
-                .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
-                .queryParam(OAuth2Constants.CLIENT_ID, clientId)
-                .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
-                .queryParam(OAuth2Constants.STATE, state);
-        if (scope != null) {
-            uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
-        }
-        URI url = uriBuilder.build();
-
-        String stateCookiePath = this.stateCookiePath;
-        if (stateCookiePath == null) stateCookiePath = request.getContextPath();
-        if (stateCookiePath.equals("")) stateCookiePath = "/";
-
-        Cookie cookie = new Cookie(stateCookieName, state);
-        cookie.setSecure(isSecure);
-        cookie.setPath(stateCookiePath);
-        response.addCookie(cookie);
-        response.sendRedirect(url.toString());
-    }
-
-    protected String getCookieValue(String name, HttpServletRequest request) {
-        if (request.getCookies() == null) return null;
-
-        for (Cookie cookie : request.getCookies()) {
-            if (cookie.getName().equals(name)) return cookie.getValue();
-        }
-        return null;
-    }
-
-    protected String getCode(HttpServletRequest request) {
-        String query = request.getQueryString();
-        if (query == null) return null;
-        String[] params = query.split("&");
-        for (String param : params) {
-            int eq = param.indexOf('=');
-            if (eq == -1) continue;
-            String name = param.substring(0, eq);
-            if (!name.equals(OAuth2Constants.CODE)) continue;
-            return param.substring(eq + 1);
-        }
-        return null;
-    }
-
-
-    /**
-     * Obtain the code parameter from the url after being redirected back from the auth-server.  Then
-     * do an authenticated request back to the auth-server to turn the access code into an access token.
-     *
-     * @param request
-     * @return
-     * @throws IOException
-     * @throws org.keycloak.adapters.ServerRequest.HttpFailure
-     */
-    public AccessTokenResponse getBearerToken(HttpServletRequest request) throws IOException, ServerRequest.HttpFailure {
-        String error = request.getParameter(OAuth2Constants.ERROR);
-        if (error != null) throw new IOException("OAuth error: " + error);
-        String redirectUri = request.getRequestURL().append("?").append(request.getQueryString()).toString();
-        String stateCookie = getCookieValue(stateCookieName, request);
-        if (stateCookie == null) throw new IOException("state cookie not set");
-        // we can call get parameter as this should be a redirect
-        String state = request.getParameter(OAuth2Constants.STATE);
-        String code = request.getParameter(OAuth2Constants.CODE);
-
-        if (state == null) throw new IOException("state parameter was null");
-        if (!state.equals(stateCookie)) {
-            throw new IOException("state parameter invalid");
-        }
-        if (code == null) throw new IOException("code parameter was null");
-        return resolveBearerToken(request, redirectUri, code);
-    }
-
-    public AccessTokenResponse refreshToken(HttpServletRequest request, String refreshToken) throws IOException, ServerRequest.HttpFailure {
-        return ServerRequest.invokeRefresh(client, publicClient, refreshToken, getUrl(request, tokenUrl, false), clientId, credentials);
-    }
-
-    public static IDToken extractIdToken(String idToken) {
-        if (idToken == null) return null;
-        JWSInput input = new JWSInput(idToken);
-        try {
-            return input.readJsonContent(IDToken.class);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private String getUrl(HttpServletRequest request, String url, boolean isBrowserRequest) {
-        if (relativeUrlsUsed.useRelative(isBrowserRequest)) {
-            String baseUrl = UriUtils.getOrigin(request.getRequestURL().toString());
-            return baseUrl + url;
-        } else {
-            return url;
-        }
-    }
-
-    public void setAdapterConfig(AdapterConfig adapterConfig) {
-        this.adapterConfig = adapterConfig;
-    }
-}
+package org.keycloak.servlet;
+
+import org.apache.http.client.HttpClient;
+import org.keycloak.AbstractOAuthClient;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.adapters.HttpClientBuilder;
+import org.keycloak.adapters.ServerRequest;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.UriUtils;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ServletOAuthClient extends AbstractOAuthClient {
+    protected HttpClient client;
+    protected AdapterConfig adapterConfig;
+
+    public void start() {
+        client = new HttpClientBuilder().build(adapterConfig);
+    }
+
+    /**
+     * closes client
+     */
+    public void stop() {
+        client.getConnectionManager().shutdown();
+    }
+
+    private AccessTokenResponse resolveBearerToken(HttpServletRequest request, String redirectUri, String code) throws IOException, ServerRequest.HttpFailure {
+        // Don't send sessionId in oauth clients for now
+        return ServerRequest.invokeAccessCodeToToken(client, publicClient, code, getUrl(request, tokenUrl, false), redirectUri, clientId, credentials, null);
+    }
+
+    /**
+     * Start the process of obtaining an access token by redirecting the browser
+     * to the authentication server
+     *
+     * @param relativePath path relative to context root you want auth server to redirect back to
+     * @param request
+     * @param response
+     * @throws IOException
+     */
+    public void redirectRelative(String relativePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
+        KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(request.getRequestURL().toString())
+                .replacePath(request.getContextPath())
+                .replaceQuery(null)
+                .path(relativePath);
+        String redirect = builder.toTemplate();
+        redirect(redirect, request, response);
+    }
+
+
+    /**
+     * Start the process of obtaining an access token by redirecting the browser
+     * to the authentication server
+     *
+     * @param redirectUri full URI you want auth server to redirect back to
+     * @param request
+     * @param response
+     * @throws IOException
+     */
+    public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String state = getStateCode();
+
+        KeycloakUriBuilder uriBuilder =  KeycloakUriBuilder.fromUri(getUrl(request, authUrl, true))
+                .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
+                .queryParam(OAuth2Constants.CLIENT_ID, clientId)
+                .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
+                .queryParam(OAuth2Constants.STATE, state);
+        if (scope != null) {
+            uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
+        }
+        URI url = uriBuilder.build();
+
+        String stateCookiePath = this.stateCookiePath;
+        if (stateCookiePath == null) stateCookiePath = request.getContextPath();
+        if (stateCookiePath.equals("")) stateCookiePath = "/";
+
+        Cookie cookie = new Cookie(stateCookieName, state);
+        cookie.setSecure(isSecure);
+        cookie.setPath(stateCookiePath);
+        response.addCookie(cookie);
+        response.sendRedirect(url.toString());
+    }
+
+    protected String getCookieValue(String name, HttpServletRequest request) {
+        if (request.getCookies() == null) return null;
+
+        for (Cookie cookie : request.getCookies()) {
+            if (cookie.getName().equals(name)) return cookie.getValue();
+        }
+        return null;
+    }
+
+    protected String getCode(HttpServletRequest request) {
+        String query = request.getQueryString();
+        if (query == null) return null;
+        String[] params = query.split("&");
+        for (String param : params) {
+            int eq = param.indexOf('=');
+            if (eq == -1) continue;
+            String name = param.substring(0, eq);
+            if (!name.equals(OAuth2Constants.CODE)) continue;
+            return param.substring(eq + 1);
+        }
+        return null;
+    }
+
+
+    /**
+     * Obtain the code parameter from the url after being redirected back from the auth-server.  Then
+     * do an authenticated request back to the auth-server to turn the access code into an access token.
+     *
+     * @param request
+     * @return
+     * @throws IOException
+     * @throws org.keycloak.adapters.ServerRequest.HttpFailure
+     */
+    public AccessTokenResponse getBearerToken(HttpServletRequest request) throws IOException, ServerRequest.HttpFailure {
+        String error = request.getParameter(OAuth2Constants.ERROR);
+        if (error != null) throw new IOException("OAuth error: " + error);
+        String redirectUri = request.getRequestURL().append("?").append(request.getQueryString()).toString();
+        String stateCookie = getCookieValue(stateCookieName, request);
+        if (stateCookie == null) throw new IOException("state cookie not set");
+        // we can call get parameter as this should be a redirect
+        String state = request.getParameter(OAuth2Constants.STATE);
+        String code = request.getParameter(OAuth2Constants.CODE);
+
+        if (state == null) throw new IOException("state parameter was null");
+        if (!state.equals(stateCookie)) {
+            throw new IOException("state parameter invalid");
+        }
+        if (code == null) throw new IOException("code parameter was null");
+        return resolveBearerToken(request, redirectUri, code);
+    }
+
+    public AccessTokenResponse refreshToken(HttpServletRequest request, String refreshToken) throws IOException, ServerRequest.HttpFailure {
+        return ServerRequest.invokeRefresh(client, publicClient, refreshToken, getUrl(request, tokenUrl, false), clientId, credentials);
+    }
+
+    public static IDToken extractIdToken(String idToken) {
+        if (idToken == null) return null;
+        JWSInput input = new JWSInput(idToken);
+        try {
+            return input.readJsonContent(IDToken.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String getUrl(HttpServletRequest request, String url, boolean isBrowserRequest) {
+        if (relativeUrlsUsed.useRelative(isBrowserRequest)) {
+            String baseUrl = UriUtils.getOrigin(request.getRequestURL().toString());
+            return baseUrl + url;
+        } else {
+            return url;
+        }
+    }
+
+    public void setAdapterConfig(AdapterConfig adapterConfig) {
+        this.adapterConfig = adapterConfig;
+    }
+}
diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
index d650e93..20f33bc 100755
--- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
+++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java
@@ -1,79 +1,79 @@
-package org.keycloak.servlet;
-
-import org.apache.http.client.HttpClient;
-import org.keycloak.constants.ServiceUrlConstants;
-import org.keycloak.adapters.HttpClientBuilder;
-import org.keycloak.enums.RelativeUrlsUsed;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ServletOAuthClientBuilder {
-
-    public static ServletOAuthClient build(InputStream is) {
-        AdapterConfig adapterConfig = getAdapterConfig(is);
-        return build(adapterConfig);
-    }
-
-    public static AdapterConfig getAdapterConfig(InputStream is) {
-        try {
-            return JsonSerialization.readValue(is, AdapterConfig.class, true);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static ServletOAuthClient build(AdapterConfig adapterConfig) {
-        ServletOAuthClient oauthClient = new ServletOAuthClient();
-        build(adapterConfig, oauthClient);
-        return oauthClient;
-    }
-
-    public static void build(InputStream is, ServletOAuthClient oauthClient) {
-        build(getAdapterConfig(is), oauthClient);
-    }
-
-
-    public static void build(AdapterConfig adapterConfig, ServletOAuthClient oauthClient) {
-        oauthClient.setAdapterConfig(adapterConfig);
-        oauthClient.setClientId(adapterConfig.getResource());
-        oauthClient.setPublicClient(adapterConfig.isPublicClient());
-        oauthClient.setCredentials(adapterConfig.getCredentials());
-        if (adapterConfig.getAuthServerUrl() == null) {
-            throw new RuntimeException("You must specify auth-url");
-        }
-        KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl());
-        RelativeUrlsUsed useRelative = relativeUrls(serverBuilder, adapterConfig);
-        oauthClient.setRelativeUrlsUsed(useRelative);
-
-        String authUrl = serverBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(adapterConfig.getRealm()).toString();
-
-        KeycloakUriBuilder tokenUrlBuilder;
-
-        if (useRelative == RelativeUrlsUsed.BROWSER_ONLY) {
-            // Use absolute URI for refreshToken and codeToToken requests
-            KeycloakUriBuilder nonBrowsersServerBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrlForBackendRequests());
-            tokenUrlBuilder = nonBrowsersServerBuilder.clone();
-        } else {
-            tokenUrlBuilder = serverBuilder.clone();
-        }
-        String tokenUrl = tokenUrlBuilder.path(ServiceUrlConstants.TOKEN_PATH).build(adapterConfig.getRealm()).toString();
-        oauthClient.setAuthUrl(authUrl);
-        oauthClient.setTokenUrl(tokenUrl);
-    }
-
-    private static RelativeUrlsUsed relativeUrls(KeycloakUriBuilder serverBuilder, AdapterConfig adapterConfig) {
-        if (serverBuilder.clone().getHost() == null) {
-            return (adapterConfig.getAuthServerUrlForBackendRequests() != null) ? RelativeUrlsUsed.BROWSER_ONLY : RelativeUrlsUsed.ALL_REQUESTS;
-        } else {
-            return RelativeUrlsUsed.NEVER;
-        }
-    }
-}
+package org.keycloak.servlet;
+
+import org.apache.http.client.HttpClient;
+import org.keycloak.constants.ServiceUrlConstants;
+import org.keycloak.adapters.HttpClientBuilder;
+import org.keycloak.enums.RelativeUrlsUsed;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ServletOAuthClientBuilder {
+
+    public static ServletOAuthClient build(InputStream is) {
+        AdapterConfig adapterConfig = getAdapterConfig(is);
+        return build(adapterConfig);
+    }
+
+    public static AdapterConfig getAdapterConfig(InputStream is) {
+        try {
+            return JsonSerialization.readValue(is, AdapterConfig.class, true);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static ServletOAuthClient build(AdapterConfig adapterConfig) {
+        ServletOAuthClient oauthClient = new ServletOAuthClient();
+        build(adapterConfig, oauthClient);
+        return oauthClient;
+    }
+
+    public static void build(InputStream is, ServletOAuthClient oauthClient) {
+        build(getAdapterConfig(is), oauthClient);
+    }
+
+
+    public static void build(AdapterConfig adapterConfig, ServletOAuthClient oauthClient) {
+        oauthClient.setAdapterConfig(adapterConfig);
+        oauthClient.setClientId(adapterConfig.getResource());
+        oauthClient.setPublicClient(adapterConfig.isPublicClient());
+        oauthClient.setCredentials(adapterConfig.getCredentials());
+        if (adapterConfig.getAuthServerUrl() == null) {
+            throw new RuntimeException("You must specify auth-url");
+        }
+        KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl());
+        RelativeUrlsUsed useRelative = relativeUrls(serverBuilder, adapterConfig);
+        oauthClient.setRelativeUrlsUsed(useRelative);
+
+        String authUrl = serverBuilder.clone().path(ServiceUrlConstants.AUTH_PATH).build(adapterConfig.getRealm()).toString();
+
+        KeycloakUriBuilder tokenUrlBuilder;
+
+        if (useRelative == RelativeUrlsUsed.BROWSER_ONLY) {
+            // Use absolute URI for refreshToken and codeToToken requests
+            KeycloakUriBuilder nonBrowsersServerBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrlForBackendRequests());
+            tokenUrlBuilder = nonBrowsersServerBuilder.clone();
+        } else {
+            tokenUrlBuilder = serverBuilder.clone();
+        }
+        String tokenUrl = tokenUrlBuilder.path(ServiceUrlConstants.TOKEN_PATH).build(adapterConfig.getRealm()).toString();
+        oauthClient.setAuthUrl(authUrl);
+        oauthClient.setTokenUrl(tokenUrl);
+    }
+
+    private static RelativeUrlsUsed relativeUrls(KeycloakUriBuilder serverBuilder, AdapterConfig adapterConfig) {
+        if (serverBuilder.clone().getHost() == null) {
+            return (adapterConfig.getAuthServerUrlForBackendRequests() != null) ? RelativeUrlsUsed.BROWSER_ONLY : RelativeUrlsUsed.ALL_REQUESTS;
+        } else {
+            return RelativeUrlsUsed.NEVER;
+        }
+    }
+}
diff --git a/integration/spring-boot/pom.xml b/integration/spring-boot/pom.xml
index ef31e98..cb913cc 100755
--- a/integration/spring-boot/pom.xml
+++ b/integration/spring-boot/pom.xml
@@ -1,72 +1,72 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <artifactId>keycloak-parent</artifactId>
-    <groupId>org.keycloak</groupId>
-    <version>1.4.0.Final-SNAPSHOT</version>
-    <relativePath>../../pom.xml</relativePath>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>keycloak-spring-boot-adapter</artifactId>
-  <name>Keycloak Spring Boot Integration</name>
-  <description/>
-
-  <properties>
-    <spring-boot.version>1.2.1.RELEASE</spring-boot.version>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.jboss.logging</groupId>
-      <artifactId>jboss-logging</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.keycloak</groupId>
-      <artifactId>keycloak-core</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>org.keycloak</groupId>
-      <artifactId>keycloak-tomcat8-adapter</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.keycloak</groupId>
-      <artifactId>keycloak-undertow-adapter</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.keycloak</groupId>
-      <artifactId>keycloak-jetty92-adapter</artifactId>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-web</artifactId>
-      <version>${spring-boot.version}</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>keycloak-parent</artifactId>
+    <groupId>org.keycloak</groupId>
+    <version>1.4.0.Final-SNAPSHOT</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>keycloak-spring-boot-adapter</artifactId>
+  <name>Keycloak Spring Boot Integration</name>
+  <description/>
+
+  <properties>
+    <spring-boot.version>1.2.1.RELEASE</spring-boot.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.jboss.logging</groupId>
+      <artifactId>jboss-logging</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.keycloak</groupId>
+      <artifactId>keycloak-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.keycloak</groupId>
+      <artifactId>keycloak-tomcat8-adapter</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.keycloak</groupId>
+      <artifactId>keycloak-undertow-adapter</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.keycloak</groupId>
+      <artifactId>keycloak-jetty92-adapter</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <version>${spring-boot.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java b/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
index f48929d..49943ad 100755
--- a/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
+++ b/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
@@ -1,123 +1,123 @@
-package org.keycloak.adapters.springboot;
-
-import org.apache.catalina.Context;
-import org.apache.tomcat.util.descriptor.web.LoginConfig;
-import org.apache.tomcat.util.descriptor.web.SecurityCollection;
-import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
-import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
-import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
-import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
-import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
-import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
-import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Keycloak authentication integration for Spring Boot
- *
- * @author <a href="mailto:jimmidyson@gmail.com">Jimmi Dyson</a>
- * @version $Revision: 1 $
- */
-@Configuration
-@ConditionalOnWebApplication
-@EnableConfigurationProperties(KeycloakSpringBootProperties.class)
-public class KeycloakSpringBootConfiguration {
-
-    private KeycloakSpringBootProperties keycloakProperties;
-
-    @Autowired
-    public void setKeycloakSpringBootProperties(KeycloakSpringBootProperties keycloakProperties) {
-        this.keycloakProperties = keycloakProperties;
-        KeycloakSpringBootConfigResolver.setAdapterConfig(keycloakProperties);
-    }
-
-    @Bean
-    public EmbeddedServletContainerCustomizer getKeycloakContainerCustomizer() {
-        return new EmbeddedServletContainerCustomizer() {
-            @Override
-            public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
-                if (configurableEmbeddedServletContainer instanceof TomcatEmbeddedServletContainerFactory) {
-                    TomcatEmbeddedServletContainerFactory container = (TomcatEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
-
-                    container.addContextValves(new KeycloakAuthenticatorValve());
-
-                    container.addContextCustomizers(getTomcatKeycloakContextCustomizer());
-                } else if (configurableEmbeddedServletContainer instanceof UndertowEmbeddedServletContainerFactory) {
-                    throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
-                } else if (configurableEmbeddedServletContainer instanceof JettyEmbeddedServletContainerFactory) {
-                    throw new IllegalArgumentException("Jetty Keycloak integration is not yet implemented");
-                }
-            }
-        };
-    }
-
-    @Bean
-    public TomcatContextCustomizer getTomcatKeycloakContextCustomizer() {
-        return new TomcatContextCustomizer() {
-            @Override
-            public void customize(Context context) {
-                LoginConfig loginConfig = new LoginConfig();
-                loginConfig.setAuthMethod("KEYCLOAK");
-                context.setLoginConfig(loginConfig);
-
-                Set<String> authRoles = new HashSet<String>();
-                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
-                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
-                        for (String authRole : collection.getAuthRoles()) {
-                            if (!authRoles.contains(authRole)) {
-                                context.addSecurityRole(authRole);
-                                authRoles.add(authRole);
-                            }
-                        }
-                    }
-                }
-
-                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
-                    SecurityConstraint tomcatConstraint = new SecurityConstraint();
-
-                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
-                        SecurityCollection tomcatSecCollection = new SecurityCollection();
-
-                        if (collection.getName() != null) {
-                            tomcatSecCollection.setName(collection.getName());
-                        }
-                        if (collection.getDescription() != null) {
-                            tomcatSecCollection.setDescription(collection.getDescription());
-                        }
-
-                        for (String authRole : collection.getAuthRoles()) {
-                            tomcatConstraint.addAuthRole(authRole);
-                        }
-
-                        for (String pattern : collection.getPatterns()) {
-                            tomcatSecCollection.addPattern(pattern);
-                        }
-
-                        for (String method : collection.getMethods()) {
-                            tomcatSecCollection.addMethod(method);
-                        }
-
-                        for (String method : collection.getOmittedMethods()) {
-                            tomcatSecCollection.addOmittedMethod(method);
-                        }
-
-                        tomcatConstraint.addCollection(tomcatSecCollection);
-                    }
-
-                    context.addConstraint(tomcatConstraint);
-                }
-
-                context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
-            }
-        };
-    }
-
-}
+package org.keycloak.adapters.springboot;
+
+import org.apache.catalina.Context;
+import org.apache.tomcat.util.descriptor.web.LoginConfig;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
+import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
+import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Keycloak authentication integration for Spring Boot
+ *
+ * @author <a href="mailto:jimmidyson@gmail.com">Jimmi Dyson</a>
+ * @version $Revision: 1 $
+ */
+@Configuration
+@ConditionalOnWebApplication
+@EnableConfigurationProperties(KeycloakSpringBootProperties.class)
+public class KeycloakSpringBootConfiguration {
+
+    private KeycloakSpringBootProperties keycloakProperties;
+
+    @Autowired
+    public void setKeycloakSpringBootProperties(KeycloakSpringBootProperties keycloakProperties) {
+        this.keycloakProperties = keycloakProperties;
+        KeycloakSpringBootConfigResolver.setAdapterConfig(keycloakProperties);
+    }
+
+    @Bean
+    public EmbeddedServletContainerCustomizer getKeycloakContainerCustomizer() {
+        return new EmbeddedServletContainerCustomizer() {
+            @Override
+            public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
+                if (configurableEmbeddedServletContainer instanceof TomcatEmbeddedServletContainerFactory) {
+                    TomcatEmbeddedServletContainerFactory container = (TomcatEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
+
+                    container.addContextValves(new KeycloakAuthenticatorValve());
+
+                    container.addContextCustomizers(getTomcatKeycloakContextCustomizer());
+                } else if (configurableEmbeddedServletContainer instanceof UndertowEmbeddedServletContainerFactory) {
+                    throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
+                } else if (configurableEmbeddedServletContainer instanceof JettyEmbeddedServletContainerFactory) {
+                    throw new IllegalArgumentException("Jetty Keycloak integration is not yet implemented");
+                }
+            }
+        };
+    }
+
+    @Bean
+    public TomcatContextCustomizer getTomcatKeycloakContextCustomizer() {
+        return new TomcatContextCustomizer() {
+            @Override
+            public void customize(Context context) {
+                LoginConfig loginConfig = new LoginConfig();
+                loginConfig.setAuthMethod("KEYCLOAK");
+                context.setLoginConfig(loginConfig);
+
+                Set<String> authRoles = new HashSet<String>();
+                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
+                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
+                        for (String authRole : collection.getAuthRoles()) {
+                            if (!authRoles.contains(authRole)) {
+                                context.addSecurityRole(authRole);
+                                authRoles.add(authRole);
+                            }
+                        }
+                    }
+                }
+
+                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
+                    SecurityConstraint tomcatConstraint = new SecurityConstraint();
+
+                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
+                        SecurityCollection tomcatSecCollection = new SecurityCollection();
+
+                        if (collection.getName() != null) {
+                            tomcatSecCollection.setName(collection.getName());
+                        }
+                        if (collection.getDescription() != null) {
+                            tomcatSecCollection.setDescription(collection.getDescription());
+                        }
+
+                        for (String authRole : collection.getAuthRoles()) {
+                            tomcatConstraint.addAuthRole(authRole);
+                        }
+
+                        for (String pattern : collection.getPatterns()) {
+                            tomcatSecCollection.addPattern(pattern);
+                        }
+
+                        for (String method : collection.getMethods()) {
+                            tomcatSecCollection.addMethod(method);
+                        }
+
+                        for (String method : collection.getOmittedMethods()) {
+                            tomcatSecCollection.addOmittedMethod(method);
+                        }
+
+                        tomcatConstraint.addCollection(tomcatSecCollection);
+                    }
+
+                    context.addConstraint(tomcatConstraint);
+                }
+
+                context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
+            }
+        };
+    }
+
+}
diff --git a/integration/tomcat/pom.xml b/integration/tomcat/pom.xml
index 36b8f68..c8fd664 100755
--- a/integration/tomcat/pom.xml
+++ b/integration/tomcat/pom.xml
@@ -1,22 +1,22 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak Tomcat Integration</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-tomcat-integration-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>tomcat-core</module>
-        <module>tomcat6</module>
-        <module>tomcat7</module>
-        <module>tomcat8</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak Tomcat Integration</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-tomcat-integration-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>tomcat-core</module>
+        <module>tomcat6</module>
+        <module>tomcat7</module>
+        <module>tomcat8</module>
+    </modules>
+</project>
diff --git a/integration/tomcat/tomcat6/pom.xml b/integration/tomcat/tomcat6/pom.xml
index fcfcfde..5c9f552 100755
--- a/integration/tomcat/tomcat6/pom.xml
+++ b/integration/tomcat/tomcat6/pom.xml
@@ -1,100 +1,100 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-tomcat6-adapter</artifactId>
-	<name>Keycloak Tomcat 6 Integration</name>
-    <properties>
-        <tomcat.version>6.0.41</tomcat.version>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat-core-adapter</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-catalina</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>catalina</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.apache.tomcat</groupId>
-            <artifactId>catalina</artifactId>
-            <version>${tomcat.version}</version>
-            <scope>provided</scope>
-        </dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-tomcat6-adapter</artifactId>
+	<name>Keycloak Tomcat 6 Integration</name>
+    <properties>
+        <tomcat.version>6.0.41</tomcat.version>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat-core-adapter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-catalina</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>catalina</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>catalina</artifactId>
+            <version>${tomcat.version}</version>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index 5dc7701..2e30429 100755
--- a/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -1,58 +1,58 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.deploy.LoginConfig;
-import org.apache.catalina.realm.GenericPrincipal;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.security.Principal;
-import java.util.List;
-
-/**
- * Keycloak authentication valve
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
-    @Override
-    public boolean authenticate(Request request, Response response, LoginConfig config) throws java.io.IOException {
-        return authenticateInternal(request, response, config);
-    }
-
-    @Override
-    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
-        if (loginConfig == null) return false;
-        LoginConfig config = (LoginConfig)loginConfig;
-        if (config.getErrorPage() == null) return false;
-        forwardToErrorPage(request, (Response)response, config);
-        return true;
-    }
-
-
-    @Override
-    public void start() throws LifecycleException {
-        StandardContext standardContext = (StandardContext) context;
-        standardContext.addLifecycleListener(this);
-        super.start();
-    }
-
-    public void logout(Request request) throws ServletException {
-        logoutInternal(request);
-    }
-
-    @Override
-    protected GenericPrincipalFactory createPrincipalFactory() {
-        return new GenericPrincipalFactory() {
-            @Override
-            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
-                return new GenericPrincipal(null, userPrincipal.getName(), null, roles, userPrincipal, null);
-            }
-        };
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.deploy.LoginConfig;
+import org.apache.catalina.realm.GenericPrincipal;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.List;
+
+/**
+ * Keycloak authentication valve
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
+    @Override
+    public boolean authenticate(Request request, Response response, LoginConfig config) throws java.io.IOException {
+        return authenticateInternal(request, response, config);
+    }
+
+    @Override
+    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+        if (loginConfig == null) return false;
+        LoginConfig config = (LoginConfig)loginConfig;
+        if (config.getErrorPage() == null) return false;
+        forwardToErrorPage(request, (Response)response, config);
+        return true;
+    }
+
+
+    @Override
+    public void start() throws LifecycleException {
+        StandardContext standardContext = (StandardContext) context;
+        standardContext.addLifecycleListener(this);
+        super.start();
+    }
+
+    public void logout(Request request) throws ServletException {
+        logoutInternal(request);
+    }
+
+    @Override
+    protected GenericPrincipalFactory createPrincipalFactory() {
+        return new GenericPrincipalFactory() {
+            @Override
+            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
+                return new GenericPrincipal(null, userPrincipal.getName(), null, roles, userPrincipal, null);
+            }
+        };
+    }
+}
diff --git a/integration/tomcat/tomcat7/pom.xml b/integration/tomcat/tomcat7/pom.xml
index 7a8e8b4..3d22729 100755
--- a/integration/tomcat/tomcat7/pom.xml
+++ b/integration/tomcat/tomcat7/pom.xml
@@ -1,108 +1,108 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-tomcat7-adapter</artifactId>
-	<name>Keycloak Tomcat 7 Integration</name>
-    <properties>
-        <!--<tomcat.version>8.0.14</tomcat.version>-->
-        <tomcat.version>7.0.52</tomcat.version>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat-core-adapter</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-catalina</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>catalina</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.tomcat</groupId>
-			<artifactId>tomcat-servlet-api</artifactId>
-			<version>${tomcat.version}</version>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.tomcat</groupId>
-			<artifactId>tomcat-catalina</artifactId>
-            <version>${tomcat.version}</version>
-			<scope>provided</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-tomcat7-adapter</artifactId>
+	<name>Keycloak Tomcat 7 Integration</name>
+    <properties>
+        <!--<tomcat.version>8.0.14</tomcat.version>-->
+        <tomcat.version>7.0.52</tomcat.version>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat-core-adapter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-catalina</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>catalina</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.tomcat</groupId>
+			<artifactId>tomcat-servlet-api</artifactId>
+			<version>${tomcat.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.tomcat</groupId>
+			<artifactId>tomcat-catalina</artifactId>
+            <version>${tomcat.version}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index 45402e6..fa94c34 100755
--- a/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -1,54 +1,54 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.deploy.LoginConfig;
-import org.apache.catalina.realm.GenericPrincipal;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.security.Principal;
-import java.util.List;
-
-/**
- * Keycloak authentication valve
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
-    public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
-        return authenticateInternal(request, response, config);
-    }
-
-    @Override
-    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
-        if (loginConfig == null) return false;
-        LoginConfig config = (LoginConfig)loginConfig;
-        if (config.getErrorPage() == null) return false;
-        forwardToErrorPage(request, (Response)response, config);
-        return true;
-    }
-
-
-    protected void initInternal() {
-        StandardContext standardContext = (StandardContext) context;
-        standardContext.addLifecycleListener(this);
-    }
-
-    public void logout(Request request) throws ServletException {
-        logoutInternal(request);
-    }
-
-    @Override
-    protected GenericPrincipalFactory createPrincipalFactory() {
-        return new GenericPrincipalFactory() {
-            @Override
-            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
-                return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
-            }
-        };
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.deploy.LoginConfig;
+import org.apache.catalina.realm.GenericPrincipal;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.List;
+
+/**
+ * Keycloak authentication valve
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
+    public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
+        return authenticateInternal(request, response, config);
+    }
+
+    @Override
+    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+        if (loginConfig == null) return false;
+        LoginConfig config = (LoginConfig)loginConfig;
+        if (config.getErrorPage() == null) return false;
+        forwardToErrorPage(request, (Response)response, config);
+        return true;
+    }
+
+
+    protected void initInternal() {
+        StandardContext standardContext = (StandardContext) context;
+        standardContext.addLifecycleListener(this);
+    }
+
+    public void logout(Request request) throws ServletException {
+        logoutInternal(request);
+    }
+
+    @Override
+    protected GenericPrincipalFactory createPrincipalFactory() {
+        return new GenericPrincipalFactory() {
+            @Override
+            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
+                return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
+            }
+        };
+    }
+}
diff --git a/integration/tomcat/tomcat8/pom.xml b/integration/tomcat/tomcat8/pom.xml
index 59b5729..c81cde1 100755
--- a/integration/tomcat/tomcat8/pom.xml
+++ b/integration/tomcat/tomcat8/pom.xml
@@ -1,107 +1,107 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-tomcat8-adapter</artifactId>
-	<name>Keycloak Tomcat 8 Integration</name>
-    <properties>
-        <tomcat.version>8.0.14</tomcat.version>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tomcat</groupId>
-            <artifactId>tomcat-servlet-api</artifactId>
-            <version>${tomcat.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tomcat</groupId>
-            <artifactId>tomcat-catalina</artifactId>
-            <version>${tomcat.version}</version>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-tomcat-core-adapter</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>tomcat-catalina</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat</groupId>
-                    <artifactId>catalina</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-tomcat8-adapter</artifactId>
+	<name>Keycloak Tomcat 8 Integration</name>
+    <properties>
+        <tomcat.version>8.0.14</tomcat.version>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-servlet-api</artifactId>
+            <version>${tomcat.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-catalina</artifactId>
+            <version>${tomcat.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-tomcat-core-adapter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>tomcat-catalina</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.tomcat</groupId>
+                    <artifactId>catalina</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index f390fe7..eea4f03 100755
--- a/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -1,74 +1,74 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.authenticator.FormAuthenticator;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.realm.GenericPrincipal;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.descriptor.web.LoginConfig;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.Principal;
-import java.util.List;
-
-/**
- * Keycloak authentication valve
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
-    public boolean authenticate(Request request, HttpServletResponse response) throws IOException {
-       return authenticateInternal(request, response, request.getContext().getLoginConfig());
-    }
-
-    @Override
-    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
-        if (loginConfig == null) return false;
-        LoginConfig config = (LoginConfig)loginConfig;
-        if (config.getErrorPage() == null) return false;
-        // had to do this to get around compiler/IDE issues :(
-        try {
-            Method method = null;
-            /*
-            for (Method m : getClass().getDeclaredMethods()) {
-                if (m.getName().equals("forwardToErrorPage")) {
-                    method = m;
-                    break;
-                }
-            }
-            */
-            method = FormAuthenticator.class.getDeclaredMethod("forwardToErrorPage", Request.class, HttpServletResponse.class, LoginConfig.class);
-            method.setAccessible(true);
-            method.invoke(this, request, response, config);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        return true;
-    }
-
-    protected void initInternal() {
-        StandardContext standardContext = (StandardContext) context;
-        standardContext.addLifecycleListener(this);
-    }
-
-    public void logout(Request request) {
-        logoutInternal(request);
-    }
-
-    @Override
-    protected GenericPrincipalFactory createPrincipalFactory() {
-        return new GenericPrincipalFactory() {
-            @Override
-            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
-                return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
-            }
-        };
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.authenticator.FormAuthenticator;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.descriptor.web.LoginConfig;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Principal;
+import java.util.List;
+
+/**
+ * Keycloak authentication valve
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
+    public boolean authenticate(Request request, HttpServletResponse response) throws IOException {
+       return authenticateInternal(request, response, request.getContext().getLoginConfig());
+    }
+
+    @Override
+    protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+        if (loginConfig == null) return false;
+        LoginConfig config = (LoginConfig)loginConfig;
+        if (config.getErrorPage() == null) return false;
+        // had to do this to get around compiler/IDE issues :(
+        try {
+            Method method = null;
+            /*
+            for (Method m : getClass().getDeclaredMethods()) {
+                if (m.getName().equals("forwardToErrorPage")) {
+                    method = m;
+                    break;
+                }
+            }
+            */
+            method = FormAuthenticator.class.getDeclaredMethod("forwardToErrorPage", Request.class, HttpServletResponse.class, LoginConfig.class);
+            method.setAccessible(true);
+            method.invoke(this, request, response, config);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return true;
+    }
+
+    protected void initInternal() {
+        StandardContext standardContext = (StandardContext) context;
+        standardContext.addLifecycleListener(this);
+    }
+
+    public void logout(Request request) {
+        logoutInternal(request);
+    }
+
+    @Override
+    protected GenericPrincipalFactory createPrincipalFactory() {
+        return new GenericPrincipalFactory() {
+            @Override
+            protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
+                return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
+            }
+        };
+    }
+}
diff --git a/integration/tomcat/tomcat-core/pom.xml b/integration/tomcat/tomcat-core/pom.xml
index 81fdbb0..83ee065 100755
--- a/integration/tomcat/tomcat-core/pom.xml
+++ b/integration/tomcat/tomcat-core/pom.xml
@@ -1,93 +1,93 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../../../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-tomcat-core-adapter</artifactId>
-	<name>Keycloak Tomcat Core Integration</name>
-    <properties>
-        <!-- <tomcat.version>8.0.14</tomcat.version> -->
-        <!-- <tomcat.version>7.0.52</tomcat.version> -->
-        <tomcat.version>6.0.41</tomcat.version>
-    </properties>
-	<description />
-
-	<dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-        </dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.keycloak</groupId>
-			<artifactId>keycloak-adapter-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.iharder</groupId>
-			<artifactId>base64</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.bouncycastle</groupId>
-			<artifactId>bcprov-jdk15on</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-core-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-mapper-asl</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.codehaus.jackson</groupId>
-			<artifactId>jackson-xc</artifactId>
-		</dependency>
-        <!--
-		<dependency>
-			<groupId>org.apache.tomcat</groupId>
-			<artifactId>tomcat-servlet-api</artifactId>
-			<version>${tomcat.version}</version>
-			<scope>compile</scope>
-		</dependency>
-		-->
-		<dependency>
-			<groupId>org.apache.tomcat</groupId>
-			<artifactId>catalina</artifactId>
-            <version>${tomcat.version}</version>
-			<scope>compile</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-tomcat-core-adapter</artifactId>
+	<name>Keycloak Tomcat Core Integration</name>
+    <properties>
+        <!-- <tomcat.version>8.0.14</tomcat.version> -->
+        <!-- <tomcat.version>7.0.52</tomcat.version> -->
+        <tomcat.version>6.0.41</tomcat.version>
+    </properties>
+	<description />
+
+	<dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+        </dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.keycloak</groupId>
+			<artifactId>keycloak-adapter-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.iharder</groupId>
+			<artifactId>base64</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15on</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-core-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-mapper-asl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-xc</artifactId>
+		</dependency>
+        <!--
+		<dependency>
+			<groupId>org.apache.tomcat</groupId>
+			<artifactId>tomcat-servlet-api</artifactId>
+			<version>${tomcat.version}</version>
+			<scope>compile</scope>
+		</dependency>
+		-->
+		<dependency>
+			<groupId>org.apache.tomcat</groupId>
+			<artifactId>catalina</artifactId>
+            <version>${tomcat.version}</version>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
index 7088b46..80663c8 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
@@ -1,253 +1,253 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleEvent;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.Manager;
-import org.apache.catalina.authenticator.Constants;
-import org.apache.catalina.authenticator.FormAuthenticator;
-import org.apache.catalina.authenticator.SavedRequest;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.deploy.LoginConfig;
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AuthChallenge;
-import org.keycloak.adapters.AuthOutcome;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.PreAuthActionsHandler;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.enums.TokenStore;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.keycloak.adapters.KeycloakConfigResolver;
-
-/**
- * Keycloak authentication valve
- * 
- * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticator implements LifecycleListener {
-
-    public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
-
-	private final static Logger log = Logger.getLogger(""+AbstractKeycloakAuthenticatorValve.class);
-	protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
-    protected AdapterDeploymentContext deploymentContext;
-    protected NodesRegistrationManagement nodesRegistrationManagement;
-
-    @Override
-    public void lifecycleEvent(LifecycleEvent event) {
-        if (Lifecycle.START_EVENT.equals(event.getType())) {
-            cache = false;
-        } else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
-        	keycloakInit();
-        } else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
-            beforeStop();
-        }
-    }
-
-    protected void logoutInternal(Request request) {
-        KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
-        if (ksc != null) {
-            CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null);
-            KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-            if (ksc instanceof RefreshableKeycloakSecurityContext) {
-                ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
-            }
-
-            AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
-            tokenStore.logout();
-            request.removeAttribute(KeycloakSecurityContext.class.getName());
-        }
-        request.setUserPrincipal(null);
-    }
-
-    @SuppressWarnings("UseSpecificCatch")
-    public void keycloakInit() {
-        // Possible scenarios:
-        // 1) The deployment has a keycloak.config.resolver specified and it exists:
-        //    Outcome: adapter uses the resolver
-        // 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
-        //    Outcome: adapter is left unconfigured
-        // 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
-        //    Outcome: adapter uses it
-        // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
-        //    Outcome: adapter is left unconfigured
-
-        String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver");
-        if (configResolverClass != null) {
-            try {
-                KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
-                deploymentContext = new AdapterDeploymentContext(configResolver);
-                log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
-            } catch (Exception ex) {
-                log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
-                deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
-            }
-        } else {
-            InputStream configInputStream = getConfigInputStream(context);
-            KeycloakDeployment kd;
-            if (configInputStream == null) {
-                log.fine("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
-                kd = new KeycloakDeployment();
-            } else {
-                kd = KeycloakDeploymentBuilder.build(configInputStream);
-            }
-            deploymentContext = new AdapterDeploymentContext(kd);
-            log.fine("Keycloak is using a per-deployment configuration.");
-        }
-
-        context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
-        AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
-        setNext(actions);
-
-        nodesRegistrationManagement = new NodesRegistrationManagement();
-    }
-
-    protected void beforeStop() {
-        if (nodesRegistrationManagement != null) {
-            nodesRegistrationManagement.stop();
-        }
-    }
-
-    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
-        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
-        if (json == null) {
-            return null;
-        }
-        log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
-        log.finest(json);
-        return new ByteArrayInputStream(json.getBytes());
-    }
-
-    private static InputStream getConfigInputStream(Context context) {
-        InputStream is = getJSONFromServletContext(context.getServletContext());
-        if (is == null) {
-            String path = context.getServletContext().getInitParameter("keycloak.config.file");
-            if (path == null) {
-                log.finest("**** using /WEB-INF/keycloak.json");
-                is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json");
-            } else {
-                try {
-                    is = new FileInputStream(path);
-                } catch (FileNotFoundException e) {
-                    log.log(Level.SEVERE, "NOT FOUND {0}", path);
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-        return is;
-    }
-
-    @Override
-    public void invoke(Request request, Response response) throws IOException, ServletException {
-        try {
-            CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
-            Manager sessionManager = request.getContext().getManager();
-            CatalinaUserSessionManagementWrapper sessionManagementWrapper = new CatalinaUserSessionManagementWrapper(userSessionManagement, sessionManager);
-            PreAuthActionsHandler handler = new PreAuthActionsHandler(sessionManagementWrapper, deploymentContext, facade);
-            if (handler.handleRequest()) {
-                return;
-            }
-            checkKeycloakSession(request, facade);
-            super.invoke(request, response);
-        } finally {
-        }
-    }
-
-    protected abstract GenericPrincipalFactory createPrincipalFactory();
-    protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
-
-    protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
-        CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (deployment == null || !deployment.isConfigured()) {
-            return false;
-        }
-        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
-
-        nodesRegistrationManagement.tryRegister(deployment);
-
-        CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, tokenStore, facade, request, createPrincipalFactory());
-        AuthOutcome outcome = authenticator.authenticate();
-        if (outcome == AuthOutcome.AUTHENTICATED) {
-            if (facade.isEnded()) {
-                return false;
-            }
-            return true;
-        }
-        AuthChallenge challenge = authenticator.getChallenge();
-        if (challenge != null) {
-            if (loginConfig == null) {
-                loginConfig = request.getContext().getLoginConfig();
-            }
-            if (challenge.errorPage()) {
-                if (forwardToErrorPageInternal(request, response, loginConfig))return false;
-            }
-            challenge.challenge(facade);
-        }
-        return false;
-    }
-
-    /**
-     * Checks that access token is still valid.  Will attempt refresh of token if it is not.
-     *
-     * @param request
-     */
-    protected void checkKeycloakSession(Request request, HttpFacade facade) {
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
-        tokenStore.checkCurrentToken();
-    }
-
-    public void keycloakSaveRequest(Request request) throws IOException {
-        saveRequest(request, request.getSessionInternal(true));
-    }
-
-    public boolean keycloakRestoreRequest(Request request) {
-        try {
-            return restoreRequest(request, request.getSessionInternal());
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
-        AdapterTokenStore store = (AdapterTokenStore)request.getNote(TOKEN_STORE_NOTE);
-        if (store != null) {
-            return store;
-        }
-
-        if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
-            store = new CatalinaSessionTokenStore(request, resolvedDeployment, userSessionManagement, createPrincipalFactory(), this);
-        } else {
-            store = new CatalinaCookieTokenStore(request, facade, resolvedDeployment, createPrincipalFactory());
-        }
-
-        request.setNote(TOKEN_STORE_NOTE, store);
-        return store;
-    }
-
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Manager;
+import org.apache.catalina.authenticator.Constants;
+import org.apache.catalina.authenticator.FormAuthenticator;
+import org.apache.catalina.authenticator.SavedRequest;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.deploy.LoginConfig;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AuthChallenge;
+import org.keycloak.adapters.AuthOutcome;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.PreAuthActionsHandler;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.enums.TokenStore;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.keycloak.adapters.KeycloakConfigResolver;
+
+/**
+ * Keycloak authentication valve
+ * 
+ * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticator implements LifecycleListener {
+
+    public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
+
+	private final static Logger log = Logger.getLogger(""+AbstractKeycloakAuthenticatorValve.class);
+	protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
+    protected AdapterDeploymentContext deploymentContext;
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+
+    @Override
+    public void lifecycleEvent(LifecycleEvent event) {
+        if (Lifecycle.START_EVENT.equals(event.getType())) {
+            cache = false;
+        } else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+        	keycloakInit();
+        } else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
+            beforeStop();
+        }
+    }
+
+    protected void logoutInternal(Request request) {
+        KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
+        if (ksc != null) {
+            CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null);
+            KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+            if (ksc instanceof RefreshableKeycloakSecurityContext) {
+                ((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
+            }
+
+            AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
+            tokenStore.logout();
+            request.removeAttribute(KeycloakSecurityContext.class.getName());
+        }
+        request.setUserPrincipal(null);
+    }
+
+    @SuppressWarnings("UseSpecificCatch")
+    public void keycloakInit() {
+        // Possible scenarios:
+        // 1) The deployment has a keycloak.config.resolver specified and it exists:
+        //    Outcome: adapter uses the resolver
+        // 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
+        //    Outcome: adapter is left unconfigured
+        // 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
+        //    Outcome: adapter uses it
+        // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
+        //    Outcome: adapter is left unconfigured
+
+        String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver");
+        if (configResolverClass != null) {
+            try {
+                KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new AdapterDeploymentContext(configResolver);
+                log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
+            } catch (Exception ex) {
+                log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
+                deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+            }
+        } else {
+            InputStream configInputStream = getConfigInputStream(context);
+            KeycloakDeployment kd;
+            if (configInputStream == null) {
+                log.fine("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
+                kd = new KeycloakDeployment();
+            } else {
+                kd = KeycloakDeploymentBuilder.build(configInputStream);
+            }
+            deploymentContext = new AdapterDeploymentContext(kd);
+            log.fine("Keycloak is using a per-deployment configuration.");
+        }
+
+        context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+        AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
+        setNext(actions);
+
+        nodesRegistrationManagement = new NodesRegistrationManagement();
+    }
+
+    protected void beforeStop() {
+        if (nodesRegistrationManagement != null) {
+            nodesRegistrationManagement.stop();
+        }
+    }
+
+    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        if (json == null) {
+            return null;
+        }
+        log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
+        log.finest(json);
+        return new ByteArrayInputStream(json.getBytes());
+    }
+
+    private static InputStream getConfigInputStream(Context context) {
+        InputStream is = getJSONFromServletContext(context.getServletContext());
+        if (is == null) {
+            String path = context.getServletContext().getInitParameter("keycloak.config.file");
+            if (path == null) {
+                log.finest("**** using /WEB-INF/keycloak.json");
+                is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json");
+            } else {
+                try {
+                    is = new FileInputStream(path);
+                } catch (FileNotFoundException e) {
+                    log.log(Level.SEVERE, "NOT FOUND {0}", path);
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return is;
+    }
+
+    @Override
+    public void invoke(Request request, Response response) throws IOException, ServletException {
+        try {
+            CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
+            Manager sessionManager = request.getContext().getManager();
+            CatalinaUserSessionManagementWrapper sessionManagementWrapper = new CatalinaUserSessionManagementWrapper(userSessionManagement, sessionManager);
+            PreAuthActionsHandler handler = new PreAuthActionsHandler(sessionManagementWrapper, deploymentContext, facade);
+            if (handler.handleRequest()) {
+                return;
+            }
+            checkKeycloakSession(request, facade);
+            super.invoke(request, response);
+        } finally {
+        }
+    }
+
+    protected abstract GenericPrincipalFactory createPrincipalFactory();
+    protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
+
+    protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+        CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment == null || !deployment.isConfigured()) {
+            return false;
+        }
+        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
+
+        nodesRegistrationManagement.tryRegister(deployment);
+
+        CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, tokenStore, facade, request, createPrincipalFactory());
+        AuthOutcome outcome = authenticator.authenticate();
+        if (outcome == AuthOutcome.AUTHENTICATED) {
+            if (facade.isEnded()) {
+                return false;
+            }
+            return true;
+        }
+        AuthChallenge challenge = authenticator.getChallenge();
+        if (challenge != null) {
+            if (loginConfig == null) {
+                loginConfig = request.getContext().getLoginConfig();
+            }
+            if (challenge.errorPage()) {
+                if (forwardToErrorPageInternal(request, response, loginConfig))return false;
+            }
+            challenge.challenge(facade);
+        }
+        return false;
+    }
+
+    /**
+     * Checks that access token is still valid.  Will attempt refresh of token if it is not.
+     *
+     * @param request
+     */
+    protected void checkKeycloakSession(Request request, HttpFacade facade) {
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        AdapterTokenStore tokenStore = getTokenStore(request, facade, deployment);
+        tokenStore.checkCurrentToken();
+    }
+
+    public void keycloakSaveRequest(Request request) throws IOException {
+        saveRequest(request, request.getSessionInternal(true));
+    }
+
+    public boolean keycloakRestoreRequest(Request request) {
+        try {
+            return restoreRequest(request, request.getSessionInternal());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
+        AdapterTokenStore store = (AdapterTokenStore)request.getNote(TOKEN_STORE_NOTE);
+        if (store != null) {
+            return store;
+        }
+
+        if (resolvedDeployment.getTokenStore() == TokenStore.SESSION) {
+            store = new CatalinaSessionTokenStore(request, resolvedDeployment, userSessionManagement, createPrincipalFactory(), this);
+        } else {
+            store = new CatalinaCookieTokenStore(request, facade, resolvedDeployment, createPrincipalFactory());
+        }
+
+        request.setNote(TOKEN_STORE_NOTE, store);
+        return store;
+    }
+
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java
index 8cb6e03..8728f36 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java
@@ -1,53 +1,53 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.Valve;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.valves.ValveBase;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AuthenticatedActionsHandler;
-import org.keycloak.adapters.KeycloakDeployment;
-
-import javax.servlet.ServletException;
-import java.io.IOException;
-
-/**
- * Pre-installed actions that must be authenticated
- * <p/>
- * Actions include:
- * <p/>
- * CORS Origin Check and Response headers
- * k_query_bearer_token: Get bearer token from server for Javascripts CORS requests
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticatedActionsValve extends ValveBase {
-    private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
-    protected AdapterDeploymentContext deploymentContext;
-
-    public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
-        this.deploymentContext = deploymentContext;
-        if (next == null) throw new RuntimeException("Next valve is null!!!");
-        setNext(next);
-        setContainer(container);
-    }
-
-
-    @Override
-    public void invoke(Request request, Response response) throws IOException, ServletException {
-        log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
-        CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (deployment != null && deployment.isConfigured()) {
-            AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response));
-            if (handler.handledRequest()) {
-                return;
-            }
-
-        }
-        getNext().invoke(request, response);
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.valves.ValveBase;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.KeycloakDeployment;
+
+import javax.servlet.ServletException;
+import java.io.IOException;
+
+/**
+ * Pre-installed actions that must be authenticated
+ * <p/>
+ * Actions include:
+ * <p/>
+ * CORS Origin Check and Response headers
+ * k_query_bearer_token: Get bearer token from server for Javascripts CORS requests
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticatedActionsValve extends ValveBase {
+    private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
+    protected AdapterDeploymentContext deploymentContext;
+
+    public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
+        this.deploymentContext = deploymentContext;
+        if (next == null) throw new RuntimeException("Next valve is null!!!");
+        setNext(next);
+        setContainer(container);
+    }
+
+
+    @Override
+    public void invoke(Request request, Response response) throws IOException, ServletException {
+        log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
+        CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment != null && deployment.isConfigured()) {
+            AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response));
+            if (handler.handledRequest()) {
+                return;
+            }
+
+        }
+        getNext().invoke(request, response);
+    }
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java
index c30bd3a..ef8a41e 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java
@@ -1,189 +1,189 @@
-package org.keycloak.adapters.tomcat;
-
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.util.MultivaluedHashMap;
-import org.keycloak.util.ServerCookie;
-import org.keycloak.util.UriUtils;
-
-import javax.security.cert.X509Certificate;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CatalinaHttpFacade implements HttpFacade {
-    protected org.apache.catalina.connector.Request request;
-    protected HttpServletResponse response;
-    protected RequestFacade requestFacade = new RequestFacade();
-    protected ResponseFacade responseFacade = new ResponseFacade();
-    protected MultivaluedHashMap<String, String> queryParameters;
-
-    protected class RequestFacade implements Request {
-        @Override
-        public String getURI() {
-            StringBuffer buf = request.getRequestURL();
-            if (request.getQueryString() != null) {
-                buf.append('?').append(request.getQueryString());
-            }
-            return buf.toString();
-        }
-
-        @Override
-        public boolean isSecure() {
-            return request.isSecure();
-        }
-
-        @Override
-        public String getQueryParamValue(String paramName) {
-            if (queryParameters == null) {
-                queryParameters = UriUtils.decodeQueryString(request.getQueryString());
-            }
-            return queryParameters.getFirst(paramName);
-        }
-
-        @Override
-        public Cookie getCookie(String cookieName) {
-            if (request.getCookies() == null) return null;
-            javax.servlet.http.Cookie cookie = null;
-            for (javax.servlet.http.Cookie c : request.getCookies()) {
-                if (c.getName().equals(cookieName)) {
-                    cookie = c;
-                    break;
-                }
-            }
-            if (cookie == null) return null;
-            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
-        }
-
-        @Override
-        public List<String> getHeaders(String name) {
-            Enumeration<String> headers = request.getHeaders(name);
-            if (headers == null) return null;
-            List<String> list = new ArrayList<String>();
-            while (headers.hasMoreElements()) {
-                list.add(headers.nextElement());
-            }
-            return list;
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            try {
-                return request.getInputStream();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public String getMethod() {
-            return request.getMethod();
-        }
-
-        @Override
-        public String getHeader(String name) {
-            return request.getHeader(name);
-        }
-
-        @Override
-        public String getRemoteAddr() {
-            return request.getRemoteAddr();
-        }
-    }
-
-    protected class ResponseFacade implements Response {
-        protected boolean ended;
-
-        @Override
-        public void setStatus(int status) {
-            response.setStatus(status);
-        }
-
-        @Override
-        public void addHeader(String name, String value) {
-            response.addHeader(name, value);
-        }
-
-        @Override
-        public void setHeader(String name, String value) {
-            response.setHeader(name, value);
-        }
-
-        @Override
-        public void resetCookie(String name, String path) {
-            setCookie(name, "", path, null, 0, false, false);
-        }
-
-        @Override
-        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
-            StringBuffer cookieBuf = new StringBuffer();
-            ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, null, maxAge, secure, httpOnly);
-            String cookie = cookieBuf.toString();
-            response.addHeader("Set-Cookie", cookie);
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            try {
-                return response.getOutputStream();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public void sendError(int code, String message) {
-            try {
-                response.sendError(code, message);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public void end() {
-            ended = true;
-        }
-
-        public boolean isEnded() {
-            return ended;
-        }
-    }
-
-    public CatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) {
-        this.request = request;
-        this.response = response;
-    }
-
-    @Override
-    public Request getRequest() {
-        return requestFacade;
-    }
-
-    @Override
-    public Response getResponse() {
-        return responseFacade;
-    }
-
-    @Override
-    public KeycloakSecurityContext getSecurityContext() {
-        return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
-    }
-
-    @Override
-    public X509Certificate[] getCertificateChain() {
-        throw new IllegalStateException("Not supported yet");
-    }
-
-    public boolean isEnded() {
-        return responseFacade.isEnded();
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.util.MultivaluedHashMap;
+import org.keycloak.util.ServerCookie;
+import org.keycloak.util.UriUtils;
+
+import javax.security.cert.X509Certificate;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CatalinaHttpFacade implements HttpFacade {
+    protected org.apache.catalina.connector.Request request;
+    protected HttpServletResponse response;
+    protected RequestFacade requestFacade = new RequestFacade();
+    protected ResponseFacade responseFacade = new ResponseFacade();
+    protected MultivaluedHashMap<String, String> queryParameters;
+
+    protected class RequestFacade implements Request {
+        @Override
+        public String getURI() {
+            StringBuffer buf = request.getRequestURL();
+            if (request.getQueryString() != null) {
+                buf.append('?').append(request.getQueryString());
+            }
+            return buf.toString();
+        }
+
+        @Override
+        public boolean isSecure() {
+            return request.isSecure();
+        }
+
+        @Override
+        public String getQueryParamValue(String paramName) {
+            if (queryParameters == null) {
+                queryParameters = UriUtils.decodeQueryString(request.getQueryString());
+            }
+            return queryParameters.getFirst(paramName);
+        }
+
+        @Override
+        public Cookie getCookie(String cookieName) {
+            if (request.getCookies() == null) return null;
+            javax.servlet.http.Cookie cookie = null;
+            for (javax.servlet.http.Cookie c : request.getCookies()) {
+                if (c.getName().equals(cookieName)) {
+                    cookie = c;
+                    break;
+                }
+            }
+            if (cookie == null) return null;
+            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
+        }
+
+        @Override
+        public List<String> getHeaders(String name) {
+            Enumeration<String> headers = request.getHeaders(name);
+            if (headers == null) return null;
+            List<String> list = new ArrayList<String>();
+            while (headers.hasMoreElements()) {
+                list.add(headers.nextElement());
+            }
+            return list;
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            try {
+                return request.getInputStream();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public String getMethod() {
+            return request.getMethod();
+        }
+
+        @Override
+        public String getHeader(String name) {
+            return request.getHeader(name);
+        }
+
+        @Override
+        public String getRemoteAddr() {
+            return request.getRemoteAddr();
+        }
+    }
+
+    protected class ResponseFacade implements Response {
+        protected boolean ended;
+
+        @Override
+        public void setStatus(int status) {
+            response.setStatus(status);
+        }
+
+        @Override
+        public void addHeader(String name, String value) {
+            response.addHeader(name, value);
+        }
+
+        @Override
+        public void setHeader(String name, String value) {
+            response.setHeader(name, value);
+        }
+
+        @Override
+        public void resetCookie(String name, String path) {
+            setCookie(name, "", path, null, 0, false, false);
+        }
+
+        @Override
+        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
+            StringBuffer cookieBuf = new StringBuffer();
+            ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, null, maxAge, secure, httpOnly);
+            String cookie = cookieBuf.toString();
+            response.addHeader("Set-Cookie", cookie);
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            try {
+                return response.getOutputStream();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void sendError(int code, String message) {
+            try {
+                response.sendError(code, message);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void end() {
+            ended = true;
+        }
+
+        public boolean isEnded() {
+            return ended;
+        }
+    }
+
+    public CatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) {
+        this.request = request;
+        this.response = response;
+    }
+
+    @Override
+    public Request getRequest() {
+        return requestFacade;
+    }
+
+    @Override
+    public Response getResponse() {
+        return responseFacade;
+    }
+
+    @Override
+    public KeycloakSecurityContext getSecurityContext() {
+        return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain() {
+        throw new IllegalStateException("Not supported yet");
+    }
+
+    public boolean isEnded() {
+        return responseFacade.isEnded();
+    }
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
index 0c70636..438f170 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaRequestAuthenticator.java
@@ -1,94 +1,94 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.authenticator.Constants;
-import org.apache.catalina.connector.Request;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.KeycloakAccount;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.OAuthRequestAuthenticator;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.RequestAuthenticator;
-import org.keycloak.enums.TokenStore;
-
-import java.io.IOException;
-import java.security.Principal;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
- * @version $Revision: 1 $
- */
-public class CatalinaRequestAuthenticator extends RequestAuthenticator {
-    private static final Logger log = Logger.getLogger(""+CatalinaRequestAuthenticator.class);
-    protected Request request;
-    protected GenericPrincipalFactory principalFactory;
-
-    public CatalinaRequestAuthenticator(KeycloakDeployment deployment,
-                                        AdapterTokenStore tokenStore,
-                                        CatalinaHttpFacade facade,
-                                        Request request,
-                                        GenericPrincipalFactory principalFactory) {
-        super(facade, deployment, tokenStore, request.getConnector().getRedirectPort());
-        this.request = request;
-        this.principalFactory = principalFactory;
-    }
-
-    @Override
-    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
-        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
-    }
-
-    @Override
-    protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
-        final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
-        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
-        KeycloakAccount account = new KeycloakAccount() {
-
-            @Override
-            public Principal getPrincipal() {
-                return skp;
-            }
-
-            @Override
-            public Set<String> getRoles() {
-                return roles;
-            }
-
-            @Override
-            public KeycloakSecurityContext getKeycloakSecurityContext() {
-                return securityContext;
-            }
-
-        };
-
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-        this.tokenStore.saveAccountInfo(account);
-    }
-
-    @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
-        RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
-        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
-        if (log.isLoggable(Level.FINE)) {
-            log.fine("Completing bearer authentication. Bearer roles: " + roles);
-        }
-        Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
-        request.setUserPrincipal(generalPrincipal);
-        request.setAuthType(method);
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-    }
-
-    @Override
-    protected String getHttpSessionId(boolean create) {
-        HttpSession session = request.getSession(create);
-        return session != null ? session.getId() : null;
-    }
-
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.authenticator.Constants;
+import org.apache.catalina.connector.Request;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OAuthRequestAuthenticator;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.keycloak.enums.TokenStore;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
+ * @version $Revision: 1 $
+ */
+public class CatalinaRequestAuthenticator extends RequestAuthenticator {
+    private static final Logger log = Logger.getLogger(""+CatalinaRequestAuthenticator.class);
+    protected Request request;
+    protected GenericPrincipalFactory principalFactory;
+
+    public CatalinaRequestAuthenticator(KeycloakDeployment deployment,
+                                        AdapterTokenStore tokenStore,
+                                        CatalinaHttpFacade facade,
+                                        Request request,
+                                        GenericPrincipalFactory principalFactory) {
+        super(facade, deployment, tokenStore, request.getConnector().getRedirectPort());
+        this.request = request;
+        this.principalFactory = principalFactory;
+    }
+
+    @Override
+    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
+        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
+    }
+
+    @Override
+    protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
+        final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
+        final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
+        KeycloakAccount account = new KeycloakAccount() {
+
+            @Override
+            public Principal getPrincipal() {
+                return skp;
+            }
+
+            @Override
+            public Set<String> getRoles() {
+                return roles;
+            }
+
+            @Override
+            public KeycloakSecurityContext getKeycloakSecurityContext() {
+                return securityContext;
+            }
+
+        };
+
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+        this.tokenStore.saveAccountInfo(account);
+    }
+
+    @Override
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
+        RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
+        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
+        if (log.isLoggable(Level.FINE)) {
+            log.fine("Completing bearer authentication. Bearer roles: " + roles);
+        }
+        Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
+        request.setUserPrincipal(generalPrincipal);
+        request.setAuthType(method);
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+    }
+
+    @Override
+    protected String getHttpSessionId(boolean create) {
+        HttpSession session = request.getSession(create);
+        return session != null ? session.getId() : null;
+    }
+
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
index 96d13e8..a91ede0 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaSessionTokenStore.java
@@ -1,185 +1,185 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.Session;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.realm.GenericPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.KeycloakAccount;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.RequestAuthenticator;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.security.Principal;
-import java.util.Set;
-import java.util.logging.Logger;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class CatalinaSessionTokenStore implements AdapterTokenStore {
-
-    private static final Logger log = Logger.getLogger("" + CatalinaSessionTokenStore.class);
-
-    private Request request;
-    private KeycloakDeployment deployment;
-    private CatalinaUserSessionManagement sessionManagement;
-    protected GenericPrincipalFactory principalFactory;
-    protected AbstractKeycloakAuthenticatorValve valve;
-
-
-    public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment,
-                                     CatalinaUserSessionManagement sessionManagement,
-                                     GenericPrincipalFactory principalFactory,
-                                     AbstractKeycloakAuthenticatorValve valve) {
-        this.request = request;
-        this.deployment = deployment;
-        this.sessionManagement = sessionManagement;
-        this.principalFactory = principalFactory;
-        this.valve = valve;
-    }
-
-    @Override
-    public void checkCurrentToken() {
-        Session catalinaSession = request.getSessionInternal(false);
-        if (catalinaSession == null) return;
-        SerializableKeycloakAccount account = (SerializableKeycloakAccount) catalinaSession.getSession().getAttribute(SerializableKeycloakAccount.class.getName());
-        if (account == null) {
-            return;
-        }
-
-        RefreshableKeycloakSecurityContext session = account.getKeycloakSecurityContext();
-        if (session == null) return;
-
-        // just in case session got serialized
-        if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
-
-        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
-
-        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
-        // not be updated
-        boolean success = session.refreshExpiredToken(false);
-        if (success && session.isActive()) return;
-
-        // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
-        log.fine("Cleanup and expire session " + catalinaSession.getId() + " after failed refresh");
-        request.setUserPrincipal(null);
-        request.setAuthType(null);
-        cleanSession(catalinaSession);
-        catalinaSession.expire();
-    }
-
-    protected void cleanSession(Session catalinaSession) {
-        catalinaSession.getSession().removeAttribute(KeycloakAccount.class.getName());
-        catalinaSession.setPrincipal(null);
-        catalinaSession.setAuthType(null);
-    }
-
-    @Override
-    public boolean isCached(RequestAuthenticator authenticator) {
-        Session session = request.getSessionInternal(false);
-        if (session == null) return false;
-        SerializableKeycloakAccount account = (SerializableKeycloakAccount) session.getSession().getAttribute(SerializableKeycloakAccount.class.getName());
-        if (account == null) {
-            return false;
-        }
-
-        log.fine("remote logged in already. Establish state from session");
-
-        RefreshableKeycloakSecurityContext securityContext = account.getKeycloakSecurityContext();
-
-        if (!deployment.getRealm().equals(securityContext.getRealm())) {
-            log.fine("Account from cookie is from a different realm than for the request.");
-            cleanSession(session);
-            return false;
-        }
-
-        securityContext.setCurrentRequestInfo(deployment, this);
-        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
-        GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
-        // in clustered environment in JBossWeb, principal is not serialized or saved
-        if (principal == null) {
-            principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), account.getRoles(), securityContext);
-            session.setPrincipal(principal);
-            session.setAuthType("KEYCLOAK");
-
-        }
-        request.setUserPrincipal(principal);
-        request.setAuthType("KEYCLOAK");
-
-        restoreRequest();
-        return true;
-    }
-
-    public static class SerializableKeycloakAccount implements KeycloakAccount, Serializable {
-        protected Set<String> roles;
-        protected Principal principal;
-        protected RefreshableKeycloakSecurityContext securityContext;
-
-        public SerializableKeycloakAccount(Set<String> roles, Principal principal, RefreshableKeycloakSecurityContext securityContext) {
-            this.roles = roles;
-            this.principal = principal;
-            this.securityContext = securityContext;
-        }
-
-        @Override
-        public Principal getPrincipal() {
-            return principal;
-        }
-
-        @Override
-        public Set<String> getRoles() {
-            return roles;
-        }
-
-        @Override
-        public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
-            return securityContext;
-        }
-    }
-
-    @Override
-    public void saveAccountInfo(KeycloakAccount account) {
-        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
-        Set<String> roles = account.getRoles();
-        GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext);
-
-        SerializableKeycloakAccount sAccount = new SerializableKeycloakAccount(roles, account.getPrincipal(), securityContext);
-        Session session = request.getSessionInternal(true);
-        session.setPrincipal(principal);
-        session.setAuthType("KEYCLOAK");
-        session.getSession().setAttribute(SerializableKeycloakAccount.class.getName(), sAccount);
-        String username = securityContext.getToken().getSubject();
-        log.fine("userSessionManagement.login: " + username);
-        this.sessionManagement.login(session);
-    }
-
-    @Override
-    public void logout() {
-        Session session = request.getSessionInternal(false);
-        if (session != null) {
-            cleanSession(session);
-        }
-    }
-
-    @Override
-    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
-        // no-op
-    }
-
-    @Override
-    public void saveRequest() {
-        try {
-            valve.keycloakSaveRequest(request);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public boolean restoreRequest() {
-        return valve.keycloakRestoreRequest(request);
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.Session;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class CatalinaSessionTokenStore implements AdapterTokenStore {
+
+    private static final Logger log = Logger.getLogger("" + CatalinaSessionTokenStore.class);
+
+    private Request request;
+    private KeycloakDeployment deployment;
+    private CatalinaUserSessionManagement sessionManagement;
+    protected GenericPrincipalFactory principalFactory;
+    protected AbstractKeycloakAuthenticatorValve valve;
+
+
+    public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment,
+                                     CatalinaUserSessionManagement sessionManagement,
+                                     GenericPrincipalFactory principalFactory,
+                                     AbstractKeycloakAuthenticatorValve valve) {
+        this.request = request;
+        this.deployment = deployment;
+        this.sessionManagement = sessionManagement;
+        this.principalFactory = principalFactory;
+        this.valve = valve;
+    }
+
+    @Override
+    public void checkCurrentToken() {
+        Session catalinaSession = request.getSessionInternal(false);
+        if (catalinaSession == null) return;
+        SerializableKeycloakAccount account = (SerializableKeycloakAccount) catalinaSession.getSession().getAttribute(SerializableKeycloakAccount.class.getName());
+        if (account == null) {
+            return;
+        }
+
+        RefreshableKeycloakSecurityContext session = account.getKeycloakSecurityContext();
+        if (session == null) return;
+
+        // just in case session got serialized
+        if (session.getDeployment() == null) session.setCurrentRequestInfo(deployment, this);
+
+        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) return;
+
+        // FYI: A refresh requires same scope, so same roles will be set.  Otherwise, refresh will fail and token will
+        // not be updated
+        boolean success = session.refreshExpiredToken(false);
+        if (success && session.isActive()) return;
+
+        // Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
+        log.fine("Cleanup and expire session " + catalinaSession.getId() + " after failed refresh");
+        request.setUserPrincipal(null);
+        request.setAuthType(null);
+        cleanSession(catalinaSession);
+        catalinaSession.expire();
+    }
+
+    protected void cleanSession(Session catalinaSession) {
+        catalinaSession.getSession().removeAttribute(KeycloakAccount.class.getName());
+        catalinaSession.setPrincipal(null);
+        catalinaSession.setAuthType(null);
+    }
+
+    @Override
+    public boolean isCached(RequestAuthenticator authenticator) {
+        Session session = request.getSessionInternal(false);
+        if (session == null) return false;
+        SerializableKeycloakAccount account = (SerializableKeycloakAccount) session.getSession().getAttribute(SerializableKeycloakAccount.class.getName());
+        if (account == null) {
+            return false;
+        }
+
+        log.fine("remote logged in already. Establish state from session");
+
+        RefreshableKeycloakSecurityContext securityContext = account.getKeycloakSecurityContext();
+
+        if (!deployment.getRealm().equals(securityContext.getRealm())) {
+            log.fine("Account from cookie is from a different realm than for the request.");
+            cleanSession(session);
+            return false;
+        }
+
+        securityContext.setCurrentRequestInfo(deployment, this);
+        request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
+        GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
+        // in clustered environment in JBossWeb, principal is not serialized or saved
+        if (principal == null) {
+            principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), account.getRoles(), securityContext);
+            session.setPrincipal(principal);
+            session.setAuthType("KEYCLOAK");
+
+        }
+        request.setUserPrincipal(principal);
+        request.setAuthType("KEYCLOAK");
+
+        restoreRequest();
+        return true;
+    }
+
+    public static class SerializableKeycloakAccount implements KeycloakAccount, Serializable {
+        protected Set<String> roles;
+        protected Principal principal;
+        protected RefreshableKeycloakSecurityContext securityContext;
+
+        public SerializableKeycloakAccount(Set<String> roles, Principal principal, RefreshableKeycloakSecurityContext securityContext) {
+            this.roles = roles;
+            this.principal = principal;
+            this.securityContext = securityContext;
+        }
+
+        @Override
+        public Principal getPrincipal() {
+            return principal;
+        }
+
+        @Override
+        public Set<String> getRoles() {
+            return roles;
+        }
+
+        @Override
+        public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
+            return securityContext;
+        }
+    }
+
+    @Override
+    public void saveAccountInfo(KeycloakAccount account) {
+        RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
+        Set<String> roles = account.getRoles();
+        GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext);
+
+        SerializableKeycloakAccount sAccount = new SerializableKeycloakAccount(roles, account.getPrincipal(), securityContext);
+        Session session = request.getSessionInternal(true);
+        session.setPrincipal(principal);
+        session.setAuthType("KEYCLOAK");
+        session.getSession().setAttribute(SerializableKeycloakAccount.class.getName(), sAccount);
+        String username = securityContext.getToken().getSubject();
+        log.fine("userSessionManagement.login: " + username);
+        this.sessionManagement.login(session);
+    }
+
+    @Override
+    public void logout() {
+        Session session = request.getSessionInternal(false);
+        if (session != null) {
+            cleanSession(session);
+        }
+    }
+
+    @Override
+    public void refreshCallback(RefreshableKeycloakSecurityContext securityContext) {
+        // no-op
+    }
+
+    @Override
+    public void saveRequest() {
+        try {
+            valve.keycloakSaveRequest(request);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public boolean restoreRequest() {
+        return valve.keycloakRestoreRequest(request);
+    }
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaUserSessionManagement.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaUserSessionManagement.java
index 2b302fc..2520f70 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaUserSessionManagement.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaUserSessionManagement.java
@@ -1,77 +1,77 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.Manager;
-import org.apache.catalina.Session;
-import org.apache.catalina.SessionEvent;
-import org.apache.catalina.SessionListener;
-import org.apache.catalina.realm.GenericPrincipal;
-import org.jboss.logging.Logger;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Manages relationship to users and sessions so that forced admin logout can be implemented
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CatalinaUserSessionManagement implements SessionListener {
-    private static final Logger log = Logger.getLogger(CatalinaUserSessionManagement.class);
-
-    public void login(Session session) {
-        session.addSessionListener(this);
-    }
-
-    public void logoutAll(Manager sessionManager) {
-        Session[] allSessions = sessionManager.findSessions();
-        for (Session session : allSessions) {
-            logoutSession(session);
-        }
-    }
-
-    public void logoutHttpSessions(Manager sessionManager, List<String> sessionIds) {
-        log.debug("logoutHttpSessions: " + sessionIds);
-
-        for (String sessionId : sessionIds) {
-            logoutSession(sessionManager, sessionId);
-        }
-    }
-
-    protected void logoutSession(Manager manager, String httpSessionId) {
-        log.debug("logoutHttpSession: " + httpSessionId);
-
-        Session session;
-        try {
-            session = manager.findSession(httpSessionId);
-        } catch (IOException ioe) {
-            log.warn("IO exception when looking for session " + httpSessionId, ioe);
-            return;
-        }
-
-        logoutSession(session);
-    }
-
-    protected void logoutSession(Session session) {
-        try {
-            session.expire();
-        } catch (Exception e) {
-            log.warn("Session not present or already invalidated.", e);
-        }
-    }
-
-    public void sessionEvent(SessionEvent event) {
-        // We only care about session destroyed events
-        if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType()))
-            return;
-
-        // Look up the single session id associated with this session (if any)
-        Session session = event.getSession();
-        log.debugf("Session %s destroyed", session.getId());
-
-        GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
-        if (principal == null) return;
-        session.setPrincipal(null);
-        session.setAuthType(null);
-    }
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.Session;
+import org.apache.catalina.SessionEvent;
+import org.apache.catalina.SessionListener;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.jboss.logging.Logger;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Manages relationship to users and sessions so that forced admin logout can be implemented
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CatalinaUserSessionManagement implements SessionListener {
+    private static final Logger log = Logger.getLogger(CatalinaUserSessionManagement.class);
+
+    public void login(Session session) {
+        session.addSessionListener(this);
+    }
+
+    public void logoutAll(Manager sessionManager) {
+        Session[] allSessions = sessionManager.findSessions();
+        for (Session session : allSessions) {
+            logoutSession(session);
+        }
+    }
+
+    public void logoutHttpSessions(Manager sessionManager, List<String> sessionIds) {
+        log.debug("logoutHttpSessions: " + sessionIds);
+
+        for (String sessionId : sessionIds) {
+            logoutSession(sessionManager, sessionId);
+        }
+    }
+
+    protected void logoutSession(Manager manager, String httpSessionId) {
+        log.debug("logoutHttpSession: " + httpSessionId);
+
+        Session session;
+        try {
+            session = manager.findSession(httpSessionId);
+        } catch (IOException ioe) {
+            log.warn("IO exception when looking for session " + httpSessionId, ioe);
+            return;
+        }
+
+        logoutSession(session);
+    }
+
+    protected void logoutSession(Session session) {
+        try {
+            session.expire();
+        } catch (Exception e) {
+            log.warn("Session not present or already invalidated.", e);
+        }
+    }
+
+    public void sessionEvent(SessionEvent event) {
+        // We only care about session destroyed events
+        if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType()))
+            return;
+
+        // Look up the single session id associated with this session (if any)
+        Session session = event.getSession();
+        log.debugf("Session %s destroyed", session.getId());
+
+        GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
+        if (principal == null) return;
+        session.setPrincipal(null);
+        session.setAuthType(null);
+    }
+}
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/GenericPrincipalFactory.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/GenericPrincipalFactory.java
index 4ff09f7..00190b5 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/GenericPrincipalFactory.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/GenericPrincipalFactory.java
@@ -1,110 +1,110 @@
-package org.keycloak.adapters.tomcat;
-
-import org.apache.catalina.Realm;
-import org.apache.catalina.realm.GenericPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-
-import javax.security.auth.Subject;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
- * @version $Revision: 1 $
- */
-public abstract class GenericPrincipalFactory {
-
-    public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
-        Subject subject = new Subject();
-        Set<Principal> principals = subject.getPrincipals();
-        principals.add(identity);
-        Group[] roleSets = getRoleSets(roleSet);
-        for (int g = 0; g < roleSets.length; g++) {
-            Group group = roleSets[g];
-            String name = group.getName();
-            Group subjectGroup = createGroup(name, principals);
-            // Copy the group members to the Subject group
-            Enumeration<? extends Principal> members = group.members();
-            while (members.hasMoreElements()) {
-                Principal role = (Principal) members.nextElement();
-                subjectGroup.addMember(role);
-            }
-        }
-        
-        Principal userPrincipal = getPrincipal(subject);
-        List<String> rolesAsStringList = new ArrayList<String>();
-        rolesAsStringList.addAll(roleSet);
-        GenericPrincipal principal = createPrincipal(userPrincipal, rolesAsStringList);
-        return principal;
-    }
-
-    protected abstract GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles);
-
-    /**
-     * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
-     * considered or the single subject inside the CallerPrincipal group.
-     *
-     * @param subject
-     * @return the authenticated subject
-     */
-    protected Principal getPrincipal(Subject subject) {
-        Principal principal = null;
-        Principal callerPrincipal = null;
-        if (subject != null) {
-            Set<Principal> principals = subject.getPrincipals();
-            if (principals != null && !principals.isEmpty()) {
-                for (Principal p : principals) {
-                    if (!(p instanceof Group) && principal == null) {
-                        principal = p;
-                    }
-//                    if (p instanceof Group) {
-//                        Group g = Group.class.cast(p);
-//                        if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
-//                            Enumeration<? extends Principal> e = g.members();
-//                            if (e.hasMoreElements())
-//                                callerPrincipal = e.nextElement();
-//                        }
-//                    }
-                }
-            }
-        }
-        return callerPrincipal == null ? principal : callerPrincipal;
-    }
-
-    protected Group createGroup(String name, Set<Principal> principals) {
-        Group roles = null;
-        Iterator<Principal> iter = principals.iterator();
-        while (iter.hasNext()) {
-            Object next = iter.next();
-            if ((next instanceof Group) == false)
-                continue;
-            Group grp = (Group) next;
-            if (grp.getName().equals(name)) {
-                roles = grp;
-                break;
-            }
-        }
-        // If we did not find a group create one
-        if (roles == null) {
-            roles = new SimpleGroup(name);
-            principals.add(roles);
-        }
-        return roles;
-    }
-
-    protected Group[] getRoleSets(Collection<String> roleSet) {
-        SimpleGroup roles = new SimpleGroup("Roles");
-        Group[] roleSets = {roles};
-        for (String role : roleSet) {
-            roles.addMember(new SimplePrincipal(role));
-        }
-        return roleSets;
-    }
-
-}
+package org.keycloak.adapters.tomcat;
+
+import org.apache.catalina.Realm;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
+ * @version $Revision: 1 $
+ */
+public abstract class GenericPrincipalFactory {
+
+    public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
+        Subject subject = new Subject();
+        Set<Principal> principals = subject.getPrincipals();
+        principals.add(identity);
+        Group[] roleSets = getRoleSets(roleSet);
+        for (int g = 0; g < roleSets.length; g++) {
+            Group group = roleSets[g];
+            String name = group.getName();
+            Group subjectGroup = createGroup(name, principals);
+            // Copy the group members to the Subject group
+            Enumeration<? extends Principal> members = group.members();
+            while (members.hasMoreElements()) {
+                Principal role = (Principal) members.nextElement();
+                subjectGroup.addMember(role);
+            }
+        }
+        
+        Principal userPrincipal = getPrincipal(subject);
+        List<String> rolesAsStringList = new ArrayList<String>();
+        rolesAsStringList.addAll(roleSet);
+        GenericPrincipal principal = createPrincipal(userPrincipal, rolesAsStringList);
+        return principal;
+    }
+
+    protected abstract GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles);
+
+    /**
+     * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
+     * considered or the single subject inside the CallerPrincipal group.
+     *
+     * @param subject
+     * @return the authenticated subject
+     */
+    protected Principal getPrincipal(Subject subject) {
+        Principal principal = null;
+        Principal callerPrincipal = null;
+        if (subject != null) {
+            Set<Principal> principals = subject.getPrincipals();
+            if (principals != null && !principals.isEmpty()) {
+                for (Principal p : principals) {
+                    if (!(p instanceof Group) && principal == null) {
+                        principal = p;
+                    }
+//                    if (p instanceof Group) {
+//                        Group g = Group.class.cast(p);
+//                        if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
+//                            Enumeration<? extends Principal> e = g.members();
+//                            if (e.hasMoreElements())
+//                                callerPrincipal = e.nextElement();
+//                        }
+//                    }
+                }
+            }
+        }
+        return callerPrincipal == null ? principal : callerPrincipal;
+    }
+
+    protected Group createGroup(String name, Set<Principal> principals) {
+        Group roles = null;
+        Iterator<Principal> iter = principals.iterator();
+        while (iter.hasNext()) {
+            Object next = iter.next();
+            if ((next instanceof Group) == false)
+                continue;
+            Group grp = (Group) next;
+            if (grp.getName().equals(name)) {
+                roles = grp;
+                break;
+            }
+        }
+        // If we did not find a group create one
+        if (roles == null) {
+            roles = new SimpleGroup(name);
+            principals.add(roles);
+        }
+        return roles;
+    }
+
+    protected Group[] getRoleSets(Collection<String> roleSet) {
+        SimpleGroup roles = new SimpleGroup("Roles");
+        Group[] roleSets = {roles};
+        for (String role : roleSet) {
+            roles.addMember(new SimplePrincipal(role));
+        }
+        return roleSets;
+    }
+
+}
diff --git a/integration/undertow/pom.xml b/integration/undertow/pom.xml
index 0a4d3c1..9b8a12e 100755
--- a/integration/undertow/pom.xml
+++ b/integration/undertow/pom.xml
@@ -1,90 +1,90 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-undertow-adapter</artifactId>
-    <name>Keycloak Undertow Integration</name>
-    <description/>
-
-    <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-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-undertow-adapter</artifactId>
+    <name>Keycloak Undertow Integration</name>
+    <description/>
+
+    <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-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
index a715aa5..f0e467b 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java
@@ -1,91 +1,91 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.session.Session;
-import io.undertow.util.Sessions;
-
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.OAuthRequestAuthenticator;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.RequestAuthenticator;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- * @version $Revision: 1 $
- */
-public abstract class AbstractUndertowRequestAuthenticator extends RequestAuthenticator {
-    protected SecurityContext securityContext;
-    protected HttpServerExchange exchange;
-
-
-    public AbstractUndertowRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
-                                                SecurityContext securityContext, HttpServerExchange exchange,
-                                                AdapterTokenStore tokenStore) {
-        super(facade, deployment, tokenStore, sslRedirectPort);
-        this.securityContext = securityContext;
-        this.exchange = exchange;
-    }
-
-    protected void propagateKeycloakContext(KeycloakUndertowAccount account) {
-        exchange.putAttachment(UndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY, account.getKeycloakSecurityContext());
-    }
-
-    @Override
-    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
-        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
-    }
-
-    @Override
-    protected void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        KeycloakUndertowAccount account = createAccount(principal);
-        securityContext.authenticationComplete(account, "KEYCLOAK", false);
-        propagateKeycloakContext(account);
-        tokenStore.saveAccountInfo(account);
-    }
-
-    @Override
-    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
-        KeycloakUndertowAccount account = createAccount(principal);
-        securityContext.authenticationComplete(account, method, false);
-        propagateKeycloakContext(account);
-    }
-
-    @Override
-    protected String getHttpSessionId(boolean create) {
-        if (create) {
-            Session session = Sessions.getOrCreateSession(exchange);
-            return session.getId();
-        } else {
-            Session session = Sessions.getSession(exchange);
-            return session != null ? session.getId() : null;
-        }
-    }
-
-    /**
-     * Subclasses need to be able to create their own version of the KeycloakUndertowAccount
-     * @return The account
-     */
-    protected abstract KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
-
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.Session;
+import io.undertow.util.Sessions;
+
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OAuthRequestAuthenticator;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.RequestAuthenticator;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractUndertowRequestAuthenticator extends RequestAuthenticator {
+    protected SecurityContext securityContext;
+    protected HttpServerExchange exchange;
+
+
+    public AbstractUndertowRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
+                                                SecurityContext securityContext, HttpServerExchange exchange,
+                                                AdapterTokenStore tokenStore) {
+        super(facade, deployment, tokenStore, sslRedirectPort);
+        this.securityContext = securityContext;
+        this.exchange = exchange;
+    }
+
+    protected void propagateKeycloakContext(KeycloakUndertowAccount account) {
+        exchange.putAttachment(UndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY, account.getKeycloakSecurityContext());
+    }
+
+    @Override
+    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
+        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
+    }
+
+    @Override
+    protected void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        KeycloakUndertowAccount account = createAccount(principal);
+        securityContext.authenticationComplete(account, "KEYCLOAK", false);
+        propagateKeycloakContext(account);
+        tokenStore.saveAccountInfo(account);
+    }
+
+    @Override
+    protected void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method) {
+        KeycloakUndertowAccount account = createAccount(principal);
+        securityContext.authenticationComplete(account, method, false);
+        propagateKeycloakContext(account);
+    }
+
+    @Override
+    protected String getHttpSessionId(boolean create) {
+        if (create) {
+            Session session = Sessions.getOrCreateSession(exchange);
+            return session.getId();
+        } else {
+            Session session = Sessions.getSession(exchange);
+            return session != null ? session.getId() : null;
+        }
+    }
+
+    /**
+     * Subclasses need to be able to create their own version of the KeycloakUndertowAccount
+     * @return The account
+     */
+    protected abstract KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
+
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakChallenge.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakChallenge.java
index 7e8aa2c..46805b0 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakChallenge.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakChallenge.java
@@ -1,29 +1,29 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.api.AuthenticationMechanism;
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakChallenge {
-    public AuthenticationMechanism.ChallengeResult sendChallenge(HttpServerExchange httpServerExchange, SecurityContext securityContext);
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakChallenge {
+    public AuthenticationMechanism.ChallengeResult sendChallenge(HttpServerExchange httpServerExchange, SecurityContext securityContext);
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
index 0258621..fba8b8f 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
@@ -1,207 +1,207 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.api.AuthenticationMechanism;
-import io.undertow.security.api.AuthenticationMechanismFactory;
-import io.undertow.security.idm.Account;
-import io.undertow.security.idm.Credential;
-import io.undertow.security.idm.IdentityManager;
-import io.undertow.server.handlers.form.FormParserFactory;
-import io.undertow.servlet.ServletExtension;
-import io.undertow.servlet.api.AuthMethodConfig;
-import io.undertow.servlet.api.DeploymentInfo;
-import io.undertow.servlet.api.InstanceFactory;
-import io.undertow.servlet.api.InstanceHandle;
-import io.undertow.servlet.api.ListenerInfo;
-import io.undertow.servlet.api.LoginConfig;
-import io.undertow.servlet.api.ServletSessionConfig;
-import io.undertow.servlet.util.ImmediateInstanceHandle;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.KeycloakConfigResolver;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.constants.AdapterConstants;
-
-import javax.servlet.ServletContext;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakServletExtension implements ServletExtension {
-
-    protected static Logger log = Logger.getLogger(KeycloakServletExtension.class);
-
-    // todo when this DeploymentInfo method of the same name is fixed.
-    public boolean isAuthenticationMechanismPresent(DeploymentInfo deploymentInfo, final String mechanismName) {
-        LoginConfig loginConfig = deploymentInfo.getLoginConfig();
-        if (loginConfig != null) {
-            for (AuthMethodConfig method : loginConfig.getAuthMethods()) {
-                if (method.getName().equalsIgnoreCase(mechanismName)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
-        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
-        if (json == null) {
-            return null;
-        }
-        return new ByteArrayInputStream(json.getBytes());
-    }
-
-    private static InputStream getConfigInputStream(ServletContext context) {
-        InputStream is = getJSONFromServletContext(context);
-        if (is == null) {
-            String path = context.getInitParameter("keycloak.config.file");
-            if (path == null) {
-                log.debug("using /WEB-INF/keycloak.json");
-                is = context.getResourceAsStream("/WEB-INF/keycloak.json");
-            } else {
-                try {
-                    is = new FileInputStream(path);
-                } catch (FileNotFoundException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-        return is;
-    }
-
-
-    @Override
-    @SuppressWarnings("UseSpecificCatch")
-    public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
-        if (!isAuthenticationMechanismPresent(deploymentInfo, "KEYCLOAK")) {
-            log.debug("auth-method is not keycloak!");
-            return;
-        }
-        log.debug("KeycloakServletException initialization");
-
-        // Possible scenarios:
-        // 1) The deployment has a keycloak.config.resolver specified and it exists:
-        //    Outcome: adapter uses the resolver
-        // 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
-        //    Outcome: adapter is left unconfigured
-        // 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
-        //    Outcome: adapter uses it
-        // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
-        //    Outcome: adapter is left unconfigured
-
-        KeycloakConfigResolver configResolver;
-        String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
-        AdapterDeploymentContext deploymentContext;
-        if (configResolverClass != null) {
-            try {
-                configResolver = (KeycloakConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
-                deploymentContext = new AdapterDeploymentContext(configResolver);
-                log.info("Using " + configResolverClass + " to resolve Keycloak configuration on a per-request basis.");
-            } catch (Exception ex) {
-                log.warn("The specified resolver " + configResolverClass + " could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: " + ex.getMessage());
-                deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
-            }
-        } else {
-            InputStream is = getConfigInputStream(servletContext);
-            final KeycloakDeployment deployment;
-            if (is == null) {
-                log.warn("No adapter configuration.  Keycloak is unconfigured and will deny all requests.");
-                deployment = new KeycloakDeployment();
-            } else {
-                deployment = KeycloakDeploymentBuilder.build(is);
-            }
-            deploymentContext = new AdapterDeploymentContext(deployment);
-            log.debug("Keycloak is using a per-deployment configuration.");
-        }
-
-        servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
-        UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
-        final NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
-        final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deploymentContext, userSessionManagement, nodesRegistrationManagement);
-
-        UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deploymentContext);
-
-        // setup handlers
-
-        deploymentInfo.addOuterHandlerChainWrapper(new ServletPreAuthActionsHandler.Wrapper(deploymentContext, userSessionManagement));
-        deploymentInfo.addAuthenticationMechanism("KEYCLOAK", new AuthenticationMechanismFactory() {
-            @Override
-            public AuthenticationMechanism create(String s, FormParserFactory formParserFactory, Map<String, String> stringStringMap) {
-                return mech;
-            }
-        }); // authentication
-        deploymentInfo.addInnerHandlerChainWrapper(actions); // handles authenticated actions and cors.
-
-        deploymentInfo.setIdentityManager(new IdentityManager() {
-            @Override
-            public Account verify(Account account) {
-                return account;
-            }
-
-            @Override
-            public Account verify(String id, Credential credential) {
-                throw new IllegalStateException("Should never be called in Keycloak flow");
-            }
-
-            @Override
-            public Account verify(Credential credential) {
-                throw new IllegalStateException("Should never be called in Keycloak flow");
-            }
-        });
-
-        log.debug("Setting jsession cookie path to: " + deploymentInfo.getContextPath());
-        ServletSessionConfig cookieConfig = new ServletSessionConfig();
-        cookieConfig.setPath(deploymentInfo.getContextPath());
-        deploymentInfo.setServletSessionConfig(cookieConfig);
-
-        deploymentInfo.addListener(new ListenerInfo(UndertowNodesRegistrationManagementWrapper.class, new InstanceFactory<UndertowNodesRegistrationManagementWrapper>() {
-
-            @Override
-            public InstanceHandle<UndertowNodesRegistrationManagementWrapper> createInstance() throws InstantiationException {
-                UndertowNodesRegistrationManagementWrapper listener = new UndertowNodesRegistrationManagementWrapper(nodesRegistrationManagement);
-                return new ImmediateInstanceHandle<UndertowNodesRegistrationManagementWrapper>(listener);
-            }
-
-        }));
-    }
-
-    protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
-                                                                    NodesRegistrationManagement nodesRegistrationManagement) {
-        log.debug("creating ServletKeycloakAuthMech");
-        String errorPage = getErrorPage(deploymentInfo);
-        return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager(), errorPage);
-    }
-
-    protected String getErrorPage(DeploymentInfo deploymentInfo) {
-        LoginConfig loginConfig = deploymentInfo.getLoginConfig();
-        String errorPage = null;
-        if (loginConfig != null) {
-            errorPage = loginConfig.getErrorPage();
-        }
-        return errorPage;
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.security.api.AuthenticationMechanismFactory;
+import io.undertow.security.idm.Account;
+import io.undertow.security.idm.Credential;
+import io.undertow.security.idm.IdentityManager;
+import io.undertow.server.handlers.form.FormParserFactory;
+import io.undertow.servlet.ServletExtension;
+import io.undertow.servlet.api.AuthMethodConfig;
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.InstanceFactory;
+import io.undertow.servlet.api.InstanceHandle;
+import io.undertow.servlet.api.ListenerInfo;
+import io.undertow.servlet.api.LoginConfig;
+import io.undertow.servlet.api.ServletSessionConfig;
+import io.undertow.servlet.util.ImmediateInstanceHandle;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.constants.AdapterConstants;
+
+import javax.servlet.ServletContext;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakServletExtension implements ServletExtension {
+
+    protected static Logger log = Logger.getLogger(KeycloakServletExtension.class);
+
+    // todo when this DeploymentInfo method of the same name is fixed.
+    public boolean isAuthenticationMechanismPresent(DeploymentInfo deploymentInfo, final String mechanismName) {
+        LoginConfig loginConfig = deploymentInfo.getLoginConfig();
+        if (loginConfig != null) {
+            for (AuthMethodConfig method : loginConfig.getAuthMethods()) {
+                if (method.getName().equalsIgnoreCase(mechanismName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static InputStream getJSONFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        if (json == null) {
+            return null;
+        }
+        return new ByteArrayInputStream(json.getBytes());
+    }
+
+    private static InputStream getConfigInputStream(ServletContext context) {
+        InputStream is = getJSONFromServletContext(context);
+        if (is == null) {
+            String path = context.getInitParameter("keycloak.config.file");
+            if (path == null) {
+                log.debug("using /WEB-INF/keycloak.json");
+                is = context.getResourceAsStream("/WEB-INF/keycloak.json");
+            } else {
+                try {
+                    is = new FileInputStream(path);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return is;
+    }
+
+
+    @Override
+    @SuppressWarnings("UseSpecificCatch")
+    public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
+        if (!isAuthenticationMechanismPresent(deploymentInfo, "KEYCLOAK")) {
+            log.debug("auth-method is not keycloak!");
+            return;
+        }
+        log.debug("KeycloakServletException initialization");
+
+        // Possible scenarios:
+        // 1) The deployment has a keycloak.config.resolver specified and it exists:
+        //    Outcome: adapter uses the resolver
+        // 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
+        //    Outcome: adapter is left unconfigured
+        // 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
+        //    Outcome: adapter uses it
+        // 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
+        //    Outcome: adapter is left unconfigured
+
+        KeycloakConfigResolver configResolver;
+        String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
+        AdapterDeploymentContext deploymentContext;
+        if (configResolverClass != null) {
+            try {
+                configResolver = (KeycloakConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new AdapterDeploymentContext(configResolver);
+                log.info("Using " + configResolverClass + " to resolve Keycloak configuration on a per-request basis.");
+            } catch (Exception ex) {
+                log.warn("The specified resolver " + configResolverClass + " could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: " + ex.getMessage());
+                deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+            }
+        } else {
+            InputStream is = getConfigInputStream(servletContext);
+            final KeycloakDeployment deployment;
+            if (is == null) {
+                log.warn("No adapter configuration.  Keycloak is unconfigured and will deny all requests.");
+                deployment = new KeycloakDeployment();
+            } else {
+                deployment = KeycloakDeploymentBuilder.build(is);
+            }
+            deploymentContext = new AdapterDeploymentContext(deployment);
+            log.debug("Keycloak is using a per-deployment configuration.");
+        }
+
+        servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+        UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
+        final NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
+        final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deploymentContext, userSessionManagement, nodesRegistrationManagement);
+
+        UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deploymentContext);
+
+        // setup handlers
+
+        deploymentInfo.addOuterHandlerChainWrapper(new ServletPreAuthActionsHandler.Wrapper(deploymentContext, userSessionManagement));
+        deploymentInfo.addAuthenticationMechanism("KEYCLOAK", new AuthenticationMechanismFactory() {
+            @Override
+            public AuthenticationMechanism create(String s, FormParserFactory formParserFactory, Map<String, String> stringStringMap) {
+                return mech;
+            }
+        }); // authentication
+        deploymentInfo.addInnerHandlerChainWrapper(actions); // handles authenticated actions and cors.
+
+        deploymentInfo.setIdentityManager(new IdentityManager() {
+            @Override
+            public Account verify(Account account) {
+                return account;
+            }
+
+            @Override
+            public Account verify(String id, Credential credential) {
+                throw new IllegalStateException("Should never be called in Keycloak flow");
+            }
+
+            @Override
+            public Account verify(Credential credential) {
+                throw new IllegalStateException("Should never be called in Keycloak flow");
+            }
+        });
+
+        log.debug("Setting jsession cookie path to: " + deploymentInfo.getContextPath());
+        ServletSessionConfig cookieConfig = new ServletSessionConfig();
+        cookieConfig.setPath(deploymentInfo.getContextPath());
+        deploymentInfo.setServletSessionConfig(cookieConfig);
+
+        deploymentInfo.addListener(new ListenerInfo(UndertowNodesRegistrationManagementWrapper.class, new InstanceFactory<UndertowNodesRegistrationManagementWrapper>() {
+
+            @Override
+            public InstanceHandle<UndertowNodesRegistrationManagementWrapper> createInstance() throws InstantiationException {
+                UndertowNodesRegistrationManagementWrapper listener = new UndertowNodesRegistrationManagementWrapper(nodesRegistrationManagement);
+                return new ImmediateInstanceHandle<UndertowNodesRegistrationManagementWrapper>(listener);
+            }
+
+        }));
+    }
+
+    protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
+                                                                    NodesRegistrationManagement nodesRegistrationManagement) {
+        log.debug("creating ServletKeycloakAuthMech");
+        String errorPage = getErrorPage(deploymentInfo);
+        return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager(), errorPage);
+    }
+
+    protected String getErrorPage(DeploymentInfo deploymentInfo) {
+        LoginConfig loginConfig = deploymentInfo.getLoginConfig();
+        String errorPage = null;
+        if (loginConfig != null) {
+            errorPage = loginConfig.getErrorPage();
+        }
+        return errorPage;
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
index 82c2727..ea9ab84 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java
@@ -1,95 +1,95 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.idm.Account;
-import org.jboss.logging.Logger;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AdapterUtils;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakAccount;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-
-import java.io.Serializable;
-import java.security.Principal;
-import java.util.Set;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class KeycloakUndertowAccount implements Account, Serializable, KeycloakAccount {
-    protected static Logger log = Logger.getLogger(KeycloakUndertowAccount.class);
-    protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
-    protected Set<String> accountRoles;
-
-    public KeycloakUndertowAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        this.principal = principal;
-        setRoles(principal.getKeycloakSecurityContext());
-    }
-
-    protected void setRoles(RefreshableKeycloakSecurityContext session) {
-        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(session);
-        this.accountRoles = roles;
-    }
-
-    @Override
-    public Principal getPrincipal() {
-        return principal;
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        return accountRoles;
-    }
-
-    @Override
-    public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
-        return principal.getKeycloakSecurityContext();
-    }
-
-    public void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
-        principal.getKeycloakSecurityContext().setCurrentRequestInfo(deployment, tokenStore);
-    }
-
-    // Check if accessToken is active and try to refresh if it's not
-    public boolean checkActive() {
-        // this object may have been serialized, so we need to reset realm config/metadata
-        RefreshableKeycloakSecurityContext session = getKeycloakSecurityContext();
-        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) {
-            log.debug("session is active");
-            return true;
-        }
-
-        log.debug("session is not active or refresh is enforced. Try refresh");
-        boolean success = session.refreshExpiredToken(false);
-        if (!success || !session.isActive()) {
-            log.debug("session is not active return with failure");
-
-            return false;
-        }
-        log.debug("refresh succeeded");
-
-        setRoles(session);
-        return true;
-    }
-
-
-
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.idm.Account;
+import org.jboss.logging.Logger;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakAccount;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Set;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class KeycloakUndertowAccount implements Account, Serializable, KeycloakAccount {
+    protected static Logger log = Logger.getLogger(KeycloakUndertowAccount.class);
+    protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
+    protected Set<String> accountRoles;
+
+    public KeycloakUndertowAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        this.principal = principal;
+        setRoles(principal.getKeycloakSecurityContext());
+    }
+
+    protected void setRoles(RefreshableKeycloakSecurityContext session) {
+        Set<String> roles = AdapterUtils.getRolesFromSecurityContext(session);
+        this.accountRoles = roles;
+    }
+
+    @Override
+    public Principal getPrincipal() {
+        return principal;
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        return accountRoles;
+    }
+
+    @Override
+    public RefreshableKeycloakSecurityContext getKeycloakSecurityContext() {
+        return principal.getKeycloakSecurityContext();
+    }
+
+    public void setCurrentRequestInfo(KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+        principal.getKeycloakSecurityContext().setCurrentRequestInfo(deployment, tokenStore);
+    }
+
+    // Check if accessToken is active and try to refresh if it's not
+    public boolean checkActive() {
+        // this object may have been serialized, so we need to reset realm config/metadata
+        RefreshableKeycloakSecurityContext session = getKeycloakSecurityContext();
+        if (session.isActive() && !session.getDeployment().isAlwaysRefreshToken()) {
+            log.debug("session is active");
+            return true;
+        }
+
+        log.debug("session is not active or refresh is enforced. Try refresh");
+        boolean success = session.refreshExpiredToken(false);
+        if (!success || !session.isActive()) {
+            log.debug("session is not active return with failure");
+
+            return false;
+        }
+        log.debug("refresh succeeded");
+
+        setRoles(session);
+        return true;
+    }
+
+
+
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java
index 3aae9c6..bd56cde 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SavedRequest.java
@@ -1,131 +1,131 @@
-package org.keycloak.adapters.undertow;
-import io.undertow.UndertowLogger;
-import io.undertow.UndertowOptions;
-import io.undertow.server.Connectors;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.session.Session;
-import io.undertow.servlet.handlers.ServletRequestContext;
-import io.undertow.servlet.spec.HttpSessionImpl;
-import io.undertow.util.HeaderMap;
-import io.undertow.util.HeaderValues;
-import io.undertow.util.Headers;
-import io.undertow.util.HttpString;
-import io.undertow.util.ImmediatePooled;
-
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.security.AccessController;
-import java.util.Iterator;
-
-/**
- * Saved servlet request.
- *
- * Note bill burke: I had to fork this because Undertow was automatically restoring the request before the code could be processed and redirected.
- *
- * @author Stuart Douglas
- */
-public class SavedRequest implements Serializable {
-
-    private static final String SESSION_KEY = SavedRequest.class.getName();
-
-    private final byte[] data;
-    private final int dataLength;
-    private final HttpString method;
-    private final String requestUri;
-    private final HeaderMap headerMap;
-
-    public SavedRequest(byte[] data, int dataLength, HttpString method, String requestUri, HeaderMap headerMap) {
-        this.data = data;
-        this.dataLength = dataLength;
-        this.method = method;
-        this.requestUri = requestUri;
-        this.headerMap = headerMap;
-    }
-
-    public static void trySaveRequest(final HttpServerExchange exchange) {
-        int maxSize = exchange.getConnection().getUndertowOptions().get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, 16384);
-        if (maxSize > 0) {
-            //if this request has a body try and cache the response
-            if (!exchange.isRequestComplete()) {
-                final long requestContentLength = exchange.getRequestContentLength();
-                if (requestContentLength > maxSize) {
-                    UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
-                    return;//failed to save the request, we just return
-                }
-                //TODO: we should really be used pooled buffers
-                //TODO: we should probably limit the number of saved requests at any given time
-                byte[] buffer = new byte[maxSize];
-                int read = 0;
-                int res = 0;
-                InputStream in = exchange.getInputStream();
-                try {
-                    while ((res = in.read(buffer, read, buffer.length - read)) > 0) {
-                        read += res;
-                        if (read == maxSize) {
-                            UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
-                            return;//failed to save the request, we just return
-                        }
-                    }
-                    HeaderMap headers = new HeaderMap();
-                    for(HeaderValues entry : exchange.getRequestHeaders()) {
-                        if(entry.getHeaderName().equals(Headers.CONTENT_LENGTH) ||
-                                entry.getHeaderName().equals(Headers.TRANSFER_ENCODING) ||
-                                entry.getHeaderName().equals(Headers.CONNECTION)) {
-                            continue;
-                        }
-                        headers.putAll(entry.getHeaderName(), entry);
-                    }
-                    SavedRequest request = new SavedRequest(buffer, read, exchange.getRequestMethod(), exchange.getRequestURI(), exchange.getRequestHeaders());
-                    final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
-                    HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true);
-                    Session underlyingSession;
-                    if(System.getSecurityManager() == null) {
-                        underlyingSession = session.getSession();
-                    } else {
-                        underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
-                    }
-                    underlyingSession.setAttribute(SESSION_KEY, request);
-                } catch (IOException e) {
-                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
-                }
-            }
-        }
-    }
-
-    public static void tryRestoreRequest(final HttpServerExchange exchange, HttpSession session) {
-        if(session instanceof HttpSessionImpl) {
-
-            Session underlyingSession;
-            if(System.getSecurityManager() == null) {
-                underlyingSession = ((HttpSessionImpl) session).getSession();
-            } else {
-                underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
-            }
-            SavedRequest request = (SavedRequest) underlyingSession.getAttribute(SESSION_KEY);
-            if(request != null) {
-                if(request.requestUri.equals(exchange.getRequestURI()) && exchange.isRequestComplete()) {
-                    UndertowLogger.REQUEST_LOGGER.debugf("restoring request body for request to %s", request.requestUri);
-                    exchange.setRequestMethod(request.method);
-                    Connectors.ungetRequestBytes(exchange, new ImmediatePooled<ByteBuffer>(ByteBuffer.wrap(request.data, 0, request.dataLength)));
-                    underlyingSession.removeAttribute(SESSION_KEY);
-                    //clear the existing header map of everything except the connection header
-                    //TODO: are there other headers we should preserve?
-                    Iterator<HeaderValues> headerIterator = exchange.getRequestHeaders().iterator();
-                    while (headerIterator.hasNext()) {
-                        HeaderValues header = headerIterator.next();
-                        if(!header.getHeaderName().equals(Headers.CONNECTION)) {
-                            headerIterator.remove();
-                        }
-                    }
-                    for(HeaderValues header : request.headerMap) {
-                        exchange.getRequestHeaders().putAll(header.getHeaderName(), header);
-                    }
-                }
-            }
-        }
-    }
-
-}
+package org.keycloak.adapters.undertow;
+import io.undertow.UndertowLogger;
+import io.undertow.UndertowOptions;
+import io.undertow.server.Connectors;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.Session;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import io.undertow.servlet.spec.HttpSessionImpl;
+import io.undertow.util.HeaderMap;
+import io.undertow.util.HeaderValues;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import io.undertow.util.ImmediatePooled;
+
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.util.Iterator;
+
+/**
+ * Saved servlet request.
+ *
+ * Note bill burke: I had to fork this because Undertow was automatically restoring the request before the code could be processed and redirected.
+ *
+ * @author Stuart Douglas
+ */
+public class SavedRequest implements Serializable {
+
+    private static final String SESSION_KEY = SavedRequest.class.getName();
+
+    private final byte[] data;
+    private final int dataLength;
+    private final HttpString method;
+    private final String requestUri;
+    private final HeaderMap headerMap;
+
+    public SavedRequest(byte[] data, int dataLength, HttpString method, String requestUri, HeaderMap headerMap) {
+        this.data = data;
+        this.dataLength = dataLength;
+        this.method = method;
+        this.requestUri = requestUri;
+        this.headerMap = headerMap;
+    }
+
+    public static void trySaveRequest(final HttpServerExchange exchange) {
+        int maxSize = exchange.getConnection().getUndertowOptions().get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, 16384);
+        if (maxSize > 0) {
+            //if this request has a body try and cache the response
+            if (!exchange.isRequestComplete()) {
+                final long requestContentLength = exchange.getRequestContentLength();
+                if (requestContentLength > maxSize) {
+                    UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
+                    return;//failed to save the request, we just return
+                }
+                //TODO: we should really be used pooled buffers
+                //TODO: we should probably limit the number of saved requests at any given time
+                byte[] buffer = new byte[maxSize];
+                int read = 0;
+                int res = 0;
+                InputStream in = exchange.getInputStream();
+                try {
+                    while ((res = in.read(buffer, read, buffer.length - read)) > 0) {
+                        read += res;
+                        if (read == maxSize) {
+                            UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
+                            return;//failed to save the request, we just return
+                        }
+                    }
+                    HeaderMap headers = new HeaderMap();
+                    for(HeaderValues entry : exchange.getRequestHeaders()) {
+                        if(entry.getHeaderName().equals(Headers.CONTENT_LENGTH) ||
+                                entry.getHeaderName().equals(Headers.TRANSFER_ENCODING) ||
+                                entry.getHeaderName().equals(Headers.CONNECTION)) {
+                            continue;
+                        }
+                        headers.putAll(entry.getHeaderName(), entry);
+                    }
+                    SavedRequest request = new SavedRequest(buffer, read, exchange.getRequestMethod(), exchange.getRequestURI(), exchange.getRequestHeaders());
+                    final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+                    HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true);
+                    Session underlyingSession;
+                    if(System.getSecurityManager() == null) {
+                        underlyingSession = session.getSession();
+                    } else {
+                        underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
+                    }
+                    underlyingSession.setAttribute(SESSION_KEY, request);
+                } catch (IOException e) {
+                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
+                }
+            }
+        }
+    }
+
+    public static void tryRestoreRequest(final HttpServerExchange exchange, HttpSession session) {
+        if(session instanceof HttpSessionImpl) {
+
+            Session underlyingSession;
+            if(System.getSecurityManager() == null) {
+                underlyingSession = ((HttpSessionImpl) session).getSession();
+            } else {
+                underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
+            }
+            SavedRequest request = (SavedRequest) underlyingSession.getAttribute(SESSION_KEY);
+            if(request != null) {
+                if(request.requestUri.equals(exchange.getRequestURI()) && exchange.isRequestComplete()) {
+                    UndertowLogger.REQUEST_LOGGER.debugf("restoring request body for request to %s", request.requestUri);
+                    exchange.setRequestMethod(request.method);
+                    Connectors.ungetRequestBytes(exchange, new ImmediatePooled<ByteBuffer>(ByteBuffer.wrap(request.data, 0, request.dataLength)));
+                    underlyingSession.removeAttribute(SESSION_KEY);
+                    //clear the existing header map of everything except the connection header
+                    //TODO: are there other headers we should preserve?
+                    Iterator<HeaderValues> headerIterator = exchange.getRequestHeaders().iterator();
+                    while (headerIterator.hasNext()) {
+                        HeaderValues header = headerIterator.next();
+                        if(!header.getHeaderName().equals(Headers.CONNECTION)) {
+                            headerIterator.remove();
+                        }
+                    }
+                    for(HeaderValues header : request.headerMap) {
+                        exchange.getRequestHeaders().putAll(header.getHeaderName(), header);
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
index 144210f..f4b6ef3 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
@@ -1,124 +1,124 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.api.AuthenticationMechanism;
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.servlet.api.ConfidentialPortManager;
-import io.undertow.servlet.handlers.ServletRequestContext;
-import io.undertow.util.Headers;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.AuthChallenge;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.RequestAuthenticator;
-import org.keycloak.enums.TokenStore;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- * @version $Revision: 1 $
- */
-public class ServletKeycloakAuthMech extends AbstractUndertowKeycloakAuthMech {
-    private static final Logger log = Logger.getLogger(ServletKeycloakAuthMech.class);
-
-    protected NodesRegistrationManagement nodesRegistrationManagement;
-    protected ConfidentialPortManager portManager;
-
-    public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
-                                   NodesRegistrationManagement nodesRegistrationManagement, ConfidentialPortManager portManager,
-                                   String errorPage) {
-        super(deploymentContext, userSessionManagement, errorPage);
-        this.nodesRegistrationManagement = nodesRegistrationManagement;
-        this.portManager = portManager;
-    }
-
-    @Override
-    protected Integer servePage(HttpServerExchange exchange, String location) {
-        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
-        ServletRequest req = servletRequestContext.getServletRequest();
-        ServletResponse resp = servletRequestContext.getServletResponse();
-        RequestDispatcher disp = req.getRequestDispatcher(location);
-        //make sure the login page is never cached
-        exchange.getResponseHeaders().add(Headers.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
-        exchange.getResponseHeaders().add(Headers.PRAGMA, "no-cache");
-        exchange.getResponseHeaders().add(Headers.EXPIRES, "0");
-
-
-        try {
-            disp.forward(req, resp);
-        } catch (ServletException e) {
-            throw new RuntimeException(e);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return null;
-    }
-
-    @Override
-    public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
-        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (!deployment.isConfigured()) {
-            return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
-        }
-
-        nodesRegistrationManagement.tryRegister(deployment);
-
-        RequestAuthenticator authenticator = createRequestAuthenticator(deployment, exchange, securityContext, facade);
-
-        return keycloakAuthenticate(exchange, securityContext, authenticator);
-    }
-
-    protected RequestAuthenticator createRequestAuthenticator(KeycloakDeployment deployment, HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
-
-        int confidentialPort = getConfidentilPort(exchange);
-        AdapterTokenStore tokenStore = getTokenStore(exchange, facade, deployment, securityContext);
-        return new ServletRequestAuthenticator(facade, deployment,
-                confidentialPort, securityContext, exchange, tokenStore);
-    }
-
-    protected int getConfidentilPort(HttpServerExchange exchange) {
-        int confidentialPort = 8443;
-        if (exchange.getRequestScheme().equalsIgnoreCase("HTTPS")) {
-            confidentialPort = exchange.getHostPort();
-        } else if (portManager != null) {
-            confidentialPort = portManager.getConfidentialPort(exchange);
-        }
-        return confidentialPort;
-    }
-
-    @Override
-    protected AdapterTokenStore getTokenStore(HttpServerExchange exchange, HttpFacade facade, KeycloakDeployment deployment, SecurityContext securityContext) {
-        if (deployment.getTokenStore() == TokenStore.SESSION) {
-            return new ServletSessionTokenStore(exchange, deployment, sessionManagement, securityContext);
-        } else {
-            return new UndertowCookieTokenStore(facade, deployment, securityContext);
-        }
-    }
-
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.servlet.api.ConfidentialPortManager;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import io.undertow.util.Headers;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AuthChallenge;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.RequestAuthenticator;
+import org.keycloak.enums.TokenStore;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
+ * @version $Revision: 1 $
+ */
+public class ServletKeycloakAuthMech extends AbstractUndertowKeycloakAuthMech {
+    private static final Logger log = Logger.getLogger(ServletKeycloakAuthMech.class);
+
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+    protected ConfidentialPortManager portManager;
+
+    public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
+                                   NodesRegistrationManagement nodesRegistrationManagement, ConfidentialPortManager portManager,
+                                   String errorPage) {
+        super(deploymentContext, userSessionManagement, errorPage);
+        this.nodesRegistrationManagement = nodesRegistrationManagement;
+        this.portManager = portManager;
+    }
+
+    @Override
+    protected Integer servePage(HttpServerExchange exchange, String location) {
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        ServletRequest req = servletRequestContext.getServletRequest();
+        ServletResponse resp = servletRequestContext.getServletResponse();
+        RequestDispatcher disp = req.getRequestDispatcher(location);
+        //make sure the login page is never cached
+        exchange.getResponseHeaders().add(Headers.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
+        exchange.getResponseHeaders().add(Headers.PRAGMA, "no-cache");
+        exchange.getResponseHeaders().add(Headers.EXPIRES, "0");
+
+
+        try {
+            disp.forward(req, resp);
+        } catch (ServletException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
+    @Override
+    public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
+        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (!deployment.isConfigured()) {
+            return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
+        }
+
+        nodesRegistrationManagement.tryRegister(deployment);
+
+        RequestAuthenticator authenticator = createRequestAuthenticator(deployment, exchange, securityContext, facade);
+
+        return keycloakAuthenticate(exchange, securityContext, authenticator);
+    }
+
+    protected RequestAuthenticator createRequestAuthenticator(KeycloakDeployment deployment, HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
+
+        int confidentialPort = getConfidentilPort(exchange);
+        AdapterTokenStore tokenStore = getTokenStore(exchange, facade, deployment, securityContext);
+        return new ServletRequestAuthenticator(facade, deployment,
+                confidentialPort, securityContext, exchange, tokenStore);
+    }
+
+    protected int getConfidentilPort(HttpServerExchange exchange) {
+        int confidentialPort = 8443;
+        if (exchange.getRequestScheme().equalsIgnoreCase("HTTPS")) {
+            confidentialPort = exchange.getHostPort();
+        } else if (portManager != null) {
+            confidentialPort = portManager.getConfidentialPort(exchange);
+        }
+        return confidentialPort;
+    }
+
+    @Override
+    protected AdapterTokenStore getTokenStore(HttpServerExchange exchange, HttpFacade facade, KeycloakDeployment deployment, SecurityContext securityContext) {
+        if (deployment.getTokenStore() == TokenStore.SESSION) {
+            return new ServletSessionTokenStore(exchange, deployment, sessionManagement, securityContext);
+        } else {
+            return new UndertowCookieTokenStore(facade, deployment, securityContext);
+        }
+    }
+
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
index d7059f7..61e66c4 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
@@ -1,71 +1,71 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.HandlerWrapper;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.servlet.handlers.ServletRequestContext;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.PreAuthActionsHandler;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ServletPreAuthActionsHandler implements HttpHandler {
-
-    private static final Logger log = Logger.getLogger(ServletPreAuthActionsHandler.class);
-    protected HttpHandler next;
-    protected UndertowUserSessionManagement userSessionManagement;
-    protected AdapterDeploymentContext deploymentContext;
-
-    public static class Wrapper implements HandlerWrapper {
-        protected AdapterDeploymentContext deploymentContext;
-        protected UndertowUserSessionManagement userSessionManagement;
-
-
-        public Wrapper(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement) {
-            this.deploymentContext = deploymentContext;
-            this.userSessionManagement = userSessionManagement;
-        }
-
-        @Override
-        public HttpHandler wrap(HttpHandler handler) {
-            return new ServletPreAuthActionsHandler(deploymentContext, userSessionManagement, handler);
-        }
-    }
-
-    protected ServletPreAuthActionsHandler(AdapterDeploymentContext deploymentContext,
-                                           UndertowUserSessionManagement userSessionManagement,
-                                           HttpHandler next) {
-        this.next = next;
-        this.deploymentContext = deploymentContext;
-        this.userSessionManagement = userSessionManagement;
-    }
-
-    @Override
-    public void handleRequest(HttpServerExchange exchange) throws Exception {
-        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
-        SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, servletRequestContext.getDeployment().getSessionManager());
-        PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade);
-        if (handler.handleRequest()) return;
-        next.handleRequest(exchange);
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.HandlerWrapper;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.PreAuthActionsHandler;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ServletPreAuthActionsHandler implements HttpHandler {
+
+    private static final Logger log = Logger.getLogger(ServletPreAuthActionsHandler.class);
+    protected HttpHandler next;
+    protected UndertowUserSessionManagement userSessionManagement;
+    protected AdapterDeploymentContext deploymentContext;
+
+    public static class Wrapper implements HandlerWrapper {
+        protected AdapterDeploymentContext deploymentContext;
+        protected UndertowUserSessionManagement userSessionManagement;
+
+
+        public Wrapper(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement) {
+            this.deploymentContext = deploymentContext;
+            this.userSessionManagement = userSessionManagement;
+        }
+
+        @Override
+        public HttpHandler wrap(HttpHandler handler) {
+            return new ServletPreAuthActionsHandler(deploymentContext, userSessionManagement, handler);
+        }
+    }
+
+    protected ServletPreAuthActionsHandler(AdapterDeploymentContext deploymentContext,
+                                           UndertowUserSessionManagement userSessionManagement,
+                                           HttpHandler next) {
+        this.next = next;
+        this.deploymentContext = deploymentContext;
+        this.userSessionManagement = userSessionManagement;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, servletRequestContext.getDeployment().getSessionManager());
+        PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade);
+        if (handler.handleRequest()) return;
+        next.handleRequest(exchange);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
index 806fb9f..812a685 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletRequestAuthenticator.java
@@ -1,78 +1,78 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.servlet.handlers.ServletRequestContext;
-import io.undertow.servlet.util.SavedRequest;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.OAuthRequestAuthenticator;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.enums.TokenStore;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- * @version $Revision: 1 $
- */
-public class ServletRequestAuthenticator extends AbstractUndertowRequestAuthenticator {
-
-
-    public ServletRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
-                                       SecurityContext securityContext, HttpServerExchange exchange,
-                                       AdapterTokenStore tokenStore) {
-        super(facade, deployment, sslRedirectPort, securityContext, exchange, tokenStore);
-    }
-
-    @Override
-    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
-        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
-    }
-
-    @Override
-    protected void propagateKeycloakContext(KeycloakUndertowAccount account) {
-        super.propagateKeycloakContext(account);
-        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
-        HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
-        req.setAttribute(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
-    }
-
-    @Override
-    protected KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        return new KeycloakUndertowAccount(principal);
-    }
-
-    @Override
-    protected String getHttpSessionId(boolean create) {
-        HttpSession session = getSession(create);
-        return session != null ? session.getId() : null;
-    }
-
-    protected HttpSession getSession(boolean create) {
-        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
-        HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
-        return req.getSession(create);
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import io.undertow.servlet.util.SavedRequest;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.OAuthRequestAuthenticator;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.enums.TokenStore;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
+ * @version $Revision: 1 $
+ */
+public class ServletRequestAuthenticator extends AbstractUndertowRequestAuthenticator {
+
+
+    public ServletRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
+                                       SecurityContext securityContext, HttpServerExchange exchange,
+                                       AdapterTokenStore tokenStore) {
+        super(facade, deployment, sslRedirectPort, securityContext, exchange, tokenStore);
+    }
+
+    @Override
+    protected OAuthRequestAuthenticator createOAuthAuthenticator() {
+        return new OAuthRequestAuthenticator(this, facade, deployment, sslRedirectPort, tokenStore);
+    }
+
+    @Override
+    protected void propagateKeycloakContext(KeycloakUndertowAccount account) {
+        super.propagateKeycloakContext(account);
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
+        req.setAttribute(KeycloakSecurityContext.class.getName(), account.getKeycloakSecurityContext());
+    }
+
+    @Override
+    protected KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        return new KeycloakUndertowAccount(principal);
+    }
+
+    @Override
+    protected String getHttpSessionId(boolean create) {
+        HttpSession session = getSession(create);
+        return session != null ? session.getId() : null;
+    }
+
+    protected HttpSession getSession(boolean create) {
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        HttpServletRequest req = (HttpServletRequest) servletRequestContext.getServletRequest();
+        return req.getSession(create);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java
index 839d39e..a0cde4c 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/SessionManagementBridge.java
@@ -1,48 +1,48 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.session.SessionManager;
-import org.keycloak.adapters.UserSessionManagement;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SessionManagementBridge implements UserSessionManagement {
-
-    protected UndertowUserSessionManagement userSessionManagement;
-    protected SessionManager sessionManager;
-
-    public SessionManagementBridge(UndertowUserSessionManagement userSessionManagement, SessionManager sessionManager) {
-        this.userSessionManagement = userSessionManagement;
-        this.sessionManager = sessionManager;
-    }
-
-    @Override
-    public void logoutAll() {
-        userSessionManagement.logoutAll(sessionManager);
-    }
-
-    @Override
-    public void logoutHttpSessions(List<String> ids) {
-        userSessionManagement.logoutHttpSessions(sessionManager, ids);
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.session.SessionManager;
+import org.keycloak.adapters.UserSessionManagement;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SessionManagementBridge implements UserSessionManagement {
+
+    protected UndertowUserSessionManagement userSessionManagement;
+    protected SessionManager sessionManager;
+
+    public SessionManagementBridge(UndertowUserSessionManagement userSessionManagement, SessionManager sessionManager) {
+        this.userSessionManagement = userSessionManagement;
+        this.sessionManager = sessionManager;
+    }
+
+    @Override
+    public void logoutAll() {
+        userSessionManagement.logoutAll(sessionManager);
+    }
+
+    @Override
+    public void logoutHttpSessions(List<String> ids) {
+        userSessionManagement.logoutHttpSessions(sessionManager, ids);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
index 7fb6046..a21272e 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
@@ -1,68 +1,68 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.HandlerWrapper;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AuthenticatedActionsHandler;
-import org.keycloak.adapters.KeycloakDeployment;
-
-/**
- * Bridge for authenticated Keycloak adapter actions
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
- * @version $Revision: 1 $
- */
-public class UndertowAuthenticatedActionsHandler implements HttpHandler {
-    private static final Logger log = Logger.getLogger(UndertowAuthenticatedActionsHandler.class);
-    protected AdapterDeploymentContext deploymentContext;
-    protected HttpHandler next;
-
-    public static class Wrapper implements HandlerWrapper {
-        protected AdapterDeploymentContext deploymentContext;
-
-        public Wrapper(AdapterDeploymentContext deploymentContext) {
-            this.deploymentContext = deploymentContext;
-        }
-
-        @Override
-        public HttpHandler wrap(HttpHandler handler) {
-            return new UndertowAuthenticatedActionsHandler(deploymentContext, handler);
-        }
-    }
-
-
-    public UndertowAuthenticatedActionsHandler(AdapterDeploymentContext deploymentContext, HttpHandler next) {
-        this.deploymentContext = deploymentContext;
-        this.next = next;
-    }
-
-    @Override
-    public void handleRequest(HttpServerExchange exchange) throws Exception {
-        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (deployment != null && deployment.isConfigured()) {
-            AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, facade);
-            if (handler.handledRequest()) return;
-        }
-        next.handleRequest(exchange);
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.HandlerWrapper;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AuthenticatedActionsHandler;
+import org.keycloak.adapters.KeycloakDeployment;
+
+/**
+ * Bridge for authenticated Keycloak adapter actions
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
+ * @version $Revision: 1 $
+ */
+public class UndertowAuthenticatedActionsHandler implements HttpHandler {
+    private static final Logger log = Logger.getLogger(UndertowAuthenticatedActionsHandler.class);
+    protected AdapterDeploymentContext deploymentContext;
+    protected HttpHandler next;
+
+    public static class Wrapper implements HandlerWrapper {
+        protected AdapterDeploymentContext deploymentContext;
+
+        public Wrapper(AdapterDeploymentContext deploymentContext) {
+            this.deploymentContext = deploymentContext;
+        }
+
+        @Override
+        public HttpHandler wrap(HttpHandler handler) {
+            return new UndertowAuthenticatedActionsHandler(deploymentContext, handler);
+        }
+    }
+
+
+    public UndertowAuthenticatedActionsHandler(AdapterDeploymentContext deploymentContext, HttpHandler next) {
+        this.deploymentContext = deploymentContext;
+        this.next = next;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (deployment != null && deployment.isConfigured()) {
+            AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, facade);
+            if (handler.handledRequest()) return;
+        }
+        next.handleRequest(exchange);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
index b408255..b55067b 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
@@ -1,42 +1,42 @@
-package org.keycloak.adapters.undertow;
-
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.RequestAuthenticator;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UndertowAuthenticationMechanism extends AbstractUndertowKeycloakAuthMech {
-    protected NodesRegistrationManagement nodesRegistrationManagement;
-    protected int confidentialPort;
-
-    public UndertowAuthenticationMechanism(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement,
-                                           NodesRegistrationManagement nodesRegistrationManagement, int confidentialPort, String errorPage) {
-        super(deploymentContext, sessionManagement, errorPage);
-        this.nodesRegistrationManagement = nodesRegistrationManagement;
-        this.confidentialPort = confidentialPort;
-    }
-
-    @Override
-    public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
-        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
-        if (!deployment.isConfigured()) {
-            return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
-        }
-
-        nodesRegistrationManagement.tryRegister(deployment);
-
-        AdapterTokenStore tokenStore = getTokenStore(exchange, facade, deployment, securityContext);
-        RequestAuthenticator authenticator = new UndertowRequestAuthenticator(facade, deployment, confidentialPort, securityContext, exchange, tokenStore);
-
-        return keycloakAuthenticate(exchange, securityContext, authenticator);
-    }
-
-}
+package org.keycloak.adapters.undertow;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.RequestAuthenticator;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UndertowAuthenticationMechanism extends AbstractUndertowKeycloakAuthMech {
+    protected NodesRegistrationManagement nodesRegistrationManagement;
+    protected int confidentialPort;
+
+    public UndertowAuthenticationMechanism(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement,
+                                           NodesRegistrationManagement nodesRegistrationManagement, int confidentialPort, String errorPage) {
+        super(deploymentContext, sessionManagement, errorPage);
+        this.nodesRegistrationManagement = nodesRegistrationManagement;
+        this.confidentialPort = confidentialPort;
+    }
+
+    @Override
+    public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
+        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+        KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+        if (!deployment.isConfigured()) {
+            return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
+        }
+
+        nodesRegistrationManagement.tryRegister(deployment);
+
+        AdapterTokenStore tokenStore = getTokenStore(exchange, facade, deployment, securityContext);
+        RequestAuthenticator authenticator = new UndertowRequestAuthenticator(facade, deployment, confidentialPort, securityContext, exchange, tokenStore);
+
+        return keycloakAuthenticate(exchange, securityContext, authenticator);
+    }
+
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java
index ce1d7ba..c864760 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java
@@ -1,211 +1,211 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.handlers.CookieImpl;
-import io.undertow.util.AttachmentKey;
-import io.undertow.util.Headers;
-import io.undertow.util.HttpString;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.util.KeycloakUriBuilder;
-
-import javax.security.cert.X509Certificate;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.util.Deque;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UndertowHttpFacade implements HttpFacade {
-    public static final AttachmentKey<KeycloakSecurityContext> KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class);
-
-    protected HttpServerExchange exchange;
-    protected RequestFacade requestFacade = new RequestFacade();
-    protected ResponseFacade responseFacade = new ResponseFacade();
-
-    protected class RequestFacade implements Request {
-        @Override
-        public String getURI() {
-            KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(exchange.getRequestURI())
-                    .replaceQuery(exchange.getQueryString());
-            if (!exchange.isHostIncludedInRequestURI()) uriBuilder.scheme(exchange.getRequestScheme()).host(exchange.getHostAndPort());
-            return uriBuilder.build().toString();
-        }
-
-        @Override
-        public boolean isSecure() {
-            String protocol = exchange.getRequestScheme();
-            return protocol.equalsIgnoreCase("https");
-        }
-
-        @Override
-        public String getQueryParamValue(String param) {
-            Map<String,Deque<String>> queryParameters = exchange.getQueryParameters();
-            if (queryParameters == null) return null;
-            Deque<String> strings = queryParameters.get(param);
-            if (strings == null) return null;
-            return strings.getFirst();
-        }
-
-        @Override
-        public Cookie getCookie(String cookieName) {
-            Map<String, io.undertow.server.handlers.Cookie> requestCookies = exchange.getRequestCookies();
-            if (requestCookies == null) return null;
-            io.undertow.server.handlers.Cookie cookie = requestCookies.get(cookieName);
-            if (cookie == null) return null;
-            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
-        }
-
-        @Override
-        public List<String> getHeaders(String name) {
-            return exchange.getRequestHeaders().get(name);
-        }
-
-        @Override
-        public String getMethod() {
-            return exchange.getRequestMethod().toString();
-        }
-
-
-
-        @Override
-        public String getHeader(String name) {
-            return exchange.getRequestHeaders().getFirst(name);
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            if (!exchange.isBlocking()) exchange.startBlocking();
-            return exchange.getInputStream();
-        }
-
-        @Override
-        public String getRemoteAddr() {
-            InetSocketAddress sourceAddress = exchange.getSourceAddress();
-            if (sourceAddress == null) {
-                return "";
-            }
-            InetAddress address = sourceAddress.getAddress();
-            if (address == null) {
-                // this is unresolved, so we just return the host name not exactly spec, but if the name should be
-                // resolved then a PeerNameResolvingHandler should be used and this is probably better than just
-                // returning null
-                return sourceAddress.getHostString();
-            }
-            return address.getHostAddress();
-        }
-    }
-
-    protected class ResponseFacade implements Response {
-        @Override
-        public void setStatus(int status) {
-            exchange.setResponseCode(status);
-        }
-
-        @Override
-        public void addHeader(String name, String value) {
-            exchange.getResponseHeaders().add(new HttpString(name), value);
-        }
-
-        @Override
-        public void setHeader(String name, String value) {
-            exchange.getResponseHeaders().put(new HttpString(name), value);
-        }
-
-        @Override
-        public void resetCookie(String name, String path) {
-            CookieImpl cookie = new CookieImpl(name, "");
-            cookie.setMaxAge(0);
-            cookie.setPath(path);
-            exchange.setResponseCookie(cookie);
-        }
-
-        @Override
-        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
-            CookieImpl cookie = new CookieImpl(name, value);
-            cookie.setPath(path);
-            cookie.setDomain(domain);
-            cookie.setMaxAge(maxAge);
-            cookie.setSecure(secure);
-            cookie.setHttpOnly(httpOnly);
-            exchange.setResponseCookie(cookie);
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            if (!exchange.isBlocking()) exchange.startBlocking();
-            return exchange.getOutputStream();
-        }
-
-        @Override
-        public void sendError(int code, String message) {
-            exchange.setResponseCode(code);
-            exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/html");
-            try {
-                exchange.getOutputStream().write(message.getBytes());
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-            exchange.endExchange();
-        }
-
-
-        @Override
-        public void end() {
-            exchange.endExchange();
-        }
-    }
-
-    public UndertowHttpFacade(HttpServerExchange exchange) {
-        this.exchange = exchange;
-    }
-
-    @Override
-    public Request getRequest() {
-        return requestFacade;
-    }
-
-    @Override
-    public Response getResponse() {
-        return responseFacade;
-    }
-
-    @Override
-    public KeycloakSecurityContext getSecurityContext() {
-        return exchange.getAttachment(KEYCLOAK_SECURITY_CONTEXT_KEY);
-    }
-
-    @Override
-    public X509Certificate[] getCertificateChain() {
-        X509Certificate[] chain = new X509Certificate[0];
-        try {
-            chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain();
-        } catch (Exception ignore) {
-
-        }
-        return chain;
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.handlers.CookieImpl;
+import io.undertow.util.AttachmentKey;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import javax.security.cert.X509Certificate;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UndertowHttpFacade implements HttpFacade {
+    public static final AttachmentKey<KeycloakSecurityContext> KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class);
+
+    protected HttpServerExchange exchange;
+    protected RequestFacade requestFacade = new RequestFacade();
+    protected ResponseFacade responseFacade = new ResponseFacade();
+
+    protected class RequestFacade implements Request {
+        @Override
+        public String getURI() {
+            KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(exchange.getRequestURI())
+                    .replaceQuery(exchange.getQueryString());
+            if (!exchange.isHostIncludedInRequestURI()) uriBuilder.scheme(exchange.getRequestScheme()).host(exchange.getHostAndPort());
+            return uriBuilder.build().toString();
+        }
+
+        @Override
+        public boolean isSecure() {
+            String protocol = exchange.getRequestScheme();
+            return protocol.equalsIgnoreCase("https");
+        }
+
+        @Override
+        public String getQueryParamValue(String param) {
+            Map<String,Deque<String>> queryParameters = exchange.getQueryParameters();
+            if (queryParameters == null) return null;
+            Deque<String> strings = queryParameters.get(param);
+            if (strings == null) return null;
+            return strings.getFirst();
+        }
+
+        @Override
+        public Cookie getCookie(String cookieName) {
+            Map<String, io.undertow.server.handlers.Cookie> requestCookies = exchange.getRequestCookies();
+            if (requestCookies == null) return null;
+            io.undertow.server.handlers.Cookie cookie = requestCookies.get(cookieName);
+            if (cookie == null) return null;
+            return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
+        }
+
+        @Override
+        public List<String> getHeaders(String name) {
+            return exchange.getRequestHeaders().get(name);
+        }
+
+        @Override
+        public String getMethod() {
+            return exchange.getRequestMethod().toString();
+        }
+
+
+
+        @Override
+        public String getHeader(String name) {
+            return exchange.getRequestHeaders().getFirst(name);
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            if (!exchange.isBlocking()) exchange.startBlocking();
+            return exchange.getInputStream();
+        }
+
+        @Override
+        public String getRemoteAddr() {
+            InetSocketAddress sourceAddress = exchange.getSourceAddress();
+            if (sourceAddress == null) {
+                return "";
+            }
+            InetAddress address = sourceAddress.getAddress();
+            if (address == null) {
+                // this is unresolved, so we just return the host name not exactly spec, but if the name should be
+                // resolved then a PeerNameResolvingHandler should be used and this is probably better than just
+                // returning null
+                return sourceAddress.getHostString();
+            }
+            return address.getHostAddress();
+        }
+    }
+
+    protected class ResponseFacade implements Response {
+        @Override
+        public void setStatus(int status) {
+            exchange.setResponseCode(status);
+        }
+
+        @Override
+        public void addHeader(String name, String value) {
+            exchange.getResponseHeaders().add(new HttpString(name), value);
+        }
+
+        @Override
+        public void setHeader(String name, String value) {
+            exchange.getResponseHeaders().put(new HttpString(name), value);
+        }
+
+        @Override
+        public void resetCookie(String name, String path) {
+            CookieImpl cookie = new CookieImpl(name, "");
+            cookie.setMaxAge(0);
+            cookie.setPath(path);
+            exchange.setResponseCookie(cookie);
+        }
+
+        @Override
+        public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
+            CookieImpl cookie = new CookieImpl(name, value);
+            cookie.setPath(path);
+            cookie.setDomain(domain);
+            cookie.setMaxAge(maxAge);
+            cookie.setSecure(secure);
+            cookie.setHttpOnly(httpOnly);
+            exchange.setResponseCookie(cookie);
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            if (!exchange.isBlocking()) exchange.startBlocking();
+            return exchange.getOutputStream();
+        }
+
+        @Override
+        public void sendError(int code, String message) {
+            exchange.setResponseCode(code);
+            exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/html");
+            try {
+                exchange.getOutputStream().write(message.getBytes());
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            exchange.endExchange();
+        }
+
+
+        @Override
+        public void end() {
+            exchange.endExchange();
+        }
+    }
+
+    public UndertowHttpFacade(HttpServerExchange exchange) {
+        this.exchange = exchange;
+    }
+
+    @Override
+    public Request getRequest() {
+        return requestFacade;
+    }
+
+    @Override
+    public Response getResponse() {
+        return responseFacade;
+    }
+
+    @Override
+    public KeycloakSecurityContext getSecurityContext() {
+        return exchange.getAttachment(KEYCLOAK_SECURITY_CONTEXT_KEY);
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain() {
+        X509Certificate[] chain = new X509Certificate[0];
+        try {
+            chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain();
+        } catch (Exception ignore) {
+
+        }
+        return chain;
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java
index 0a70c67..a68f39f 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java
@@ -1,56 +1,56 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.session.SessionManager;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.adapters.PreAuthActionsHandler;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UndertowPreAuthActionsHandler implements HttpHandler {
-
-    private static final Logger log = Logger.getLogger(UndertowPreAuthActionsHandler.class);
-    protected HttpHandler next;
-    protected SessionManager sessionManager;
-    protected UndertowUserSessionManagement userSessionManagement;
-    protected AdapterDeploymentContext deploymentContext;
-
-    public UndertowPreAuthActionsHandler(AdapterDeploymentContext deploymentContext,
-                                            UndertowUserSessionManagement userSessionManagement,
-                                            SessionManager sessionManager,
-                                            HttpHandler next) {
-        this.next = next;
-        this.deploymentContext = deploymentContext;
-        this.sessionManager = sessionManager;
-        this.userSessionManagement = userSessionManagement;
-    }
-
-    @Override
-    public void handleRequest(HttpServerExchange exchange) throws Exception {
-        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
-        SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, sessionManager);
-        PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade);
-        if (handler.handleRequest()) return;
-        next.handleRequest(exchange);
-    }
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.SessionManager;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.PreAuthActionsHandler;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UndertowPreAuthActionsHandler implements HttpHandler {
+
+    private static final Logger log = Logger.getLogger(UndertowPreAuthActionsHandler.class);
+    protected HttpHandler next;
+    protected SessionManager sessionManager;
+    protected UndertowUserSessionManagement userSessionManagement;
+    protected AdapterDeploymentContext deploymentContext;
+
+    public UndertowPreAuthActionsHandler(AdapterDeploymentContext deploymentContext,
+                                            UndertowUserSessionManagement userSessionManagement,
+                                            SessionManager sessionManager,
+                                            HttpHandler next) {
+        this.next = next;
+        this.deploymentContext = deploymentContext;
+        this.sessionManager = sessionManager;
+        this.userSessionManagement = userSessionManagement;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+        SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, sessionManager);
+        PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade);
+        if (handler.handleRequest()) return;
+        next.handleRequest(exchange);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
index 91fe9e8..d3bccd4 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowRequestAuthenticator.java
@@ -1,27 +1,27 @@
-package org.keycloak.adapters.undertow;
-
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpServerExchange;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.adapters.AdapterTokenStore;
-import org.keycloak.adapters.HttpFacade;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.adapters.undertow.AbstractUndertowRequestAuthenticator;
-import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UndertowRequestAuthenticator extends AbstractUndertowRequestAuthenticator {
-    public UndertowRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
-                                        SecurityContext securityContext, HttpServerExchange exchange, AdapterTokenStore tokenStore) {
-        super(facade, deployment, sslRedirectPort, securityContext, exchange, tokenStore);
-    }
-
-    @Override
-    protected KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
-        return new KeycloakUndertowAccount(principal);
-    }
-}
+package org.keycloak.adapters.undertow;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpServerExchange;
+import org.keycloak.KeycloakPrincipal;
+import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
+import org.keycloak.adapters.undertow.AbstractUndertowRequestAuthenticator;
+import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UndertowRequestAuthenticator extends AbstractUndertowRequestAuthenticator {
+    public UndertowRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
+                                        SecurityContext securityContext, HttpServerExchange exchange, AdapterTokenStore tokenStore) {
+        super(facade, deployment, sslRedirectPort, securityContext, exchange, tokenStore);
+    }
+
+    @Override
+    protected KeycloakUndertowAccount createAccount(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal) {
+        return new KeycloakUndertowAccount(principal);
+    }
+}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
index 6165d76..0b9a9a2 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
@@ -1,130 +1,130 @@
-/*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.adapters.undertow;
-
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.session.Session;
-import io.undertow.server.session.SessionConfig;
-import io.undertow.server.session.SessionListener;
-import io.undertow.server.session.SessionManager;
-import org.jboss.logging.Logger;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Manages relationship to users and sessions so that forced admin logout can be implemented
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UndertowUserSessionManagement implements SessionListener {
-    private static final Logger log = Logger.getLogger(UndertowUserSessionManagement.class);
-    protected volatile boolean registered;
-
-    public void login(SessionManager manager) {
-        if (!registered) {
-            manager.registerSessionListener(this);
-            registered = true;
-        }
-    }
-
-    public void logoutAll(SessionManager manager) {
-        Set<String> allSessions = manager.getAllSessions();
-        for (String sessionId : allSessions) logoutSession(manager, sessionId);
-    }
-
-    public void logoutHttpSessions(SessionManager manager, List<String> sessionIds) {
-        log.debug("logoutHttpSessions: " + sessionIds);
-
-        for (String sessionId : sessionIds) {
-            logoutSession(manager, sessionId);
-        }
-    }
-
-    protected void logoutSession(SessionManager manager, String httpSessionId) {
-        log.debug("logoutHttpSession: " + httpSessionId);
-        Session session = getSessionById(manager, httpSessionId);
-        try {
-            if (session != null) session.invalidate(null);
-        } catch (Exception e) {
-            log.warnf("Session %s not present or already invalidated.", httpSessionId);
-        }
-    }
-
-    protected Session getSessionById(SessionManager manager, final String sessionId) {
-        // TODO: Workaround for WFLY-3345. Remove this once we move to wildfly 8.2
-        if (manager.getClass().getName().equals("org.wildfly.clustering.web.undertow.session.DistributableSessionManager")) {
-            return manager.getSession(null, new SessionConfig() {
-
-                @Override
-                public void setSessionId(HttpServerExchange exchange, String sessionId) {
-                }
-
-                @Override
-                public void clearSession(HttpServerExchange exchange, String sessionId) {
-                }
-
-                @Override
-                public String findSessionId(HttpServerExchange exchange) {
-                    return sessionId;
-                }
-
-                @Override
-                public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
-                    return null;
-                }
-
-                @Override
-                public String rewriteUrl(String originalUrl, String sessionId) {
-                    return null;
-                }
-
-            });
-
-        } else {
-            return manager.getSession(sessionId);
-        }
-    }
-
-
-    @Override
-    public void sessionCreated(Session session, HttpServerExchange exchange) {
-    }
-
-    @Override
-    public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
-    }
-
-
-    @Override
-    public void sessionIdChanged(Session session, String oldSessionId) {
-    }
-
-    @Override
-    public void attributeAdded(Session session, String name, Object value) {
-    }
-
-    @Override
-    public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) {
-    }
-
-    @Override
-    public void attributeRemoved(Session session, String name, Object oldValue) {
-    }
-
-}
+/*
+ * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.adapters.undertow;
+
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.session.Session;
+import io.undertow.server.session.SessionConfig;
+import io.undertow.server.session.SessionListener;
+import io.undertow.server.session.SessionManager;
+import org.jboss.logging.Logger;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Manages relationship to users and sessions so that forced admin logout can be implemented
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UndertowUserSessionManagement implements SessionListener {
+    private static final Logger log = Logger.getLogger(UndertowUserSessionManagement.class);
+    protected volatile boolean registered;
+
+    public void login(SessionManager manager) {
+        if (!registered) {
+            manager.registerSessionListener(this);
+            registered = true;
+        }
+    }
+
+    public void logoutAll(SessionManager manager) {
+        Set<String> allSessions = manager.getAllSessions();
+        for (String sessionId : allSessions) logoutSession(manager, sessionId);
+    }
+
+    public void logoutHttpSessions(SessionManager manager, List<String> sessionIds) {
+        log.debug("logoutHttpSessions: " + sessionIds);
+
+        for (String sessionId : sessionIds) {
+            logoutSession(manager, sessionId);
+        }
+    }
+
+    protected void logoutSession(SessionManager manager, String httpSessionId) {
+        log.debug("logoutHttpSession: " + httpSessionId);
+        Session session = getSessionById(manager, httpSessionId);
+        try {
+            if (session != null) session.invalidate(null);
+        } catch (Exception e) {
+            log.warnf("Session %s not present or already invalidated.", httpSessionId);
+        }
+    }
+
+    protected Session getSessionById(SessionManager manager, final String sessionId) {
+        // TODO: Workaround for WFLY-3345. Remove this once we move to wildfly 8.2
+        if (manager.getClass().getName().equals("org.wildfly.clustering.web.undertow.session.DistributableSessionManager")) {
+            return manager.getSession(null, new SessionConfig() {
+
+                @Override
+                public void setSessionId(HttpServerExchange exchange, String sessionId) {
+                }
+
+                @Override
+                public void clearSession(HttpServerExchange exchange, String sessionId) {
+                }
+
+                @Override
+                public String findSessionId(HttpServerExchange exchange) {
+                    return sessionId;
+                }
+
+                @Override
+                public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
+                    return null;
+                }
+
+                @Override
+                public String rewriteUrl(String originalUrl, String sessionId) {
+                    return null;
+                }
+
+            });
+
+        } else {
+            return manager.getSession(sessionId);
+        }
+    }
+
+
+    @Override
+    public void sessionCreated(Session session, HttpServerExchange exchange) {
+    }
+
+    @Override
+    public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
+    }
+
+
+    @Override
+    public void sessionIdChanged(Session session, String oldSessionId) {
+    }
+
+    @Override
+    public void attributeAdded(Session session, String name, Object value) {
+    }
+
+    @Override
+    public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) {
+    }
+
+    @Override
+    public void attributeRemoved(Session session, String name, Object oldValue) {
+    }
+
+}
diff --git a/misc/logo/logo-big-background.svg b/misc/logo/logo-big-background.svg
index 551ce43..ab5c367 100644
--- a/misc/logo/logo-big-background.svg
+++ b/misc/logo/logo-big-background.svg
@@ -1,241 +1,241 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="431.217px" height="183.782px" viewBox="0 0 431.217 183.782" enable-background="new 0 0 431.217 183.782"
-	 xml:space="preserve">
-<rect fill="#04578B" width="431.217" height="183.782"/>
-<defs>
-	<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="165.717" height="183.782">
-		<feColorMatrix  type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
-	</filter>
-</defs>
-<mask maskUnits="userSpaceOnUse" x="0" y="0" width="165.717" height="183.782" id="SVGID_1_">
-	<g filter="url(#Adobe_OpacityMaskFilter)">
-		
-			<radialGradient id="SVGID_2_" cx="228.8584" cy="-63.1089" r="82.3594" gradientTransform="matrix(1 0 0 -1 -146 28.7822)" gradientUnits="userSpaceOnUse">
-			<stop  offset="0" style="stop-color:#FFFFFF"/>
-			<stop  offset="0.0433" style="stop-color:#ECECEC"/>
-			<stop  offset="0.1971" style="stop-color:#AFAFAF"/>
-			<stop  offset="0.3497" style="stop-color:#797979"/>
-			<stop  offset="0.4973" style="stop-color:#4E4E4E"/>
-			<stop  offset="0.639" style="stop-color:#2C2C2C"/>
-			<stop  offset="0.7732" style="stop-color:#141414"/>
-			<stop  offset="0.8968" style="stop-color:#050505"/>
-			<stop  offset="1" style="stop-color:#000000"/>
-		</radialGradient>
-		<rect fill="url(#SVGID_2_)" width="165.717" height="183.782"/>
-	</g>
-</mask>
-<rect mask="url(#SVGID_1_)" fill="#97C8DB" width="165.717" height="183.782"/>
-<g>
-	<g>
-		<g>
-			
-				<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="321.4775" y1="-49.4629" x2="321.4775" y2="-100.345" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_3_)" d="M181.507,97.659h-11.599c0.303,2.346,1.01,3.92,2.117,4.723c1.107,0.806,2.943,1.207,5.506,1.207
-				c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.606-8.015,2.41-14.01,2.41c-6.038,0-10.339-1.304-12.901-3.908
-				c-2.563-2.607-3.845-6.908-3.845-12.902c0-6.299,1.248-10.708,3.746-13.229c2.498-2.519,6.701-3.779,12.609-3.779
-				c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.745
-				C187.426,96.909,184.938,97.659,181.507,97.659z M169.713,91.858h9.122c1.173,0,1.966-0.282,2.378-0.847
-				c0.413-0.564,0.619-1.391,0.619-2.477c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
-				c-2.477,0-4.171,0.489-5.083,1.466C170.364,86.939,169.843,88.904,169.713,91.858z"/>
-			
-				<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="355.1025" y1="-49.4619" x2="355.1025" y2="-100.3444" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_4_)" d="M226.924,78.37l-11.402,32.582c-0.609,1.735-1.359,3.344-2.248,4.82
-				c-0.892,1.477-2.031,2.898-3.422,4.27c-1.391,1.367-3.117,2.377-5.18,3.028c-2.064,0.652-4.355,0.825-6.875,0.521l-0.781-5.668
-				c2.605-0.695,4.647-1.598,6.125-2.705c1.477-1.106,2.627-2.596,3.453-4.463l0.131-0.262H204.9c-1.607,0-2.649-0.781-3.128-2.346
-				l-10.49-29.778h10.295l5.995,20.786c0.391,1.521,0.717,3.129,0.978,4.822h0.847c0.13-0.521,0.347-1.336,0.651-2.443
-				c0.304-1.107,0.521-1.9,0.652-2.379l5.93-20.786L226.924,78.37L226.924,78.37z"/>
-			
-				<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="386.1865" y1="-49.4619" x2="386.1865" y2="-100.3455" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_5_)" d="M253.61,102.872l0.848,6.256c-3.303,1.433-7.451,2.148-12.445,2.148
-				c-5.908,0-10.068-1.271-12.479-3.812c-2.412-2.541-3.616-6.896-3.616-13.063c0-6.213,1.216-10.59,3.648-13.131
-				c2.434-2.541,6.625-3.812,12.576-3.812c4.864,0,8.817,0.674,11.858,2.021l-1.042,5.994c-4.691-0.086-7.755-0.131-9.188-0.131
-				c-2.955,0-4.984,0.631-6.092,1.891c-1.109,1.26-1.662,3.648-1.662,7.168c0,3.519,0.555,5.908,1.662,7.167
-				c1.106,1.262,3.137,1.891,6.092,1.891C247.55,103.458,250.83,103.26,253.61,102.872z"/>
-			
-				<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="436.9375" y1="-49.4629" x2="436.9375" y2="-100.3452" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_6_)" d="M290.972,77.458c5.995,0,10.24,1.293,12.739,3.877c2.497,2.585,3.746,6.962,3.746,13.13
-				c0,6.168-1.249,10.522-3.746,13.063c-2.499,2.542-6.744,3.812-12.739,3.812c-6.039,0-10.308-1.271-12.805-3.812
-				c-2.499-2.541-3.747-6.896-3.747-13.063c0-6.211,1.248-10.599,3.747-13.163C280.664,78.74,284.933,77.458,290.972,77.458z
-				 M290.972,84.691c-2.562,0-4.279,0.65-5.146,1.954c-0.87,1.304-1.305,3.909-1.305,7.818c0,3.824,0.435,6.387,1.305,7.689
-				c0.867,1.303,2.584,1.955,5.146,1.955c2.477,0,4.159-0.652,5.051-1.955c0.89-1.304,1.336-3.865,1.336-7.689
-				c0-3.864-0.437-6.46-1.305-7.787C295.185,85.353,293.49,84.691,290.972,84.691z"/>
-			
-				<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="470.8486" y1="-49.4629" x2="470.8486" y2="-100.345" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_7_)" d="M311.851,85.538l-0.912-6.517c5.776-1.043,11.358-1.563,16.746-1.563
-				c4.344,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154v21.243h-7.625l-0.978-4.888
-				c-3.217,3.778-7.168,5.669-11.858,5.669c-3.087,0-5.605-0.814-7.56-2.443c-1.955-1.629-2.934-3.897-2.934-6.81v-3.258
-				c0-2.562,0.869-4.562,2.607-5.994c1.735-1.434,4.147-2.15,7.231-2.15h11.47v-1.434c-0.046-1.65-0.425-2.759-1.142-3.324
-				c-0.717-0.563-2.097-0.847-4.14-0.847C321.84,85.016,317.324,85.191,311.851,85.538z M318.888,99.482v1.238
-				c0,2.215,1.26,3.321,3.778,3.321c2.606,0,5.278-1.041,8.017-3.127v-4.496h-8.666C319.931,96.461,318.888,97.484,318.888,99.482z"
-				/>
-			
-				<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="291.9043" y1="-49.4624" x2="291.9043" y2="-100.3454" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_8_)" d="M152.485,96.159c-0.913-1.562-1.912-2.714-2.997-3.453v-0.131c1.303-0.868,2.302-1.89,2.997-3.062
-				l8.341-11.143H150.01l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865V64.881h-2.992l-6.651,9.482v36.13h9.644v-10.1
-				c0-1.26-0.152-2.867-0.455-4.822h3.062l8.992,14.922h10.816L152.485,96.159z"/>
-			
-				<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="411.2822" y1="-49.4624" x2="411.2822" y2="-100.3453" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_9_)" d="M272.646,103.26h-2.606c-2.435,0-3.647-1.086-3.647-3.258V64.881h-3.015l-6.565,9.36v28.171
-				c0,2.824,0.826,5.008,2.477,6.549c1.65,1.543,3.91,2.313,6.777,2.313c3.475,0,6.037-0.435,7.688-1.304L272.646,103.26z"/>
-			
-				<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="506.0684" y1="-49.4624" x2="506.0684" y2="-100.3454" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
-				<stop  offset="0" style="stop-color:#FFFFFF"/>
-				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
-				<stop  offset="1" style="stop-color:#E9E8E9"/>
-			</linearGradient>
-			<path fill="url(#SVGID_10_)" d="M366.649,96.159c-0.912-1.562-1.912-2.714-2.998-3.453v-0.131
-				c1.304-0.868,2.304-1.89,2.998-3.062l8.341-11.143h-10.816l-7.948,11.208h-2.998c0.303-1.781,0.457-3.736,0.457-5.865V64.881
-				h-2.992l-6.652,9.484v36.127h9.645v-10.1c0-1.26-0.154-2.867-0.457-4.822h3.062l8.992,14.922h10.816L366.649,96.159z"/>
-		</g>
-	</g>
-	<g>
-		
-			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="264.1172" y1="-1546.0913" x2="326.7803" y2="-1546.0913" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#FEFEFE"/>
-			<stop  offset="0.1452" style="stop-color:#F4F5F4"/>
-			<stop  offset="0.6844" style="stop-color:#DADCDB"/>
-			<stop  offset="1" style="stop-color:#CFD1D1"/>
-		</linearGradient>
-		<path fill="url(#SVGID_11_)" d="M120.78,83.181c-7.205,5-14.688,3.683-23.183-3.357c-4.897-4.059-11.15-2.771-15.411-1.454
-			c-2.647,0.819-6.324,0.744-9.518,0.075c-13.979-2.93-10.93,6.038-8.339,14.015c4.757,14.641-3.236,18.031-5.983,12.815
-			c-1.766,6.615,7.138,8.572,10.937,7.701c6.007-1.377,14.052-2.154,19.044-0.627c9.544,2.916,13.125,0.512,11.542-2.57
-			c-0.521-1.012-0.229-2.446,0.583-3.127c2.834-2.373,5.295-0.373,8.007-1.946c2.107-1.226,2.077-3.927-1.19-5.463
-			c-1.73-0.812-1.648-2.882,0.185-3.841c3.729-1.95,8.75-1.034,10-5.137C117.899,88.794,119.151,85.105,120.78,83.181z"/>
-		
-			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="684.1572" y1="-833.1753" x2="675.8836" y2="-833.1753" gradientTransform="matrix(1 0 0 -1 -594 -737.2178)">
-			<stop  offset="0" style="stop-color:#E6E6E6"/>
-			<stop  offset="1" style="stop-color:#B3B4B4"/>
-		</linearGradient>
-		<path fill="url(#SVGID_12_)" d="M84.828,81.388c0,4.983,0.74,22.799,4.537,30.403l-8.733-0.192V80.126L84.828,81.388z"/>
-		
-			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="290.9736" y1="-1552.6763" x2="297.9739" y2="-1533.1755" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#F6F6F6"/>
-			<stop  offset="1" style="stop-color:#B3B4B4"/>
-		</linearGradient>
-		<path fill="url(#SVGID_13_)" d="M65.2,93.14c-2.762-7.459-6.509-16.625,7.47-13.695c3.192,0.669,6.869,0.744,9.518-0.075
-			c4.261-1.317,9.973-2.444,14.515,1.521c8.875,7.748,16.875,8.293,24.079,3.293c-1.63,1.924-3.105,5.562-3.329,7.082
-			c-0.189,1.293-1.135,1.873-2.383,2.379c-18.519,7.52-15.394-5.307-21.352-9.479c-3.158-2.214-7.733-2.09-11.247-0.812
-			c-3.171,1.152-6.438,0.863-9.833-0.396C66.971,80.849,63.163,81.96,65.2,93.14z"/>
-		
-			<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="82.471" y1="111.904" x2="82.471" y2="80.681"/>
-		<g opacity="0.75">
-			<path fill="#FFFFFF" d="M89.527,79.08c2.72,0,4.941,0.747,6.795,2.284c5.541,4.592,10.631,6.823,15.558,6.823
-				c1.473,0,2.934-0.209,4.373-0.615c-0.317,0.854-0.56,1.602-0.714,2.111c-0.433,1.414-1.599,1.811-4.357,2.436
-				c-1.463,0.333-3.121,0.709-4.656,1.514c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.821,2.396,3.514
-				c1.152,0.541,1.478,1.135,1.486,1.373c0.013,0.26-0.343,0.486-0.449,0.551c-0.598,0.348-1.182,0.412-2.052,0.412
-				c-0.159,0-0.32-0.002-0.481-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
-				c-1.545,1.293-2.02,3.742-1.078,5.571c0.137,0.269,0.141,0.406,0.148,0.408c-0.093,0.127-0.771,0.563-2.586,0.563
-				c-1.775,0-4.106-0.426-6.74-1.229c-2.006-0.613-4.513-0.924-7.451-0.924c-3.827,0-8.429,0.553-12.624,1.516
-				c-0.412,0.094-0.935,0.145-1.509,0.145c-1.875,0-4.188-0.543-5.674-1.596c1.675-0.01,3.265-0.885,4.366-2.402
-				c1.341-1.846,3.15-6.288,0.213-15.329l-0.081-0.25c-1.277-3.937-2.87-8.832-1.541-10.664c0.509-0.698,1.637-1.053,3.354-1.053
-				c1.188,0,2.632,0.178,4.295,0.525c1.76,0.369,3.618,0.562,5.375,0.562c1.944,0,3.676-0.23,5.144-0.686
-				C84.444,79.765,86.957,79.08,89.527,79.08 M89.527,77.08c-2.663,0-5.242,0.641-7.34,1.29c-1.324,0.41-2.904,0.597-4.553,0.597
-				c-1.649,0-3.367-0.188-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.475,0-5.881,7.664-3.635,14.582
-				c3.376,10.396,0.326,15.117-2.708,15.117c-1.241,0-2.479-0.789-3.276-2.301c-1.506,5.643,4.751,7.895,8.98,7.895
-				c0.729,0,1.396-0.065,1.955-0.192c3.685-0.845,8.135-1.463,12.178-1.463c2.549,0,4.936,0.245,6.865,0.836
-				c3.037,0.933,5.473,1.317,7.326,1.317c3.976,0,5.295-1.785,4.217-3.889c-0.521-1.012-0.229-2.445,0.582-3.125
-				c1.375-1.152,2.663-1.275,3.936-1.275c0.34,0,0.679,0.011,1.018,0.011c1.005,0,2.012-0.076,3.056-0.683
-				c2.107-1.227,2.077-3.928-1.19-5.463c-1.73-0.813-1.648-2.881,0.185-3.84c3.729-1.953,8.75-1.037,10-5.139
-				c0.447-1.473,1.699-5.162,3.329-7.084c-2.905,2.018-5.856,3.006-8.901,3.006c-4.504,0-9.211-2.164-14.28-6.364
-				C95.111,77.763,92.275,77.08,89.527,77.08L89.527,77.08z M120.78,83.181h0.006H120.78z"/>
-		</g>
-		<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-			M120.78,83.181c-7.205,5-14.688,3.683-23.183-3.357c-4.897-4.059-11.15-2.771-15.411-1.454c-2.647,0.819-6.324,0.744-9.518,0.075
-			c-13.979-2.93-10.93,6.038-8.339,14.015c4.757,14.641-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
-			c6.007-1.377,14.052-2.154,19.044-0.627c9.544,2.916,13.125,0.512,11.542-2.57c-0.521-1.012-0.229-2.446,0.583-3.127
-			c2.834-2.373,5.295-0.373,8.007-1.946c2.107-1.226,2.077-3.927-1.19-5.463c-1.73-0.812-1.648-2.882,0.185-3.841
-			c3.729-1.95,8.75-1.034,10-5.137C117.899,88.794,119.151,85.105,120.78,83.181z"/>
-		<path fill="#034672" d="M65.2,92.14c-2.762-7.459-6.509-16.625,7.47-13.695c3.192,0.669,6.869,0.744,9.518-0.075
-			c4.261-1.317,9.973-2.444,14.515,1.521c8.875,7.748,16.875,8.293,24.079,3.293c-1.63,1.924-3.105,5.562-3.329,7.082
-			c-0.189,1.293-1.116,1.916-2.383,2.379c-13.119,4.795-14.124-5.484-20.082-9.664c-3.157-2.215-9.003-1.908-12.517-0.631
-			c-3.171,1.153-6.438,0.865-9.833-0.396C66.971,79.849,63.163,80.96,65.2,92.14z"/>
-		
-			<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="273.9326" y1="-1540.3081" x2="304.77" y2="-1532.6405" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#B8D7E8"/>
-			<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-			<stop  offset="0.6937" style="stop-color:#DAEBF8"/>
-			<stop  offset="1" style="stop-color:#E0EEF9"/>
-		</linearGradient>
-		<path fill="url(#SVGID_14_)" d="M87.452,57.497c-1.053-0.594-4.274-2.612-5.079-3.063c-0.807-0.453-2.724-1.881-4.819-1.881
-			v69.289l4.819-4.936V82.746c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.16
-			c0-2.14,0.778-2.969,1.762-3.469c2.883-1.462,4.479-3.598,4.479-6.439c0-0.956,0-3.213,0-4.521
-			C91.176,59.534,88.257,57.951,87.452,57.497z"/>
-		
-			<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="276.8936" y1="-1516.1357" x2="285.5189" y2="-1558.3877" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#F1F9FE"/>
-			<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-			<stop  offset="1" style="stop-color:#E4F3FC"/>
-		</linearGradient>
-		<path fill="url(#SVGID_15_)" d="M77.554,52.552c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.451-4.026,2.471-5.079,3.063
-			c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.31,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44
-			c0.982,0.498,1.762,1.328,1.762,3.467c0,0.943,0.352,1.162,0.918,1.162h0.68c0.625,0,0.965,0.234,0.965,1.256
-			c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l0.862-0.883L77.554,52.552L77.554,52.552z"/>
-		<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M77.264,52.552
-			c1.908,0.938,3.431,1.965,4.236,2.418c0.805,0.453,4.026,2.472,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34
-			c0,1.309,0,2.807,0,3.762c0,2.844-1.597,4.979-4.479,6.44c-0.982,0.499-1.762,1.431-1.762,3.569v1.238"/>
-		<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M87.452,57.497
-			c-1.053-0.594-4.274-2.612-5.079-3.063c-0.807-0.453-2.724-1.881-4.819-1.881c-2.095,0-4.014,1.428-4.819,1.881
-			c-0.805,0.451-4.026,2.471-5.079,3.063c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.31,0,3.564,0,4.521
-			c0,2.843,1.597,4.979,4.479,6.44c0.982,0.498,1.762,1.328,1.762,3.467c0,0.943,0.352,1.162,0.918,1.162h0.68
-			c0.625,0,0.965,0.234,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.683-5.82V82.745c0,0,0-1.5,0-2.062
-			c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.219,0.918-1.162c0-2.139,0.778-2.969,1.762-3.467
-			c2.883-1.463,4.479-3.599,4.479-6.44c0-0.956,0-3.212,0-4.521C91.176,59.534,88.257,57.951,87.452,57.497z"/>
-		<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M92.373,82.745"/>
-		
-			<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="283.5557" y1="-1511.2954" x2="283.5557" y2="-1521.4633" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#01649B"/>
-			<stop  offset="0.2355" style="stop-color:#03588B"/>
-			<stop  offset="0.507" style="stop-color:#004E7C"/>
-			<stop  offset="0.7167" style="stop-color:#004873"/>
-			<stop  offset="1" style="stop-color:#00446E"/>
-		</linearGradient>
-		<polygon fill="url(#SVGID_16_)" points="77.556,62.472 68.504,60.448 67.504,64.187 77.556,69.245 87.607,64.187 86.607,60.448 		
-			"/>
-		<polyline opacity="0.2" fill="#010202" enable-background="new    " points="77.556,69.245 87.607,64.187 86.607,60.448 
-			77.556,62.472 		"/>
-		<path fill="#034672" d="M72.638,81.953c3.396,1.262,6.662,1.55,9.833,0.396l-0.283-2.224c-2.647,0.82-6.324,0.744-9.518,0.075
-			L72.638,81.953z"/>
-		<path fill="#034672" d="M77.282,81.599c-0.402,2.758,1.896,4.707,1.896,7.619C83.027,84.884,78.105,83.421,77.282,81.599z"/>
-		<path fill="#034672" d="M77.235,81.787c-0.118,3.207-0.401,5.581-1.74,7.246C73.075,84.296,76.182,82.714,77.235,81.787z"/>
-		<circle fill="#034672" cx="77.264" cy="81.765" r="1.594"/>
-		
-			<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="294.3252" y1="-1563.0669" x2="294.3252" y2="-1563.0669" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
-			<stop  offset="0" style="stop-color:#F6F6F6"/>
-			<stop  offset="0.5386" style="stop-color:#E4E4E3"/>
-			<stop  offset="1" style="stop-color:#DADADA"/>
-		</linearGradient>
-		<path fill="url(#SVGID_17_)" d="M88.325,112.349"/>
-	</g>
-</g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="431.217px" height="183.782px" viewBox="0 0 431.217 183.782" enable-background="new 0 0 431.217 183.782"
+	 xml:space="preserve">
+<rect fill="#04578B" width="431.217" height="183.782"/>
+<defs>
+	<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="165.717" height="183.782">
+		<feColorMatrix  type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
+	</filter>
+</defs>
+<mask maskUnits="userSpaceOnUse" x="0" y="0" width="165.717" height="183.782" id="SVGID_1_">
+	<g filter="url(#Adobe_OpacityMaskFilter)">
+		
+			<radialGradient id="SVGID_2_" cx="228.8584" cy="-63.1089" r="82.3594" gradientTransform="matrix(1 0 0 -1 -146 28.7822)" gradientUnits="userSpaceOnUse">
+			<stop  offset="0" style="stop-color:#FFFFFF"/>
+			<stop  offset="0.0433" style="stop-color:#ECECEC"/>
+			<stop  offset="0.1971" style="stop-color:#AFAFAF"/>
+			<stop  offset="0.3497" style="stop-color:#797979"/>
+			<stop  offset="0.4973" style="stop-color:#4E4E4E"/>
+			<stop  offset="0.639" style="stop-color:#2C2C2C"/>
+			<stop  offset="0.7732" style="stop-color:#141414"/>
+			<stop  offset="0.8968" style="stop-color:#050505"/>
+			<stop  offset="1" style="stop-color:#000000"/>
+		</radialGradient>
+		<rect fill="url(#SVGID_2_)" width="165.717" height="183.782"/>
+	</g>
+</mask>
+<rect mask="url(#SVGID_1_)" fill="#97C8DB" width="165.717" height="183.782"/>
+<g>
+	<g>
+		<g>
+			
+				<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="321.4775" y1="-49.4629" x2="321.4775" y2="-100.345" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_3_)" d="M181.507,97.659h-11.599c0.303,2.346,1.01,3.92,2.117,4.723c1.107,0.806,2.943,1.207,5.506,1.207
+				c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.606-8.015,2.41-14.01,2.41c-6.038,0-10.339-1.304-12.901-3.908
+				c-2.563-2.607-3.845-6.908-3.845-12.902c0-6.299,1.248-10.708,3.746-13.229c2.498-2.519,6.701-3.779,12.609-3.779
+				c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.745
+				C187.426,96.909,184.938,97.659,181.507,97.659z M169.713,91.858h9.122c1.173,0,1.966-0.282,2.378-0.847
+				c0.413-0.564,0.619-1.391,0.619-2.477c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
+				c-2.477,0-4.171,0.489-5.083,1.466C170.364,86.939,169.843,88.904,169.713,91.858z"/>
+			
+				<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="355.1025" y1="-49.4619" x2="355.1025" y2="-100.3444" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_4_)" d="M226.924,78.37l-11.402,32.582c-0.609,1.735-1.359,3.344-2.248,4.82
+				c-0.892,1.477-2.031,2.898-3.422,4.27c-1.391,1.367-3.117,2.377-5.18,3.028c-2.064,0.652-4.355,0.825-6.875,0.521l-0.781-5.668
+				c2.605-0.695,4.647-1.598,6.125-2.705c1.477-1.106,2.627-2.596,3.453-4.463l0.131-0.262H204.9c-1.607,0-2.649-0.781-3.128-2.346
+				l-10.49-29.778h10.295l5.995,20.786c0.391,1.521,0.717,3.129,0.978,4.822h0.847c0.13-0.521,0.347-1.336,0.651-2.443
+				c0.304-1.107,0.521-1.9,0.652-2.379l5.93-20.786L226.924,78.37L226.924,78.37z"/>
+			
+				<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="386.1865" y1="-49.4619" x2="386.1865" y2="-100.3455" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_5_)" d="M253.61,102.872l0.848,6.256c-3.303,1.433-7.451,2.148-12.445,2.148
+				c-5.908,0-10.068-1.271-12.479-3.812c-2.412-2.541-3.616-6.896-3.616-13.063c0-6.213,1.216-10.59,3.648-13.131
+				c2.434-2.541,6.625-3.812,12.576-3.812c4.864,0,8.817,0.674,11.858,2.021l-1.042,5.994c-4.691-0.086-7.755-0.131-9.188-0.131
+				c-2.955,0-4.984,0.631-6.092,1.891c-1.109,1.26-1.662,3.648-1.662,7.168c0,3.519,0.555,5.908,1.662,7.167
+				c1.106,1.262,3.137,1.891,6.092,1.891C247.55,103.458,250.83,103.26,253.61,102.872z"/>
+			
+				<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="436.9375" y1="-49.4629" x2="436.9375" y2="-100.3452" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_6_)" d="M290.972,77.458c5.995,0,10.24,1.293,12.739,3.877c2.497,2.585,3.746,6.962,3.746,13.13
+				c0,6.168-1.249,10.522-3.746,13.063c-2.499,2.542-6.744,3.812-12.739,3.812c-6.039,0-10.308-1.271-12.805-3.812
+				c-2.499-2.541-3.747-6.896-3.747-13.063c0-6.211,1.248-10.599,3.747-13.163C280.664,78.74,284.933,77.458,290.972,77.458z
+				 M290.972,84.691c-2.562,0-4.279,0.65-5.146,1.954c-0.87,1.304-1.305,3.909-1.305,7.818c0,3.824,0.435,6.387,1.305,7.689
+				c0.867,1.303,2.584,1.955,5.146,1.955c2.477,0,4.159-0.652,5.051-1.955c0.89-1.304,1.336-3.865,1.336-7.689
+				c0-3.864-0.437-6.46-1.305-7.787C295.185,85.353,293.49,84.691,290.972,84.691z"/>
+			
+				<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="470.8486" y1="-49.4629" x2="470.8486" y2="-100.345" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_7_)" d="M311.851,85.538l-0.912-6.517c5.776-1.043,11.358-1.563,16.746-1.563
+				c4.344,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154v21.243h-7.625l-0.978-4.888
+				c-3.217,3.778-7.168,5.669-11.858,5.669c-3.087,0-5.605-0.814-7.56-2.443c-1.955-1.629-2.934-3.897-2.934-6.81v-3.258
+				c0-2.562,0.869-4.562,2.607-5.994c1.735-1.434,4.147-2.15,7.231-2.15h11.47v-1.434c-0.046-1.65-0.425-2.759-1.142-3.324
+				c-0.717-0.563-2.097-0.847-4.14-0.847C321.84,85.016,317.324,85.191,311.851,85.538z M318.888,99.482v1.238
+				c0,2.215,1.26,3.321,3.778,3.321c2.606,0,5.278-1.041,8.017-3.127v-4.496h-8.666C319.931,96.461,318.888,97.484,318.888,99.482z"
+				/>
+			
+				<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="291.9043" y1="-49.4624" x2="291.9043" y2="-100.3454" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_8_)" d="M152.485,96.159c-0.913-1.562-1.912-2.714-2.997-3.453v-0.131c1.303-0.868,2.302-1.89,2.997-3.062
+				l8.341-11.143H150.01l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865V64.881h-2.992l-6.651,9.482v36.13h9.644v-10.1
+				c0-1.26-0.152-2.867-0.455-4.822h3.062l8.992,14.922h10.816L152.485,96.159z"/>
+			
+				<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="411.2822" y1="-49.4624" x2="411.2822" y2="-100.3453" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_9_)" d="M272.646,103.26h-2.606c-2.435,0-3.647-1.086-3.647-3.258V64.881h-3.015l-6.565,9.36v28.171
+				c0,2.824,0.826,5.008,2.477,6.549c1.65,1.543,3.91,2.313,6.777,2.313c3.475,0,6.037-0.435,7.688-1.304L272.646,103.26z"/>
+			
+				<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="506.0684" y1="-49.4624" x2="506.0684" y2="-100.3454" gradientTransform="matrix(1 0 0 -1 -146 28.7822)">
+				<stop  offset="0" style="stop-color:#FFFFFF"/>
+				<stop  offset="0.5103" style="stop-color:#F2F1F2"/>
+				<stop  offset="1" style="stop-color:#E9E8E9"/>
+			</linearGradient>
+			<path fill="url(#SVGID_10_)" d="M366.649,96.159c-0.912-1.562-1.912-2.714-2.998-3.453v-0.131
+				c1.304-0.868,2.304-1.89,2.998-3.062l8.341-11.143h-10.816l-7.948,11.208h-2.998c0.303-1.781,0.457-3.736,0.457-5.865V64.881
+				h-2.992l-6.652,9.484v36.127h9.645v-10.1c0-1.26-0.154-2.867-0.457-4.822h3.062l8.992,14.922h10.816L366.649,96.159z"/>
+		</g>
+	</g>
+	<g>
+		
+			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="264.1172" y1="-1546.0913" x2="326.7803" y2="-1546.0913" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#FEFEFE"/>
+			<stop  offset="0.1452" style="stop-color:#F4F5F4"/>
+			<stop  offset="0.6844" style="stop-color:#DADCDB"/>
+			<stop  offset="1" style="stop-color:#CFD1D1"/>
+		</linearGradient>
+		<path fill="url(#SVGID_11_)" d="M120.78,83.181c-7.205,5-14.688,3.683-23.183-3.357c-4.897-4.059-11.15-2.771-15.411-1.454
+			c-2.647,0.819-6.324,0.744-9.518,0.075c-13.979-2.93-10.93,6.038-8.339,14.015c4.757,14.641-3.236,18.031-5.983,12.815
+			c-1.766,6.615,7.138,8.572,10.937,7.701c6.007-1.377,14.052-2.154,19.044-0.627c9.544,2.916,13.125,0.512,11.542-2.57
+			c-0.521-1.012-0.229-2.446,0.583-3.127c2.834-2.373,5.295-0.373,8.007-1.946c2.107-1.226,2.077-3.927-1.19-5.463
+			c-1.73-0.812-1.648-2.882,0.185-3.841c3.729-1.95,8.75-1.034,10-5.137C117.899,88.794,119.151,85.105,120.78,83.181z"/>
+		
+			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="684.1572" y1="-833.1753" x2="675.8836" y2="-833.1753" gradientTransform="matrix(1 0 0 -1 -594 -737.2178)">
+			<stop  offset="0" style="stop-color:#E6E6E6"/>
+			<stop  offset="1" style="stop-color:#B3B4B4"/>
+		</linearGradient>
+		<path fill="url(#SVGID_12_)" d="M84.828,81.388c0,4.983,0.74,22.799,4.537,30.403l-8.733-0.192V80.126L84.828,81.388z"/>
+		
+			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="290.9736" y1="-1552.6763" x2="297.9739" y2="-1533.1755" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#F6F6F6"/>
+			<stop  offset="1" style="stop-color:#B3B4B4"/>
+		</linearGradient>
+		<path fill="url(#SVGID_13_)" d="M65.2,93.14c-2.762-7.459-6.509-16.625,7.47-13.695c3.192,0.669,6.869,0.744,9.518-0.075
+			c4.261-1.317,9.973-2.444,14.515,1.521c8.875,7.748,16.875,8.293,24.079,3.293c-1.63,1.924-3.105,5.562-3.329,7.082
+			c-0.189,1.293-1.135,1.873-2.383,2.379c-18.519,7.52-15.394-5.307-21.352-9.479c-3.158-2.214-7.733-2.09-11.247-0.812
+			c-3.171,1.152-6.438,0.863-9.833-0.396C66.971,80.849,63.163,81.96,65.2,93.14z"/>
+		
+			<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="82.471" y1="111.904" x2="82.471" y2="80.681"/>
+		<g opacity="0.75">
+			<path fill="#FFFFFF" d="M89.527,79.08c2.72,0,4.941,0.747,6.795,2.284c5.541,4.592,10.631,6.823,15.558,6.823
+				c1.473,0,2.934-0.209,4.373-0.615c-0.317,0.854-0.56,1.602-0.714,2.111c-0.433,1.414-1.599,1.811-4.357,2.436
+				c-1.463,0.333-3.121,0.709-4.656,1.514c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.821,2.396,3.514
+				c1.152,0.541,1.478,1.135,1.486,1.373c0.013,0.26-0.343,0.486-0.449,0.551c-0.598,0.348-1.182,0.412-2.052,0.412
+				c-0.159,0-0.32-0.002-0.481-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
+				c-1.545,1.293-2.02,3.742-1.078,5.571c0.137,0.269,0.141,0.406,0.148,0.408c-0.093,0.127-0.771,0.563-2.586,0.563
+				c-1.775,0-4.106-0.426-6.74-1.229c-2.006-0.613-4.513-0.924-7.451-0.924c-3.827,0-8.429,0.553-12.624,1.516
+				c-0.412,0.094-0.935,0.145-1.509,0.145c-1.875,0-4.188-0.543-5.674-1.596c1.675-0.01,3.265-0.885,4.366-2.402
+				c1.341-1.846,3.15-6.288,0.213-15.329l-0.081-0.25c-1.277-3.937-2.87-8.832-1.541-10.664c0.509-0.698,1.637-1.053,3.354-1.053
+				c1.188,0,2.632,0.178,4.295,0.525c1.76,0.369,3.618,0.562,5.375,0.562c1.944,0,3.676-0.23,5.144-0.686
+				C84.444,79.765,86.957,79.08,89.527,79.08 M89.527,77.08c-2.663,0-5.242,0.641-7.34,1.29c-1.324,0.41-2.904,0.597-4.553,0.597
+				c-1.649,0-3.367-0.188-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.475,0-5.881,7.664-3.635,14.582
+				c3.376,10.396,0.326,15.117-2.708,15.117c-1.241,0-2.479-0.789-3.276-2.301c-1.506,5.643,4.751,7.895,8.98,7.895
+				c0.729,0,1.396-0.065,1.955-0.192c3.685-0.845,8.135-1.463,12.178-1.463c2.549,0,4.936,0.245,6.865,0.836
+				c3.037,0.933,5.473,1.317,7.326,1.317c3.976,0,5.295-1.785,4.217-3.889c-0.521-1.012-0.229-2.445,0.582-3.125
+				c1.375-1.152,2.663-1.275,3.936-1.275c0.34,0,0.679,0.011,1.018,0.011c1.005,0,2.012-0.076,3.056-0.683
+				c2.107-1.227,2.077-3.928-1.19-5.463c-1.73-0.813-1.648-2.881,0.185-3.84c3.729-1.953,8.75-1.037,10-5.139
+				c0.447-1.473,1.699-5.162,3.329-7.084c-2.905,2.018-5.856,3.006-8.901,3.006c-4.504,0-9.211-2.164-14.28-6.364
+				C95.111,77.763,92.275,77.08,89.527,77.08L89.527,77.08z M120.78,83.181h0.006H120.78z"/>
+		</g>
+		<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+			M120.78,83.181c-7.205,5-14.688,3.683-23.183-3.357c-4.897-4.059-11.15-2.771-15.411-1.454c-2.647,0.819-6.324,0.744-9.518,0.075
+			c-13.979-2.93-10.93,6.038-8.339,14.015c4.757,14.641-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
+			c6.007-1.377,14.052-2.154,19.044-0.627c9.544,2.916,13.125,0.512,11.542-2.57c-0.521-1.012-0.229-2.446,0.583-3.127
+			c2.834-2.373,5.295-0.373,8.007-1.946c2.107-1.226,2.077-3.927-1.19-5.463c-1.73-0.812-1.648-2.882,0.185-3.841
+			c3.729-1.95,8.75-1.034,10-5.137C117.899,88.794,119.151,85.105,120.78,83.181z"/>
+		<path fill="#034672" d="M65.2,92.14c-2.762-7.459-6.509-16.625,7.47-13.695c3.192,0.669,6.869,0.744,9.518-0.075
+			c4.261-1.317,9.973-2.444,14.515,1.521c8.875,7.748,16.875,8.293,24.079,3.293c-1.63,1.924-3.105,5.562-3.329,7.082
+			c-0.189,1.293-1.116,1.916-2.383,2.379c-13.119,4.795-14.124-5.484-20.082-9.664c-3.157-2.215-9.003-1.908-12.517-0.631
+			c-3.171,1.153-6.438,0.865-9.833-0.396C66.971,79.849,63.163,80.96,65.2,92.14z"/>
+		
+			<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="273.9326" y1="-1540.3081" x2="304.77" y2="-1532.6405" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#B8D7E8"/>
+			<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+			<stop  offset="0.6937" style="stop-color:#DAEBF8"/>
+			<stop  offset="1" style="stop-color:#E0EEF9"/>
+		</linearGradient>
+		<path fill="url(#SVGID_14_)" d="M87.452,57.497c-1.053-0.594-4.274-2.612-5.079-3.063c-0.807-0.453-2.724-1.881-4.819-1.881
+			v69.289l4.819-4.936V82.746c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.16
+			c0-2.14,0.778-2.969,1.762-3.469c2.883-1.462,4.479-3.598,4.479-6.439c0-0.956,0-3.213,0-4.521
+			C91.176,59.534,88.257,57.951,87.452,57.497z"/>
+		
+			<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="276.8936" y1="-1516.1357" x2="285.5189" y2="-1558.3877" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#F1F9FE"/>
+			<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+			<stop  offset="1" style="stop-color:#E4F3FC"/>
+		</linearGradient>
+		<path fill="url(#SVGID_15_)" d="M77.554,52.552c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.451-4.026,2.471-5.079,3.063
+			c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.31,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44
+			c0.982,0.498,1.762,1.328,1.762,3.467c0,0.943,0.352,1.162,0.918,1.162h0.68c0.625,0,0.965,0.234,0.965,1.256
+			c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l0.862-0.883L77.554,52.552L77.554,52.552z"/>
+		<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M77.264,52.552
+			c1.908,0.938,3.431,1.965,4.236,2.418c0.805,0.453,4.026,2.472,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34
+			c0,1.309,0,2.807,0,3.762c0,2.844-1.597,4.979-4.479,6.44c-0.982,0.499-1.762,1.431-1.762,3.569v1.238"/>
+		<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M87.452,57.497
+			c-1.053-0.594-4.274-2.612-5.079-3.063c-0.807-0.453-2.724-1.881-4.819-1.881c-2.095,0-4.014,1.428-4.819,1.881
+			c-0.805,0.451-4.026,2.471-5.079,3.063c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.31,0,3.564,0,4.521
+			c0,2.843,1.597,4.979,4.479,6.44c0.982,0.498,1.762,1.328,1.762,3.467c0,0.943,0.352,1.162,0.918,1.162h0.68
+			c0.625,0,0.965,0.234,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.683-5.82V82.745c0,0,0-1.5,0-2.062
+			c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.219,0.918-1.162c0-2.139,0.778-2.969,1.762-3.467
+			c2.883-1.463,4.479-3.599,4.479-6.44c0-0.956,0-3.212,0-4.521C91.176,59.534,88.257,57.951,87.452,57.497z"/>
+		<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M92.373,82.745"/>
+		
+			<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="283.5557" y1="-1511.2954" x2="283.5557" y2="-1521.4633" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#01649B"/>
+			<stop  offset="0.2355" style="stop-color:#03588B"/>
+			<stop  offset="0.507" style="stop-color:#004E7C"/>
+			<stop  offset="0.7167" style="stop-color:#004873"/>
+			<stop  offset="1" style="stop-color:#00446E"/>
+		</linearGradient>
+		<polygon fill="url(#SVGID_16_)" points="77.556,62.472 68.504,60.448 67.504,64.187 77.556,69.245 87.607,64.187 86.607,60.448 		
+			"/>
+		<polyline opacity="0.2" fill="#010202" enable-background="new    " points="77.556,69.245 87.607,64.187 86.607,60.448 
+			77.556,62.472 		"/>
+		<path fill="#034672" d="M72.638,81.953c3.396,1.262,6.662,1.55,9.833,0.396l-0.283-2.224c-2.647,0.82-6.324,0.744-9.518,0.075
+			L72.638,81.953z"/>
+		<path fill="#034672" d="M77.282,81.599c-0.402,2.758,1.896,4.707,1.896,7.619C83.027,84.884,78.105,83.421,77.282,81.599z"/>
+		<path fill="#034672" d="M77.235,81.787c-0.118,3.207-0.401,5.581-1.74,7.246C73.075,84.296,76.182,82.714,77.235,81.787z"/>
+		<circle fill="#034672" cx="77.264" cy="81.765" r="1.594"/>
+		
+			<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="294.3252" y1="-1563.0669" x2="294.3252" y2="-1563.0669" gradientTransform="matrix(1 0 0 -1 -206 -1450.7178)">
+			<stop  offset="0" style="stop-color:#F6F6F6"/>
+			<stop  offset="0.5386" style="stop-color:#E4E4E3"/>
+			<stop  offset="1" style="stop-color:#DADADA"/>
+		</linearGradient>
+		<path fill="url(#SVGID_17_)" d="M88.325,112.349"/>
+	</g>
+</g>
+</svg>
diff --git a/misc/logo/logo-big-blue.svg b/misc/logo/logo-big-blue.svg
index f3c0d5c..10f8a37 100644
--- a/misc/logo/logo-big-blue.svg
+++ b/misc/logo/logo-big-blue.svg
@@ -1,205 +1,205 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="322.131px" height="77.5px" viewBox="0 0 322.131 77.5" enable-background="new 0 0 322.131 77.5" xml:space="preserve">
-<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-189.8491" y1="135.8701" x2="-127.186" y2="135.8701" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-	<stop  offset="0" style="stop-color:#FDFDFD"/>
-	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
-	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
-	<stop  offset="1" style="stop-color:#CFD1D1"/>
-</linearGradient>
-<path fill="url(#SVGID_1_)" d="M66.814,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454
-	c-2.648,0.82-6.324,0.744-9.518,0.075c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815
-	c-1.766,6.615,7.138,8.572,10.937,7.701c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57
-	c-0.52-1.012-0.229-2.446,0.583-3.126c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463
-	c-1.731-0.813-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.138C63.933,40.052,65.185,36.362,66.814,34.438z"/>
-<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="36.1904" y1="47.2168" x2="27.9168" y2="47.2168">
-	<stop  offset="0" style="stop-color:#E6E6E6"/>
-	<stop  offset="1" style="stop-color:#B2B3B3"/>
-</linearGradient>
-<path fill="url(#SVGID_2_)" d="M30.861,32.645c0,4.983,0.741,22.798,4.538,30.405l-8.734-0.194V31.383L30.861,32.645z"/>
-<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-356.9922" y1="766.7129" x2="-349.9919" y2="747.2122" gradientTransform="matrix(1 0 0 1 388 -713.5)">
-	<stop  offset="0" style="stop-color:#F6F6F6"/>
-	<stop  offset="1" style="stop-color:#B2B3B3"/>
-</linearGradient>
-<path fill="url(#SVGID_3_)" d="M11.234,44.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
-	c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
-	c-0.189,1.293-1.134,1.873-2.382,2.379c-18.519,7.519-15.394-5.307-21.352-9.481c-3.158-2.214-7.733-2.09-11.247-0.812
-	c-3.171,1.153-6.437,0.864-9.833-0.396C13.004,32.105,9.196,33.217,11.234,44.396z"/>
-<g opacity="0.75">
-	<path fill="#FFFFFF" d="M35.561,30.336c2.719,0,4.941,0.747,6.795,2.284c5.541,4.592,10.63,6.823,15.557,6.823
-		c1.473,0,2.934-0.206,4.373-0.615c-0.317,0.854-0.559,1.602-0.714,2.111c-0.432,1.414-1.598,1.811-4.357,2.437
-		c-1.463,0.332-3.121,0.708-4.656,1.513c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.822,2.396,3.514
-		c1.153,0.541,1.478,1.135,1.487,1.373c0.012,0.26-0.343,0.487-0.45,0.551c-0.597,0.346-1.181,0.412-2.051,0.412
-		c-0.16,0-0.321-0.002-0.482-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
-		c-1.545,1.294-2.019,3.742-1.078,5.573c0.137,0.267,0.141,0.405,0.149,0.407c-0.093,0.127-0.771,0.567-2.586,0.567
-		c-1.776,0-4.107-0.426-6.741-1.229c-2.005-0.613-4.512-0.924-7.451-0.924c-3.827,0-8.428,0.553-12.624,1.515
-		c-0.412,0.094-0.934,0.144-1.509,0.144c-1.875,0-4.187-0.543-5.673-1.594c1.674-0.011,3.264-0.886,4.366-2.404
-		c1.341-1.844,3.15-6.289,0.213-15.33l-0.081-0.25c-1.278-3.936-2.87-8.834-1.541-10.663c0.508-0.699,1.636-1.053,3.354-1.053
-		c1.188,0,2.632,0.177,4.295,0.525c1.76,0.369,3.618,0.563,5.375,0.563c1.944,0,3.676-0.231,5.144-0.686
-		C30.478,31.021,32.99,30.336,35.561,30.336 M35.561,28.336c-2.663,0-5.243,0.641-7.34,1.29c-1.324,0.41-2.904,0.596-4.553,0.596
-		s-3.367-0.187-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.474,0-5.881,7.664-3.635,14.583
-		c3.376,10.394,0.327,15.117-2.708,15.117c-1.241,0-2.479-0.789-3.276-2.302c-1.506,5.643,4.751,7.896,8.98,7.896
-		c0.729,0,1.397-0.067,1.956-0.194C19,63.389,23.45,62.77,27.493,62.77c2.549,0,4.936,0.246,6.866,0.836
-		c3.037,0.929,5.472,1.318,7.326,1.318c3.975,0,5.295-1.785,4.216-3.888c-0.52-1.013-0.229-2.446,0.583-3.126
-		c1.375-1.152,2.663-1.274,3.935-1.274c0.34,0,0.679,0.009,1.018,0.009c1.005,0,2.011-0.076,3.055-0.682
-		c2.108-1.227,2.077-3.927-1.19-5.463c-1.731-0.814-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.139
-		c0.448-1.47,1.7-5.159,3.33-7.083c-2.906,2.017-5.857,3.005-8.902,3.005c-4.504,0-9.211-2.163-14.28-6.364
-		C41.145,29.019,38.309,28.336,35.561,28.336L35.561,28.336z M66.814,34.438h0.005H66.814z"/>
-</g>
-<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="28.504" y1="63.161" x2="28.504" y2="31.938"/>
-<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-	M66.814,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
-	c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
-	c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
-	c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
-	c3.73-1.952,8.75-1.036,10-5.138C63.933,40.052,65.185,36.362,66.814,34.438z"/>
-<path fill="#034672" d="M11.234,43.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
-	c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
-	c-0.189,1.293-1.116,1.916-2.382,2.379c-13.119,4.795-14.124-5.487-20.082-9.665c-3.158-2.214-9.003-1.908-12.517-0.63
-	c-3.171,1.153-6.437,0.864-9.833-0.396C13.004,31.105,9.196,32.217,11.234,43.396z"/>
-<path fill="#FFFFFF" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881
-	c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34
-	c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161
-	h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
-	c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
-	c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C37.209,10.79,34.29,9.207,33.485,8.753z"/>
-<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-180.0332" y1="141.6543" x2="-149.1986" y2="149.3212" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-	<stop  offset="0" style="stop-color:#B8D7E9"/>
-	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
-	<stop  offset="1" style="stop-color:#DFEEF9"/>
-</linearGradient>
-<path fill="url(#SVGID_4_)" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881v69.29
-	l4.819-4.936v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
-	c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
-	C37.209,10.79,34.29,9.207,33.485,8.753z"/>
-<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-177.0732" y1="165.8252" x2="-168.4482" y2="123.5749" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-	<stop  offset="0" style="stop-color:#F1F9FE"/>
-	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-	<stop  offset="1" style="stop-color:#E4F3FD"/>
-</linearGradient>
-<path fill="url(#SVGID_5_)" d="M23.587,3.808c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
-	c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468
-	c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244
-	l0.862-0.883L23.587,3.808L23.587,3.808z"/>
-<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M23.297,3.808c1.908,0.938,3.431,1.966,4.236,2.419
-	c0.805,0.452,4.027,2.471,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34c0,1.309,0,2.806,0,3.762c0,2.843-1.597,4.979-4.479,6.44
-	c-0.983,0.499-1.762,1.431-1.762,3.569v1.238"/>
-<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064
-	c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
-	c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468
-	c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244
-	l5.682-5.819v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
-	c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
-	C37.209,10.79,34.29,9.207,33.485,8.753z"/>
-<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M38.406,34.001"/>
-<g>
-	
-		<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-72.4878" y1="166.5" x2="-72.4878" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_6_)" d="M127.54,48.914h-11.599c0.303,2.346,1.01,3.92,2.117,4.725s2.943,1.205,5.506,1.205
-		c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.607-8.015,2.411-14.01,2.411c-6.038,0-10.339-1.304-12.901-3.909
-		c-2.563-2.607-3.845-6.907-3.845-12.902c0-6.299,1.248-10.707,3.746-13.228c2.498-2.519,6.701-3.779,12.609-3.779
-		c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.744
-		C133.459,48.164,130.971,48.914,127.54,48.914z M115.746,43.114h9.122c1.173,0,1.966-0.282,2.378-0.847
-		c0.413-0.564,0.619-1.392,0.619-2.478c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
-		c-2.477,0-4.171,0.489-5.083,1.466C116.397,38.195,115.876,40.16,115.746,43.114z"/>
-	
-		<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-38.8638" y1="166.5" x2="-38.8638" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_7_)" d="M172.957,29.626l-11.402,32.581c-0.609,1.736-1.359,3.344-2.248,4.82
-		c-0.892,1.478-2.031,2.899-3.422,4.27c-1.391,1.368-3.117,2.378-5.18,3.029c-2.064,0.652-4.355,0.824-6.875,0.521l-0.781-5.67
-		c2.605-0.695,4.647-1.597,6.125-2.703c1.477-1.107,2.627-2.597,3.453-4.464l0.131-0.262h-1.825c-1.607,0-2.649-0.781-3.128-2.347
-		l-10.49-29.777h10.295l5.995,20.786c0.391,1.521,0.717,3.128,0.978,4.821h0.847c0.13-0.521,0.347-1.336,0.651-2.442
-		c0.304-1.106,0.521-1.899,0.652-2.379l5.93-20.786L172.957,29.626L172.957,29.626z"/>
-	
-		<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-7.7783" y1="166.5" x2="-7.7783" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_8_)" d="M199.644,54.127l0.849,6.256c-3.304,1.434-7.451,2.149-12.446,2.149
-		c-5.908,0-10.066-1.271-12.479-3.812c-2.412-2.54-3.616-6.896-3.616-13.063c0-6.213,1.216-10.59,3.647-13.131
-		c2.435-2.541,6.625-3.812,12.576-3.812c4.865,0,8.818,0.674,11.859,2.021l-1.042,5.994c-4.692-0.086-7.755-0.131-9.188-0.131
-		c-2.953,0-4.984,0.631-6.092,1.891c-1.107,1.26-1.662,3.648-1.662,7.168c0,3.518,0.555,5.908,1.662,7.167
-		c1.107,1.261,3.139,1.89,6.092,1.89C193.583,54.713,196.862,54.518,199.644,54.127z"/>
-	
-		<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="42.9717" y1="166.5" x2="42.9717" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_9_)" d="M237.004,28.714c5.996,0,10.241,1.293,12.74,3.877c2.497,2.585,3.746,6.962,3.746,13.13
-		c0,6.17-1.249,10.523-3.746,13.064c-2.499,2.542-6.744,3.812-12.74,3.812c-6.038,0-10.308-1.271-12.804-3.812
-		c-2.499-2.541-3.747-6.896-3.747-13.064c0-6.211,1.248-10.599,3.747-13.162C226.697,29.996,230.966,28.714,237.004,28.714z
-		 M237.004,35.947c-2.562,0-4.278,0.65-5.146,1.954c-0.871,1.304-1.305,3.91-1.305,7.819c0,3.823,0.434,6.386,1.305,7.689
-		c0.867,1.303,2.584,1.955,5.146,1.955c2.478,0,4.16-0.652,5.052-1.955c0.889-1.304,1.336-3.866,1.336-7.689
-		c0-3.864-0.437-6.461-1.305-7.787C241.218,36.609,239.522,35.947,237.004,35.947z"/>
-	
-		<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="76.8818" y1="166.5" x2="76.8818" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_10_)" d="M257.883,36.794l-0.911-6.517c5.776-1.043,11.358-1.563,16.745-1.563
-		c4.345,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154V61.75h-7.625l-0.977-4.887
-		c-3.217,3.779-7.168,5.669-11.859,5.669c-3.086,0-5.604-0.814-7.559-2.443c-1.955-1.629-2.934-3.897-2.934-6.81v-3.258
-		c0-2.562,0.869-4.562,2.607-5.994c1.735-1.435,4.147-2.15,7.231-2.15h11.469v-1.434c-0.045-1.65-0.424-2.759-1.141-3.324
-		c-0.718-0.563-2.097-0.847-4.14-0.847C267.873,36.272,263.356,36.447,257.883,36.794z M264.92,50.738v1.238
-		c0,2.215,1.261,3.321,3.779,3.321c2.606,0,5.278-1.042,8.016-3.127v-4.496h-8.666C265.963,47.719,264.92,48.74,264.92,50.738z"/>
-	
-		<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-102.0625" y1="166.5" x2="-102.0625" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_11_)" d="M98.519,47.415c-0.913-1.563-1.912-2.714-2.997-3.454v-0.13c1.303-0.868,2.302-1.89,2.997-3.062
-		l8.341-11.144H96.043l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865V16.138h-2.992l-6.651,9.482v36.13h9.644v-10.1
-		c0-1.26-0.152-2.867-0.455-4.822h3.062L97.15,61.75h10.816L98.519,47.415z"/>
-	
-		<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="17.3159" y1="166.5" x2="17.3159" y2="111.1533" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_12_)" d="M218.678,54.518h-2.606c-2.434,0-3.647-1.086-3.647-3.258V16.138h-3.014l-6.565,9.36V53.67
-		c0,2.824,0.825,5.008,2.477,6.549c1.65,1.542,3.91,2.313,6.777,2.313c3.475,0,6.036-0.435,7.688-1.304L218.678,54.518z"/>
-	
-		<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="112.103" y1="166.5" x2="112.103" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_13_)" d="M312.684,47.415c-0.911-1.563-1.911-2.714-2.998-3.454v-0.13c1.304-0.868,2.304-1.89,2.998-3.062
-		l8.341-11.144h-10.816l-7.949,11.208h-2.998c0.303-1.781,0.457-3.736,0.457-5.865V16.138h-2.992l-6.651,9.484V61.75h9.645v-10.1
-		c0-1.26-0.153-2.867-0.457-4.822h3.062l8.992,14.922h10.815L312.684,47.415z"/>
-</g>
-<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-170.4106" y1="170.666" x2="-170.4106" y2="160.4981" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-	<stop  offset="0" style="stop-color:#00639A"/>
-	<stop  offset="0.2355" style="stop-color:#00578A"/>
-	<stop  offset="0.507" style="stop-color:#004D7B"/>
-	<stop  offset="0.7167" style="stop-color:#004773"/>
-	<stop  offset="1" style="stop-color:#00446E"/>
-</linearGradient>
-<polygon fill="url(#SVGID_14_)" points="23.589,13.729 14.537,11.704 13.537,15.443 23.589,20.501 33.641,15.443 32.641,11.704 "/>
-<polyline opacity="0.2" enable-background="new    " points="23.589,20.501 33.641,15.443 32.641,11.704 23.589,13.729 "/>
-<path fill="#034672" d="M18.671,33.209c3.396,1.261,6.662,1.55,9.833,0.396l-0.283-2.223c-2.648,0.82-6.324,0.744-9.518,0.075
-	L18.671,33.209z"/>
-<path fill="#034672" d="M23.316,32.856c-0.403,2.757,1.896,4.707,1.896,7.619C29.061,36.14,24.139,34.678,23.316,32.856z"/>
-<path fill="#034672" d="M23.269,33.043c-0.118,3.207-0.402,5.581-1.741,7.247C19.109,35.553,22.215,33.97,23.269,33.043z"/>
-<circle fill="#034672" cx="23.297" cy="33.021" r="1.594"/>
-<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-159.6411" y1="118.8945" x2="-159.6411" y2="118.8945" gradientTransform="matrix(1 0 0 -1 194 182.5)">
-	<stop  offset="0" style="stop-color:#F6F6F6"/>
-	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
-	<stop  offset="1" style="stop-color:#DADADA"/>
-</linearGradient>
-<path fill="url(#SVGID_15_)" d="M34.359,63.605"/>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="322.131px" height="77.5px" viewBox="0 0 322.131 77.5" enable-background="new 0 0 322.131 77.5" xml:space="preserve">
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-189.8491" y1="135.8701" x2="-127.186" y2="135.8701" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+	<stop  offset="0" style="stop-color:#FDFDFD"/>
+	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
+	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
+	<stop  offset="1" style="stop-color:#CFD1D1"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M66.814,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454
+	c-2.648,0.82-6.324,0.744-9.518,0.075c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815
+	c-1.766,6.615,7.138,8.572,10.937,7.701c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57
+	c-0.52-1.012-0.229-2.446,0.583-3.126c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463
+	c-1.731-0.813-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.138C63.933,40.052,65.185,36.362,66.814,34.438z"/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="36.1904" y1="47.2168" x2="27.9168" y2="47.2168">
+	<stop  offset="0" style="stop-color:#E6E6E6"/>
+	<stop  offset="1" style="stop-color:#B2B3B3"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M30.861,32.645c0,4.983,0.741,22.798,4.538,30.405l-8.734-0.194V31.383L30.861,32.645z"/>
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-356.9922" y1="766.7129" x2="-349.9919" y2="747.2122" gradientTransform="matrix(1 0 0 1 388 -713.5)">
+	<stop  offset="0" style="stop-color:#F6F6F6"/>
+	<stop  offset="1" style="stop-color:#B2B3B3"/>
+</linearGradient>
+<path fill="url(#SVGID_3_)" d="M11.234,44.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
+	c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
+	c-0.189,1.293-1.134,1.873-2.382,2.379c-18.519,7.519-15.394-5.307-21.352-9.481c-3.158-2.214-7.733-2.09-11.247-0.812
+	c-3.171,1.153-6.437,0.864-9.833-0.396C13.004,32.105,9.196,33.217,11.234,44.396z"/>
+<g opacity="0.75">
+	<path fill="#FFFFFF" d="M35.561,30.336c2.719,0,4.941,0.747,6.795,2.284c5.541,4.592,10.63,6.823,15.557,6.823
+		c1.473,0,2.934-0.206,4.373-0.615c-0.317,0.854-0.559,1.602-0.714,2.111c-0.432,1.414-1.598,1.811-4.357,2.437
+		c-1.463,0.332-3.121,0.708-4.656,1.513c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.822,2.396,3.514
+		c1.153,0.541,1.478,1.135,1.487,1.373c0.012,0.26-0.343,0.487-0.45,0.551c-0.597,0.346-1.181,0.412-2.051,0.412
+		c-0.16,0-0.321-0.002-0.482-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
+		c-1.545,1.294-2.019,3.742-1.078,5.573c0.137,0.267,0.141,0.405,0.149,0.407c-0.093,0.127-0.771,0.567-2.586,0.567
+		c-1.776,0-4.107-0.426-6.741-1.229c-2.005-0.613-4.512-0.924-7.451-0.924c-3.827,0-8.428,0.553-12.624,1.515
+		c-0.412,0.094-0.934,0.144-1.509,0.144c-1.875,0-4.187-0.543-5.673-1.594c1.674-0.011,3.264-0.886,4.366-2.404
+		c1.341-1.844,3.15-6.289,0.213-15.33l-0.081-0.25c-1.278-3.936-2.87-8.834-1.541-10.663c0.508-0.699,1.636-1.053,3.354-1.053
+		c1.188,0,2.632,0.177,4.295,0.525c1.76,0.369,3.618,0.563,5.375,0.563c1.944,0,3.676-0.231,5.144-0.686
+		C30.478,31.021,32.99,30.336,35.561,30.336 M35.561,28.336c-2.663,0-5.243,0.641-7.34,1.29c-1.324,0.41-2.904,0.596-4.553,0.596
+		s-3.367-0.187-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.474,0-5.881,7.664-3.635,14.583
+		c3.376,10.394,0.327,15.117-2.708,15.117c-1.241,0-2.479-0.789-3.276-2.302c-1.506,5.643,4.751,7.896,8.98,7.896
+		c0.729,0,1.397-0.067,1.956-0.194C19,63.389,23.45,62.77,27.493,62.77c2.549,0,4.936,0.246,6.866,0.836
+		c3.037,0.929,5.472,1.318,7.326,1.318c3.975,0,5.295-1.785,4.216-3.888c-0.52-1.013-0.229-2.446,0.583-3.126
+		c1.375-1.152,2.663-1.274,3.935-1.274c0.34,0,0.679,0.009,1.018,0.009c1.005,0,2.011-0.076,3.055-0.682
+		c2.108-1.227,2.077-3.927-1.19-5.463c-1.731-0.814-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.139
+		c0.448-1.47,1.7-5.159,3.33-7.083c-2.906,2.017-5.857,3.005-8.902,3.005c-4.504,0-9.211-2.163-14.28-6.364
+		C41.145,29.019,38.309,28.336,35.561,28.336L35.561,28.336z M66.814,34.438h0.005H66.814z"/>
+</g>
+<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="28.504" y1="63.161" x2="28.504" y2="31.938"/>
+<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+	M66.814,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
+	c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
+	c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
+	c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
+	c3.73-1.952,8.75-1.036,10-5.138C63.933,40.052,65.185,36.362,66.814,34.438z"/>
+<path fill="#034672" d="M11.234,43.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
+	c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
+	c-0.189,1.293-1.116,1.916-2.382,2.379c-13.119,4.795-14.124-5.487-20.082-9.665c-3.158-2.214-9.003-1.908-12.517-0.63
+	c-3.171,1.153-6.437,0.864-9.833-0.396C13.004,31.105,9.196,32.217,11.234,43.396z"/>
+<path fill="#FFFFFF" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881
+	c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34
+	c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161
+	h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
+	c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
+	c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C37.209,10.79,34.29,9.207,33.485,8.753z"/>
+<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-180.0332" y1="141.6543" x2="-149.1986" y2="149.3212" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+	<stop  offset="0" style="stop-color:#B8D7E9"/>
+	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
+	<stop  offset="1" style="stop-color:#DFEEF9"/>
+</linearGradient>
+<path fill="url(#SVGID_4_)" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881v69.29
+	l4.819-4.936v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
+	c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
+	C37.209,10.79,34.29,9.207,33.485,8.753z"/>
+<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-177.0732" y1="165.8252" x2="-168.4482" y2="123.5749" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+	<stop  offset="0" style="stop-color:#F1F9FE"/>
+	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+	<stop  offset="1" style="stop-color:#E4F3FD"/>
+</linearGradient>
+<path fill="url(#SVGID_5_)" d="M23.587,3.808c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
+	c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468
+	c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244
+	l0.862-0.883L23.587,3.808L23.587,3.808z"/>
+<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M23.297,3.808c1.908,0.938,3.431,1.966,4.236,2.419
+	c0.805,0.452,4.027,2.471,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34c0,1.309,0,2.806,0,3.762c0,2.843-1.597,4.979-4.479,6.44
+	c-0.983,0.499-1.762,1.431-1.762,3.569v1.238"/>
+<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M33.485,8.753c-1.052-0.594-4.274-2.612-5.079-3.064
+	c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
+	c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468
+	c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244
+	l5.682-5.819v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
+	c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
+	C37.209,10.79,34.29,9.207,33.485,8.753z"/>
+<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M38.406,34.001"/>
+<g>
+	
+		<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-72.4878" y1="166.5" x2="-72.4878" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_6_)" d="M127.54,48.914h-11.599c0.303,2.346,1.01,3.92,2.117,4.725s2.943,1.205,5.506,1.205
+		c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.607-8.015,2.411-14.01,2.411c-6.038,0-10.339-1.304-12.901-3.909
+		c-2.563-2.607-3.845-6.907-3.845-12.902c0-6.299,1.248-10.707,3.746-13.228c2.498-2.519,6.701-3.779,12.609-3.779
+		c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.744
+		C133.459,48.164,130.971,48.914,127.54,48.914z M115.746,43.114h9.122c1.173,0,1.966-0.282,2.378-0.847
+		c0.413-0.564,0.619-1.392,0.619-2.478c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
+		c-2.477,0-4.171,0.489-5.083,1.466C116.397,38.195,115.876,40.16,115.746,43.114z"/>
+	
+		<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-38.8638" y1="166.5" x2="-38.8638" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_7_)" d="M172.957,29.626l-11.402,32.581c-0.609,1.736-1.359,3.344-2.248,4.82
+		c-0.892,1.478-2.031,2.899-3.422,4.27c-1.391,1.368-3.117,2.378-5.18,3.029c-2.064,0.652-4.355,0.824-6.875,0.521l-0.781-5.67
+		c2.605-0.695,4.647-1.597,6.125-2.703c1.477-1.107,2.627-2.597,3.453-4.464l0.131-0.262h-1.825c-1.607,0-2.649-0.781-3.128-2.347
+		l-10.49-29.777h10.295l5.995,20.786c0.391,1.521,0.717,3.128,0.978,4.821h0.847c0.13-0.521,0.347-1.336,0.651-2.442
+		c0.304-1.106,0.521-1.899,0.652-2.379l5.93-20.786L172.957,29.626L172.957,29.626z"/>
+	
+		<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-7.7783" y1="166.5" x2="-7.7783" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_8_)" d="M199.644,54.127l0.849,6.256c-3.304,1.434-7.451,2.149-12.446,2.149
+		c-5.908,0-10.066-1.271-12.479-3.812c-2.412-2.54-3.616-6.896-3.616-13.063c0-6.213,1.216-10.59,3.647-13.131
+		c2.435-2.541,6.625-3.812,12.576-3.812c4.865,0,8.818,0.674,11.859,2.021l-1.042,5.994c-4.692-0.086-7.755-0.131-9.188-0.131
+		c-2.953,0-4.984,0.631-6.092,1.891c-1.107,1.26-1.662,3.648-1.662,7.168c0,3.518,0.555,5.908,1.662,7.167
+		c1.107,1.261,3.139,1.89,6.092,1.89C193.583,54.713,196.862,54.518,199.644,54.127z"/>
+	
+		<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="42.9717" y1="166.5" x2="42.9717" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_9_)" d="M237.004,28.714c5.996,0,10.241,1.293,12.74,3.877c2.497,2.585,3.746,6.962,3.746,13.13
+		c0,6.17-1.249,10.523-3.746,13.064c-2.499,2.542-6.744,3.812-12.74,3.812c-6.038,0-10.308-1.271-12.804-3.812
+		c-2.499-2.541-3.747-6.896-3.747-13.064c0-6.211,1.248-10.599,3.747-13.162C226.697,29.996,230.966,28.714,237.004,28.714z
+		 M237.004,35.947c-2.562,0-4.278,0.65-5.146,1.954c-0.871,1.304-1.305,3.91-1.305,7.819c0,3.823,0.434,6.386,1.305,7.689
+		c0.867,1.303,2.584,1.955,5.146,1.955c2.478,0,4.16-0.652,5.052-1.955c0.889-1.304,1.336-3.866,1.336-7.689
+		c0-3.864-0.437-6.461-1.305-7.787C241.218,36.609,239.522,35.947,237.004,35.947z"/>
+	
+		<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="76.8818" y1="166.5" x2="76.8818" y2="111.1529" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_10_)" d="M257.883,36.794l-0.911-6.517c5.776-1.043,11.358-1.563,16.745-1.563
+		c4.345,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154V61.75h-7.625l-0.977-4.887
+		c-3.217,3.779-7.168,5.669-11.859,5.669c-3.086,0-5.604-0.814-7.559-2.443c-1.955-1.629-2.934-3.897-2.934-6.81v-3.258
+		c0-2.562,0.869-4.562,2.607-5.994c1.735-1.435,4.147-2.15,7.231-2.15h11.469v-1.434c-0.045-1.65-0.424-2.759-1.141-3.324
+		c-0.718-0.563-2.097-0.847-4.14-0.847C267.873,36.272,263.356,36.447,257.883,36.794z M264.92,50.738v1.238
+		c0,2.215,1.261,3.321,3.779,3.321c2.606,0,5.278-1.042,8.016-3.127v-4.496h-8.666C265.963,47.719,264.92,48.74,264.92,50.738z"/>
+	
+		<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-102.0625" y1="166.5" x2="-102.0625" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_11_)" d="M98.519,47.415c-0.913-1.563-1.912-2.714-2.997-3.454v-0.13c1.303-0.868,2.302-1.89,2.997-3.062
+		l8.341-11.144H96.043l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865V16.138h-2.992l-6.651,9.482v36.13h9.644v-10.1
+		c0-1.26-0.152-2.867-0.455-4.822h3.062L97.15,61.75h10.816L98.519,47.415z"/>
+	
+		<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="17.3159" y1="166.5" x2="17.3159" y2="111.1533" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_12_)" d="M218.678,54.518h-2.606c-2.434,0-3.647-1.086-3.647-3.258V16.138h-3.014l-6.565,9.36V53.67
+		c0,2.824,0.825,5.008,2.477,6.549c1.65,1.542,3.91,2.313,6.777,2.313c3.475,0,6.036-0.435,7.688-1.304L218.678,54.518z"/>
+	
+		<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="112.103" y1="166.5" x2="112.103" y2="111.1545" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_13_)" d="M312.684,47.415c-0.911-1.563-1.911-2.714-2.998-3.454v-0.13c1.304-0.868,2.304-1.89,2.998-3.062
+		l8.341-11.144h-10.816l-7.949,11.208h-2.998c0.303-1.781,0.457-3.736,0.457-5.865V16.138h-2.992l-6.651,9.484V61.75h9.645v-10.1
+		c0-1.26-0.153-2.867-0.457-4.822h3.062l8.992,14.922h10.815L312.684,47.415z"/>
+</g>
+<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-170.4106" y1="170.666" x2="-170.4106" y2="160.4981" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+	<stop  offset="0" style="stop-color:#00639A"/>
+	<stop  offset="0.2355" style="stop-color:#00578A"/>
+	<stop  offset="0.507" style="stop-color:#004D7B"/>
+	<stop  offset="0.7167" style="stop-color:#004773"/>
+	<stop  offset="1" style="stop-color:#00446E"/>
+</linearGradient>
+<polygon fill="url(#SVGID_14_)" points="23.589,13.729 14.537,11.704 13.537,15.443 23.589,20.501 33.641,15.443 32.641,11.704 "/>
+<polyline opacity="0.2" enable-background="new    " points="23.589,20.501 33.641,15.443 32.641,11.704 23.589,13.729 "/>
+<path fill="#034672" d="M18.671,33.209c3.396,1.261,6.662,1.55,9.833,0.396l-0.283-2.223c-2.648,0.82-6.324,0.744-9.518,0.075
+	L18.671,33.209z"/>
+<path fill="#034672" d="M23.316,32.856c-0.403,2.757,1.896,4.707,1.896,7.619C29.061,36.14,24.139,34.678,23.316,32.856z"/>
+<path fill="#034672" d="M23.269,33.043c-0.118,3.207-0.402,5.581-1.741,7.247C19.109,35.553,22.215,33.97,23.269,33.043z"/>
+<circle fill="#034672" cx="23.297" cy="33.021" r="1.594"/>
+<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-159.6411" y1="118.8945" x2="-159.6411" y2="118.8945" gradientTransform="matrix(1 0 0 -1 194 182.5)">
+	<stop  offset="0" style="stop-color:#F6F6F6"/>
+	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
+	<stop  offset="1" style="stop-color:#DADADA"/>
+</linearGradient>
+<path fill="url(#SVGID_15_)" d="M34.359,63.605"/>
+</svg>
diff --git a/misc/logo/logo-big-white.svg b/misc/logo/logo-big-white.svg
index 3e5f017..da8cd0e 100644
--- a/misc/logo/logo-big-white.svg
+++ b/misc/logo/logo-big-white.svg
@@ -1,230 +1,230 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="325.403px" height="77.333px" viewBox="-3.268 0.083 325.403 77.333" enable-background="new -3.268 0.083 325.403 77.333"
-	 xml:space="preserve">
-<g>
-	<g>
-		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-			M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
-			c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
-			c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
-			c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
-			c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
-		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-			M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881
-			c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521
-			c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68
-			c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
-			c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
-			c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
-	</g>
-	
-		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-85.7192" y1="-1070.1299" x2="-23.0562" y2="-1070.1299" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#FDFDFD"/>
-		<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
-		<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
-		<stop  offset="1" style="stop-color:#CFD1D1"/>
-	</linearGradient>
-	<path fill="url(#SVGID_1_)" d="M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454
-		c-2.648,0.82-6.324,0.744-9.518,0.075c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815
-		c-1.766,6.615,7.138,8.572,10.937,7.701c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57
-		c-0.52-1.012-0.229-2.446,0.583-3.126c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463
-		c-1.731-0.813-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
-	
-		<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="334.3203" y1="-357.2158" x2="326.0467" y2="-357.2158" gradientTransform="matrix(1 0 0 -1 -302 -310)">
-		<stop  offset="0" style="stop-color:#E6E6E6"/>
-		<stop  offset="1" style="stop-color:#B2B3B3"/>
-	</linearGradient>
-	<path fill="url(#SVGID_2_)" d="M26.991,32.645c0,4.983,0.741,22.798,4.538,30.405l-8.734-0.194V31.383L26.991,32.645z"/>
-	
-		<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-58.8633" y1="-1076.7139" x2="-51.863" y2="-1057.2131" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#F6F6F6"/>
-		<stop  offset="1" style="stop-color:#B2B3B3"/>
-	</linearGradient>
-	<path fill="url(#SVGID_3_)" d="M7.364,44.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
-		c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
-		c-0.189,1.293-1.134,1.873-2.382,2.379c-18.519,7.52-15.394-5.307-21.352-9.48c-3.158-2.214-7.733-2.09-11.247-0.812
-		c-3.171,1.153-6.437,0.864-9.833-0.396C9.134,32.105,5.326,33.217,7.364,44.396z"/>
-	<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="24.634" y1="63.161" x2="24.634" y2="31.938"/>
-	<g opacity="0.75">
-		<path fill="#FFFFFF" d="M31.691,30.336c2.719,0,4.941,0.747,6.795,2.284c5.541,4.592,10.63,6.823,15.557,6.823
-			c1.473,0,2.934-0.208,4.373-0.615c-0.317,0.854-0.559,1.602-0.714,2.111c-0.432,1.414-1.598,1.811-4.357,2.437
-			c-1.463,0.332-3.121,0.708-4.656,1.513c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.822,2.396,3.514
-			c1.153,0.541,1.478,1.135,1.487,1.373c0.012,0.26-0.343,0.487-0.45,0.551c-0.597,0.348-1.181,0.412-2.051,0.412
-			c-0.16,0-0.321-0.002-0.482-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
-			c-1.545,1.294-2.019,3.742-1.078,5.573c0.137,0.267,0.141,0.405,0.149,0.407c-0.093,0.127-0.771,0.565-2.586,0.565
-			c-1.776,0-4.107-0.426-6.741-1.229c-2.005-0.612-4.512-0.924-7.451-0.924c-3.827,0-8.428,0.554-12.624,1.516
-			c-0.412,0.094-0.934,0.145-1.509,0.145c-1.875,0-4.187-0.543-5.673-1.595c1.674-0.011,3.264-0.886,4.366-2.403
-			c1.341-1.845,3.15-6.289,0.213-15.33l-0.081-0.25c-1.278-3.937-2.87-8.833-1.541-10.664c0.508-0.699,1.636-1.053,3.354-1.053
-			c1.188,0,2.632,0.177,4.295,0.525c1.76,0.369,3.618,0.563,5.375,0.563c1.944,0,3.676-0.231,5.144-0.686
-			C26.608,31.021,29.12,30.336,31.691,30.336 M31.691,28.336c-2.663,0-5.243,0.641-7.34,1.29c-1.324,0.41-2.904,0.596-4.553,0.596
-			s-3.367-0.187-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.474,0-5.881,7.664-3.635,14.583
-			C9.87,54.109,6.821,58.833,3.786,58.833c-1.241,0-2.479-0.789-3.276-2.302c-1.506,5.643,4.751,7.896,8.98,7.896
-			c0.729,0,1.397-0.067,1.956-0.194c3.684-0.844,8.134-1.463,12.177-1.463c2.549,0,4.936,0.246,6.866,0.836
-			c3.037,0.931,5.472,1.318,7.326,1.318c3.975,0,5.295-1.785,4.216-3.888c-0.52-1.013-0.229-2.446,0.583-3.126
-			c1.375-1.152,2.663-1.274,3.935-1.274c0.34,0,0.679,0.009,1.018,0.009c1.005,0,2.011-0.076,3.055-0.682
-			c2.108-1.227,2.077-3.927-1.19-5.463c-1.731-0.814-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.139
-			c0.448-1.472,1.7-5.161,3.33-7.083c-2.906,2.017-5.857,3.005-8.902,3.005c-4.504,0-9.211-2.163-14.28-6.364
-			C37.275,29.019,34.439,28.336,31.691,28.336L31.691,28.336z M62.944,34.438h0.005H62.944z"/>
-	</g>
-	<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-		M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
-		c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
-		c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
-		c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
-		c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
-	<path fill="#034672" d="M7.364,43.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
-		c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
-		c-0.189,1.293-1.116,1.916-2.382,2.379c-13.119,4.795-14.124-5.485-20.082-9.665c-3.158-2.214-9.003-1.908-12.517-0.63
-		c-3.171,1.153-6.437,0.864-9.833-0.396C9.134,31.105,5.326,32.217,7.364,43.396z"/>
-	<path fill="#FFFFFF" d="M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881
-		c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34
-		c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161
-		h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
-		c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
-		c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
-	
-		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-75.9038" y1="-1064.3447" x2="-45.0681" y2="-1056.6775" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#B8D7E9"/>
-		<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-		<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
-		<stop  offset="1" style="stop-color:#DFEEF9"/>
-	</linearGradient>
-	<path fill="url(#SVGID_4_)" d="M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881v69.29
-		l4.819-4.936v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
-		c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
-		C33.339,10.79,30.42,9.207,29.615,8.753z"/>
-	
-		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-72.9458" y1="-1040.1738" x2="-64.3205" y2="-1082.4258" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#F1F9FE"/>
-		<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-		<stop  offset="1" style="stop-color:#E4F3FD"/>
-	</linearGradient>
-	<path fill="url(#SVGID_5_)" d="M19.717,3.808c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
-		c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44
-		c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256
-		c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l0.862-0.883L19.717,3.808L19.717,3.808z"/>
-	<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M19.427,3.808c1.908,0.938,3.431,1.966,4.236,2.419
-		c0.805,0.452,4.027,2.471,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34c0,1.309,0,2.806,0,3.762c0,2.843-1.597,4.979-4.479,6.44
-		c-0.983,0.499-1.762,1.431-1.762,3.569v1.238"/>
-	<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M29.615,8.753
-		c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881
-		c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521
-		c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68
-		c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
-		c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
-		c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
-	<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M34.536,34.001"/>
-	<g>
-		
-			<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="35.5122" y1="-1053" x2="35.5122" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_6_)" d="M127.54,48.914h-11.599c0.303,2.346,1.01,3.92,2.117,4.725s2.943,1.205,5.506,1.205
-			c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.607-8.015,2.411-14.01,2.411c-6.038,0-10.339-1.304-12.901-3.909
-			c-2.563-2.607-3.845-6.907-3.845-12.902c0-6.299,1.248-10.707,3.746-13.228c2.498-2.519,6.701-3.779,12.609-3.779
-			c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.744
-			C133.459,48.164,130.971,48.914,127.54,48.914z M115.746,43.114h9.122c1.173,0,1.966-0.282,2.378-0.847
-			c0.413-0.564,0.619-1.394,0.619-2.479c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
-			c-2.477,0-4.171,0.489-5.083,1.466C116.397,38.195,115.876,40.16,115.746,43.114z"/>
-		
-			<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="69.1362" y1="-1053" x2="69.1362" y2="-1103.8832" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_7_)" d="M172.957,29.626l-11.402,32.581c-0.609,1.736-1.359,3.344-2.248,4.82
-			c-0.892,1.478-2.031,2.897-3.422,4.27c-1.391,1.368-3.117,2.378-5.18,3.029c-2.064,0.652-4.355,0.824-6.875,0.521l-0.781-5.672
-			c2.605-0.693,4.647-1.597,6.125-2.701c1.477-1.107,2.627-2.599,3.453-4.466l0.131-0.262h-1.825c-1.607,0-2.649-0.781-3.128-2.349
-			l-10.49-29.775h10.295l5.995,20.786c0.391,1.521,0.717,3.128,0.978,4.819h0.847c0.13-0.521,0.347-1.336,0.651-2.44
-			c0.304-1.104,0.521-1.897,0.652-2.379l5.93-20.786L172.957,29.626L172.957,29.626z"/>
-		
-			<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="100.2241" y1="-1053" x2="100.2241" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_8_)" d="M199.644,54.127l0.851,6.256c-3.306,1.434-7.451,2.149-12.446,2.149
-			c-5.906,0-10.064-1.271-12.479-3.812c-2.411-2.541-3.615-6.896-3.615-13.062c0-6.215,1.216-10.59,3.646-13.131
-			c2.436-2.541,6.625-3.812,12.575-3.812c4.865,0,8.818,0.674,11.859,2.021l-1.042,5.994c-4.692-0.086-7.756-0.131-9.188-0.131
-			c-2.953,0-4.984,0.631-6.093,1.891c-1.106,1.26-1.662,3.646-1.662,7.168c0,3.518,0.556,5.906,1.662,7.167s3.14,1.89,6.093,1.89
-			C193.583,54.713,196.862,54.518,199.644,54.127z"/>
-		
-			<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="150.9712" y1="-1053" x2="150.9712" y2="-1103.886" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_9_)" d="M237.004,28.714c5.996,0,10.241,1.293,12.74,3.877c2.497,2.585,3.746,6.962,3.746,13.13
-			c0,6.17-1.249,10.523-3.746,13.064c-2.499,2.542-6.744,3.812-12.74,3.812c-6.038,0-10.308-1.271-12.804-3.812
-			c-2.499-2.541-3.747-6.896-3.747-13.064c0-6.211,1.248-10.599,3.747-13.162C226.696,29.996,230.966,28.714,237.004,28.714z
-			 M237.004,35.947c-2.562,0-4.278,0.65-5.146,1.954c-0.871,1.304-1.305,3.91-1.305,7.82c0,3.822,0.434,6.385,1.305,7.688
-			c0.867,1.303,2.584,1.955,5.146,1.955c2.478,0,4.16-0.652,5.052-1.955c0.889-1.304,1.336-3.866,1.336-7.688
-			c0-3.865-0.437-6.462-1.305-7.788C241.218,36.609,239.522,35.947,237.004,35.947z"/>
-		
-			<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="184.8789" y1="-1053" x2="184.8789" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_10_)" d="M257.883,36.794l-0.911-6.517c5.776-1.043,11.358-1.563,16.745-1.563
-			c4.345,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154V61.75h-7.625l-0.979-4.887
-			c-3.217,3.779-7.168,5.669-11.857,5.669c-3.086,0-5.604-0.814-7.561-2.443s-2.936-3.897-2.936-6.81v-3.258
-			c0-2.562,0.869-4.562,2.607-5.994c1.735-1.437,4.146-2.15,7.23-2.15h11.47v-1.434c-0.045-1.65-0.424-2.759-1.142-3.324
-			c-0.717-0.563-2.097-0.847-4.14-0.847C267.873,36.272,263.356,36.447,257.883,36.794z M264.92,50.738v1.238
-			c0,2.215,1.261,3.319,3.779,3.319c2.606,0,5.278-1.042,8.016-3.127v-4.496h-8.666C265.963,47.719,264.92,48.74,264.92,50.738z"/>
-		
-			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="5.9375" y1="-1053" x2="5.9375" y2="-1103.882" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_11_)" d="M98.519,47.415c-0.913-1.563-1.912-2.714-2.997-3.454v-0.13c1.303-0.868,2.302-1.89,2.997-3.062
-			l8.341-11.146H96.043l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865v-18.83h-2.992l-6.651,9.482v36.13h9.644V51.648
-			c0-1.26-0.152-2.866-0.455-4.821h3.062L97.15,61.75h10.816L98.519,47.415z"/>
-		
-			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="125.3193" y1="-1053" x2="125.3193" y2="-1103.884" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_12_)" d="M218.679,54.518h-2.607c-2.434,0-3.646-1.086-3.646-3.258V16.138h-3.014l-6.563,9.36V53.67
-			c0,2.824,0.823,5.008,2.477,6.549c1.65,1.542,3.91,2.313,6.777,2.313c3.475,0,6.035-0.435,7.688-1.304L218.679,54.518z"/>
-		
-			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="220.1055" y1="-1053" x2="220.1055" y2="-1103.882" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-			<stop  offset="0" style="stop-color:#FFFFFE"/>
-			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-			<stop  offset="1" style="stop-color:#E9E7E8"/>
-		</linearGradient>
-		<path fill="url(#SVGID_13_)" d="M312.684,47.415c-0.909-1.563-1.909-2.714-2.998-3.454v-0.13c1.306-0.868,2.306-1.89,2.998-3.062
-			l8.343-11.146H310.21l-7.949,11.208h-2.996c0.303-1.781,0.455-3.736,0.455-5.865v-18.83h-2.99l-6.651,9.484V61.75h9.646v-10.1
-			c0-1.26-0.154-2.867-0.457-4.822h3.062l8.992,14.922h10.813L312.684,47.415z"/>
-	</g>
-	
-		<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-66.2808" y1="-1035.334" x2="-66.2808" y2="-1045.5018" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#00639A"/>
-		<stop  offset="0.2355" style="stop-color:#00578A"/>
-		<stop  offset="0.507" style="stop-color:#004D7B"/>
-		<stop  offset="0.7167" style="stop-color:#004773"/>
-		<stop  offset="1" style="stop-color:#00446E"/>
-	</linearGradient>
-	<polygon fill="url(#SVGID_14_)" points="19.719,13.729 10.667,11.704 9.667,15.443 19.719,20.501 29.771,15.443 28.771,11.704 	"/>
-	<polyline opacity="0.2" enable-background="new    " points="19.719,20.501 29.771,15.443 28.771,11.704 19.719,13.729 	"/>
-	<path fill="#034672" d="M14.801,33.209c3.396,1.261,6.662,1.55,9.833,0.396l-0.283-2.223c-2.648,0.82-6.324,0.744-9.518,0.075
-		L14.801,33.209z"/>
-	<path fill="#034672" d="M19.446,32.856c-0.403,2.757,1.896,4.707,1.896,7.619C25.191,36.14,20.269,34.678,19.446,32.856z"/>
-	<path fill="#034672" d="M19.399,33.043c-0.118,3.207-0.402,5.581-1.741,7.247C15.239,35.553,18.345,33.97,19.399,33.043z"/>
-	<circle fill="#034672" cx="19.427" cy="33.021" r="1.594"/>
-	
-		<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-55.5112" y1="-1087.1055" x2="-55.5112" y2="-1087.1055" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
-		<stop  offset="0" style="stop-color:#F6F6F6"/>
-		<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
-		<stop  offset="1" style="stop-color:#DADADA"/>
-	</linearGradient>
-	<path fill="url(#SVGID_15_)" d="M30.489,63.605"/>
-</g>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="325.403px" height="77.333px" viewBox="-3.268 0.083 325.403 77.333" enable-background="new -3.268 0.083 325.403 77.333"
+	 xml:space="preserve">
+<g>
+	<g>
+		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+			M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
+			c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
+			c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
+			c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
+			c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
+		<path fill="none" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+			M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881
+			c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521
+			c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68
+			c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
+			c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
+			c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
+	</g>
+	
+		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-85.7192" y1="-1070.1299" x2="-23.0562" y2="-1070.1299" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#FDFDFD"/>
+		<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
+		<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
+		<stop  offset="1" style="stop-color:#CFD1D1"/>
+	</linearGradient>
+	<path fill="url(#SVGID_1_)" d="M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454
+		c-2.648,0.82-6.324,0.744-9.518,0.075c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815
+		c-1.766,6.615,7.138,8.572,10.937,7.701c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57
+		c-0.52-1.012-0.229-2.446,0.583-3.126c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463
+		c-1.731-0.813-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
+	
+		<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="334.3203" y1="-357.2158" x2="326.0467" y2="-357.2158" gradientTransform="matrix(1 0 0 -1 -302 -310)">
+		<stop  offset="0" style="stop-color:#E6E6E6"/>
+		<stop  offset="1" style="stop-color:#B2B3B3"/>
+	</linearGradient>
+	<path fill="url(#SVGID_2_)" d="M26.991,32.645c0,4.983,0.741,22.798,4.538,30.405l-8.734-0.194V31.383L26.991,32.645z"/>
+	
+		<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-58.8633" y1="-1076.7139" x2="-51.863" y2="-1057.2131" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#F6F6F6"/>
+		<stop  offset="1" style="stop-color:#B2B3B3"/>
+	</linearGradient>
+	<path fill="url(#SVGID_3_)" d="M7.364,44.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
+		c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
+		c-0.189,1.293-1.134,1.873-2.382,2.379c-18.519,7.52-15.394-5.307-21.352-9.48c-3.158-2.214-7.733-2.09-11.247-0.812
+		c-3.171,1.153-6.437,0.864-9.833-0.396C9.134,32.105,5.326,33.217,7.364,44.396z"/>
+	<line fill="none" stroke="#FFFFFF" stroke-width="3.5" stroke-miterlimit="10" x1="24.634" y1="63.161" x2="24.634" y2="31.938"/>
+	<g opacity="0.75">
+		<path fill="#FFFFFF" d="M31.691,30.336c2.719,0,4.941,0.747,6.795,2.284c5.541,4.592,10.63,6.823,15.557,6.823
+			c1.473,0,2.934-0.208,4.373-0.615c-0.317,0.854-0.559,1.602-0.714,2.111c-0.432,1.414-1.598,1.811-4.357,2.437
+			c-1.463,0.332-3.121,0.708-4.656,1.513c-1.577,0.824-2.536,2.322-2.503,3.908c0.032,1.51,0.928,2.822,2.396,3.514
+			c1.153,0.541,1.478,1.135,1.487,1.373c0.012,0.26-0.343,0.487-0.45,0.551c-0.597,0.348-1.181,0.412-2.051,0.412
+			c-0.16,0-0.321-0.002-0.482-0.004c-0.179-0.002-0.356-0.004-0.535-0.004c-1.632,0-3.393,0.211-5.219,1.74
+			c-1.545,1.294-2.019,3.742-1.078,5.573c0.137,0.267,0.141,0.405,0.149,0.407c-0.093,0.127-0.771,0.565-2.586,0.565
+			c-1.776,0-4.107-0.426-6.741-1.229c-2.005-0.612-4.512-0.924-7.451-0.924c-3.827,0-8.428,0.554-12.624,1.516
+			c-0.412,0.094-0.934,0.145-1.509,0.145c-1.875,0-4.187-0.543-5.673-1.595c1.674-0.011,3.264-0.886,4.366-2.403
+			c1.341-1.845,3.15-6.289,0.213-15.33l-0.081-0.25c-1.278-3.937-2.87-8.833-1.541-10.664c0.508-0.699,1.636-1.053,3.354-1.053
+			c1.188,0,2.632,0.177,4.295,0.525c1.76,0.369,3.618,0.563,5.375,0.563c1.944,0,3.676-0.231,5.144-0.686
+			C26.608,31.021,29.12,30.336,31.691,30.336 M31.691,28.336c-2.663,0-5.243,0.641-7.34,1.29c-1.324,0.41-2.904,0.596-4.553,0.596
+			s-3.367-0.187-4.965-0.521c-1.854-0.389-3.409-0.568-4.704-0.568c-8.474,0-5.881,7.664-3.635,14.583
+			C9.87,54.109,6.821,58.833,3.786,58.833c-1.241,0-2.479-0.789-3.276-2.302c-1.506,5.643,4.751,7.896,8.98,7.896
+			c0.729,0,1.397-0.067,1.956-0.194c3.684-0.844,8.134-1.463,12.177-1.463c2.549,0,4.936,0.246,6.866,0.836
+			c3.037,0.931,5.472,1.318,7.326,1.318c3.975,0,5.295-1.785,4.216-3.888c-0.52-1.013-0.229-2.446,0.583-3.126
+			c1.375-1.152,2.663-1.274,3.935-1.274c0.34,0,0.679,0.009,1.018,0.009c1.005,0,2.011-0.076,3.055-0.682
+			c2.108-1.227,2.077-3.927-1.19-5.463c-1.731-0.814-1.649-2.881,0.184-3.84c3.73-1.952,8.75-1.036,10-5.139
+			c0.448-1.472,1.7-5.161,3.33-7.083c-2.906,2.017-5.857,3.005-8.902,3.005c-4.504,0-9.211-2.163-14.28-6.364
+			C37.275,29.019,34.439,28.336,31.691,28.336L31.691,28.336z M62.944,34.438h0.005H62.944z"/>
+	</g>
+	<path fill="none" stroke="#034672" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+		M62.944,34.438c-7.205,5-14.688,3.682-23.183-3.358c-4.897-4.059-11.15-2.771-15.411-1.454c-2.648,0.82-6.324,0.744-9.518,0.075
+		c-13.978-2.93-10.929,6.038-8.339,14.015c4.757,14.64-3.236,18.031-5.983,12.815c-1.766,6.615,7.138,8.572,10.937,7.701
+		c6.006-1.377,14.051-2.153,19.043-0.627c9.544,2.916,13.125,0.513,11.542-2.57c-0.52-1.012-0.229-2.446,0.583-3.126
+		c2.834-2.374,5.295-0.373,8.007-1.947c2.108-1.226,2.077-3.927-1.19-5.463c-1.731-0.813-1.649-2.881,0.184-3.84
+		c3.73-1.952,8.75-1.036,10-5.138C60.063,40.052,61.315,36.362,62.944,34.438z"/>
+	<path fill="#034672" d="M7.364,43.396c-2.762-7.458-6.509-16.625,7.469-13.695c3.193,0.669,6.869,0.745,9.518-0.075
+		c4.261-1.317,9.972-2.444,14.514,1.521c8.875,7.748,16.875,8.292,24.08,3.292c-1.63,1.924-3.106,5.563-3.33,7.083
+		c-0.189,1.293-1.116,1.916-2.382,2.379c-13.119,4.795-14.124-5.485-20.082-9.665c-3.158-2.214-9.003-1.908-12.517-0.63
+		c-3.171,1.153-6.437,0.864-9.833-0.396C9.134,31.105,5.326,32.217,7.364,43.396z"/>
+	<path fill="#FFFFFF" d="M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881
+		c-2.096,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34
+		c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161
+		h0.68c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
+		c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
+		c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
+	
+		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-75.9038" y1="-1064.3447" x2="-45.0681" y2="-1056.6775" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#B8D7E9"/>
+		<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+		<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
+		<stop  offset="1" style="stop-color:#DFEEF9"/>
+	</linearGradient>
+	<path fill="url(#SVGID_4_)" d="M29.615,8.753c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881v69.29
+		l4.819-4.936v-34.16c0,0,0-1.5,0-2.062c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161
+		c0-2.139,0.778-2.969,1.762-3.468c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521
+		C33.339,10.79,30.42,9.207,29.615,8.753z"/>
+	
+		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-72.9458" y1="-1040.1738" x2="-64.3205" y2="-1082.4258" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#F1F9FE"/>
+		<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+		<stop  offset="1" style="stop-color:#E4F3FD"/>
+	</linearGradient>
+	<path fill="url(#SVGID_5_)" d="M19.717,3.808c-2.097,0-4.014,1.428-4.819,1.881c-0.805,0.452-4.027,2.471-5.079,3.064
+		c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521c0,2.843,1.597,4.979,4.479,6.44
+		c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68c0.625,0,0.965,0.235,0.965,1.256
+		c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l0.862-0.883L19.717,3.808L19.717,3.808z"/>
+	<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M19.427,3.808c1.908,0.938,3.431,1.966,4.236,2.419
+		c0.805,0.452,4.027,2.471,5.079,3.064c0.805,0.454,3.724,2.037,3.724,6.34c0,1.309,0,2.806,0,3.762c0,2.843-1.597,4.979-4.479,6.44
+		c-0.983,0.499-1.762,1.431-1.762,3.569v1.238"/>
+	<path fill="none" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M29.615,8.753
+		c-1.052-0.594-4.274-2.612-5.079-3.064c-0.806-0.453-2.723-1.881-4.819-1.881c-2.096,0-4.014,1.428-4.819,1.881
+		c-0.805,0.452-4.027,2.471-5.079,3.064c-0.805,0.454-3.724,2.037-3.724,6.34c0,1.309,0,3.564,0,4.521
+		c0,2.843,1.597,4.979,4.479,6.44c0.983,0.499,1.762,1.329,1.762,3.468c0,0.943,0.352,1.161,0.918,1.161h0.68
+		c0.625,0,0.965,0.235,0.965,1.256c0,0.562,0,2.062,0,2.062v37.2l2.713,2.779h1.244l5.682-5.819v-34.16c0,0,0-1.5,0-2.062
+		c0-1.021,0.34-1.256,0.965-1.256h0.68c0.566,0,0.918-0.218,0.918-1.161c0-2.139,0.778-2.969,1.762-3.468
+		c2.882-1.462,4.479-3.598,4.479-6.44c0-0.956,0-3.212,0-4.521C33.339,10.79,30.42,9.207,29.615,8.753z"/>
+	<path fill="#E9F6FE" stroke="#034672" stroke-width="2" stroke-miterlimit="10" d="M34.536,34.001"/>
+	<g>
+		
+			<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="35.5122" y1="-1053" x2="35.5122" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_6_)" d="M127.54,48.914h-11.599c0.303,2.346,1.01,3.92,2.117,4.725s2.943,1.205,5.506,1.205
+			c3.432,0,7.43-0.238,11.99-0.717l0.912,5.994c-3.346,1.607-8.015,2.411-14.01,2.411c-6.038,0-10.339-1.304-12.901-3.909
+			c-2.563-2.607-3.845-6.907-3.845-12.902c0-6.299,1.248-10.707,3.746-13.228c2.498-2.519,6.701-3.779,12.609-3.779
+			c5.344,0,9.209,0.923,11.599,2.769c2.389,1.848,3.605,4.66,3.649,8.439c0,2.997-0.771,5.245-2.313,6.744
+			C133.459,48.164,130.971,48.914,127.54,48.914z M115.746,43.114h9.122c1.173,0,1.966-0.282,2.378-0.847
+			c0.413-0.564,0.619-1.394,0.619-2.479c0-1.52-0.391-2.574-1.172-3.16c-0.782-0.586-2.216-0.88-4.301-0.88
+			c-2.477,0-4.171,0.489-5.083,1.466C116.397,38.195,115.876,40.16,115.746,43.114z"/>
+		
+			<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="69.1362" y1="-1053" x2="69.1362" y2="-1103.8832" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_7_)" d="M172.957,29.626l-11.402,32.581c-0.609,1.736-1.359,3.344-2.248,4.82
+			c-0.892,1.478-2.031,2.897-3.422,4.27c-1.391,1.368-3.117,2.378-5.18,3.029c-2.064,0.652-4.355,0.824-6.875,0.521l-0.781-5.672
+			c2.605-0.693,4.647-1.597,6.125-2.701c1.477-1.107,2.627-2.599,3.453-4.466l0.131-0.262h-1.825c-1.607,0-2.649-0.781-3.128-2.349
+			l-10.49-29.775h10.295l5.995,20.786c0.391,1.521,0.717,3.128,0.978,4.819h0.847c0.13-0.521,0.347-1.336,0.651-2.44
+			c0.304-1.104,0.521-1.897,0.652-2.379l5.93-20.786L172.957,29.626L172.957,29.626z"/>
+		
+			<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="100.2241" y1="-1053" x2="100.2241" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_8_)" d="M199.644,54.127l0.851,6.256c-3.306,1.434-7.451,2.149-12.446,2.149
+			c-5.906,0-10.064-1.271-12.479-3.812c-2.411-2.541-3.615-6.896-3.615-13.062c0-6.215,1.216-10.59,3.646-13.131
+			c2.436-2.541,6.625-3.812,12.575-3.812c4.865,0,8.818,0.674,11.859,2.021l-1.042,5.994c-4.692-0.086-7.756-0.131-9.188-0.131
+			c-2.953,0-4.984,0.631-6.093,1.891c-1.106,1.26-1.662,3.646-1.662,7.168c0,3.518,0.556,5.906,1.662,7.167s3.14,1.89,6.093,1.89
+			C193.583,54.713,196.862,54.518,199.644,54.127z"/>
+		
+			<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="150.9712" y1="-1053" x2="150.9712" y2="-1103.886" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_9_)" d="M237.004,28.714c5.996,0,10.241,1.293,12.74,3.877c2.497,2.585,3.746,6.962,3.746,13.13
+			c0,6.17-1.249,10.523-3.746,13.064c-2.499,2.542-6.744,3.812-12.74,3.812c-6.038,0-10.308-1.271-12.804-3.812
+			c-2.499-2.541-3.747-6.896-3.747-13.064c0-6.211,1.248-10.599,3.747-13.162C226.696,29.996,230.966,28.714,237.004,28.714z
+			 M237.004,35.947c-2.562,0-4.278,0.65-5.146,1.954c-0.871,1.304-1.305,3.91-1.305,7.82c0,3.822,0.434,6.385,1.305,7.688
+			c0.867,1.303,2.584,1.955,5.146,1.955c2.478,0,4.16-0.652,5.052-1.955c0.889-1.304,1.336-3.866,1.336-7.688
+			c0-3.865-0.437-6.462-1.305-7.788C241.218,36.609,239.522,35.947,237.004,35.947z"/>
+		
+			<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="184.8789" y1="-1053" x2="184.8789" y2="-1103.885" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_10_)" d="M257.883,36.794l-0.911-6.517c5.776-1.043,11.358-1.563,16.745-1.563
+			c4.345,0,7.537,0.88,9.578,2.64c2.043,1.759,3.063,4.811,3.063,9.154V61.75h-7.625l-0.979-4.887
+			c-3.217,3.779-7.168,5.669-11.857,5.669c-3.086,0-5.604-0.814-7.561-2.443s-2.936-3.897-2.936-6.81v-3.258
+			c0-2.562,0.869-4.562,2.607-5.994c1.735-1.437,4.146-2.15,7.23-2.15h11.47v-1.434c-0.045-1.65-0.424-2.759-1.142-3.324
+			c-0.717-0.563-2.097-0.847-4.14-0.847C267.873,36.272,263.356,36.447,257.883,36.794z M264.92,50.738v1.238
+			c0,2.215,1.261,3.319,3.779,3.319c2.606,0,5.278-1.042,8.016-3.127v-4.496h-8.666C265.963,47.719,264.92,48.74,264.92,50.738z"/>
+		
+			<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="5.9375" y1="-1053" x2="5.9375" y2="-1103.882" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_11_)" d="M98.519,47.415c-0.913-1.563-1.912-2.714-2.997-3.454v-0.13c1.303-0.868,2.302-1.89,2.997-3.062
+			l8.341-11.146H96.043l-7.95,11.208h-2.997c0.303-1.781,0.455-3.736,0.455-5.865v-18.83h-2.992l-6.651,9.482v36.13h9.644V51.648
+			c0-1.26-0.152-2.866-0.455-4.821h3.062L97.15,61.75h10.816L98.519,47.415z"/>
+		
+			<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="125.3193" y1="-1053" x2="125.3193" y2="-1103.884" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_12_)" d="M218.679,54.518h-2.607c-2.434,0-3.646-1.086-3.646-3.258V16.138h-3.014l-6.563,9.36V53.67
+			c0,2.824,0.823,5.008,2.477,6.549c1.65,1.542,3.91,2.313,6.777,2.313c3.475,0,6.035-0.435,7.688-1.304L218.679,54.518z"/>
+		
+			<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="220.1055" y1="-1053" x2="220.1055" y2="-1103.882" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+			<stop  offset="0" style="stop-color:#FFFFFE"/>
+			<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+			<stop  offset="1" style="stop-color:#E9E7E8"/>
+		</linearGradient>
+		<path fill="url(#SVGID_13_)" d="M312.684,47.415c-0.909-1.563-1.909-2.714-2.998-3.454v-0.13c1.306-0.868,2.306-1.89,2.998-3.062
+			l8.343-11.146H310.21l-7.949,11.208h-2.996c0.303-1.781,0.455-3.736,0.455-5.865v-18.83h-2.99l-6.651,9.484V61.75h9.646v-10.1
+			c0-1.26-0.154-2.867-0.457-4.822h3.062l8.992,14.922h10.813L312.684,47.415z"/>
+	</g>
+	
+		<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-66.2808" y1="-1035.334" x2="-66.2808" y2="-1045.5018" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#00639A"/>
+		<stop  offset="0.2355" style="stop-color:#00578A"/>
+		<stop  offset="0.507" style="stop-color:#004D7B"/>
+		<stop  offset="0.7167" style="stop-color:#004773"/>
+		<stop  offset="1" style="stop-color:#00446E"/>
+	</linearGradient>
+	<polygon fill="url(#SVGID_14_)" points="19.719,13.729 10.667,11.704 9.667,15.443 19.719,20.501 29.771,15.443 28.771,11.704 	"/>
+	<polyline opacity="0.2" enable-background="new    " points="19.719,20.501 29.771,15.443 28.771,11.704 19.719,13.729 	"/>
+	<path fill="#034672" d="M14.801,33.209c3.396,1.261,6.662,1.55,9.833,0.396l-0.283-2.223c-2.648,0.82-6.324,0.744-9.518,0.075
+		L14.801,33.209z"/>
+	<path fill="#034672" d="M19.446,32.856c-0.403,2.757,1.896,4.707,1.896,7.619C25.191,36.14,20.269,34.678,19.446,32.856z"/>
+	<path fill="#034672" d="M19.399,33.043c-0.118,3.207-0.402,5.581-1.741,7.247C15.239,35.553,18.345,33.97,19.399,33.043z"/>
+	<circle fill="#034672" cx="19.427" cy="33.021" r="1.594"/>
+	
+		<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-55.5112" y1="-1087.1055" x2="-55.5112" y2="-1087.1055" gradientTransform="matrix(1 0 0 -1 86 -1023.5)">
+		<stop  offset="0" style="stop-color:#F6F6F6"/>
+		<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
+		<stop  offset="1" style="stop-color:#DADADA"/>
+	</linearGradient>
+	<path fill="url(#SVGID_15_)" d="M30.489,63.605"/>
+</g>
+</svg>
diff --git a/misc/logo/logo-small-blue.svg b/misc/logo/logo-small-blue.svg
index 0407792..53b97d5 100644
--- a/misc/logo/logo-small-blue.svg
+++ b/misc/logo/logo-small-blue.svg
@@ -1,160 +1,160 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="160.651px" height="36.438px" viewBox="0 0 160.651 36.438" enable-background="new 0 0 160.651 36.438"
-	 xml:space="preserve">
-<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0.6514" y1="22.168" x2="32.1816" y2="22.168">
-	<stop  offset="0" style="stop-color:#FDFDFD"/>
-	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
-	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
-	<stop  offset="1" style="stop-color:#CFD1D1"/>
-</linearGradient>
-<path fill="url(#SVGID_1_)" d="M32.182,16.033c-3.625,2.516-7.391,1.853-11.665-1.69c-2.464-2.042-5.61-1.395-7.754-0.731
-	c-1.333,0.413-3.183,0.375-4.789,0.038c-7.033-1.474-5.499,3.039-4.196,7.052c2.393,7.367-1.629,9.073-3.011,6.448
-	c-0.889,3.329,3.591,4.313,5.503,3.875c3.021-0.693,7.069-1.083,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293
-	c-0.262-0.509-0.115-1.231,0.293-1.573c1.426-1.194,2.664-0.188,4.029-0.98c1.061-0.617,1.045-1.976-0.6-2.749
-	c-0.871-0.41-0.83-1.45,0.093-1.932c1.877-0.982,4.402-0.521,5.031-2.585C30.731,18.858,31.361,17.001,32.182,16.033z"/>
-<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-	M32.182,16.033c-3.625,2.516-7.391,1.853-11.665-1.69c-2.464-2.042-5.61-1.395-7.754-0.731c-1.333,0.413-3.183,0.375-4.789,0.038
-	c-7.033-1.474-5.499,3.039-4.196,7.052c2.393,7.367-1.629,9.073-3.011,6.448c-0.889,3.329,3.591,4.313,5.503,3.875
-	c3.021-0.693,7.069-1.083,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
-	c1.426-1.194,2.664-0.188,4.029-0.98c1.061-0.617,1.045-1.976-0.6-2.749c-0.871-0.41-0.83-1.45,0.093-1.932
-	c1.877-0.982,4.402-0.521,5.031-2.585C30.731,18.858,31.361,17.001,32.182,16.033z"/>
-<path fill="#034672" d="M4.215,20.541c-1.39-3.752-3.274-8.366,3.759-6.892c1.606,0.337,3.456,0.375,4.789-0.038
-	c2.144-0.663,5.018-1.23,7.303,0.765c4.466,3.898,8.491,4.172,12.116,1.656c-0.82,0.968-1.562,2.799-1.676,3.564
-	c-0.095,0.651-0.562,0.964-1.198,1.197c-6.602,2.412-7.106-2.762-10.104-4.863c-1.59-1.114-4.53-0.96-6.299-0.317
-	c-1.595,0.58-3.238,0.435-4.947-0.2C5.105,14.356,3.189,14.916,4.215,20.541z"/>
-<path fill="#FFFFFF" d="M15.411,3.109c-0.529-0.299-2.15-1.314-2.556-1.542c-0.405-0.228-1.37-0.946-2.425-0.946
-	s-2.02,0.718-2.425,0.946C7.601,1.794,5.979,2.81,5.45,3.109c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275
-	c0,1.43,0.804,2.505,2.254,3.241c0.494,0.251,0.886,0.668,0.886,1.745c0,0.475,0.178,0.584,0.462,0.584h0.343
-	c0.314,0,0.485,0.118,0.485,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626l2.858-2.928V15.813c0,0,0-0.754,0-1.038
-	c0-0.514,0.171-0.632,0.485-0.632h0.343c0.284,0,0.462-0.11,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
-	c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275C17.285,4.134,15.816,3.337,15.411,3.109z"/>
-<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="5.1582" y1="19.2568" x2="20.673" y2="15.3991">
-	<stop  offset="0" style="stop-color:#B8D7E9"/>
-	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
-	<stop  offset="1" style="stop-color:#DFEEF9"/>
-</linearGradient>
-<path fill="url(#SVGID_2_)" d="M14.98,3.109c-0.529-0.299-2.15-1.314-2.556-1.542C12.02,1.339,11.055,0.621,10,0.621v34.865
-	l2.425-2.483V15.813c0,0,0-0.754,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.343c0.284,0,0.462-0.11,0.462-0.584
-	c0-1.076,0.392-1.494,0.886-1.745c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275
-	C16.854,4.134,15.386,3.337,14.98,3.109z"/>
-<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="7.0781" y1="7.0952" x2="11.418" y2="28.3545">
-	<stop  offset="0" style="stop-color:#F1F9FE"/>
-	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-	<stop  offset="1" style="stop-color:#E4F3FD"/>
-</linearGradient>
-<path fill="url(#SVGID_3_)" d="M10.431,0.621c-1.055,0-2.02,0.718-2.425,0.946C7.601,1.794,5.979,2.81,5.45,3.109
-	c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275c0,1.43,0.804,2.505,2.254,3.241c0.494,0.251,0.886,0.668,0.886,1.745
-	c0,0.475,0.178,0.584,0.462,0.584h0.343c0.314,0,0.485,0.118,0.485,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626
-	l0.434-0.445V0.621z"/>
-<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M15.411,3.109
-	c-0.529-0.299-2.15-1.314-2.556-1.542c-0.405-0.228-1.37-0.946-2.425-0.946s-2.02,0.718-2.425,0.946
-	C7.601,1.794,5.979,2.81,5.45,3.109c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275c0,1.43,0.804,2.505,2.254,3.241
-	c0.494,0.251,0.886,0.668,0.886,1.745c0,0.475,0.178,0.584,0.462,0.584h0.343c0.314,0,0.485,0.118,0.485,0.632
-	c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626l2.858-2.928V15.813c0,0,0-0.754,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.343
-	c0.284,0,0.462-0.11,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275
-	C17.285,4.134,15.816,3.337,15.411,3.109z"/>
-<path fill="#E9F6FE" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M17.888,15.813"/>
-<g>
-	<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="59.7051" y1="6.7554" x2="59.7051" y2="34.6039">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_4_)" d="M62.737,23.317h-5.836c0.152,1.181,0.508,1.973,1.065,2.377c0.557,0.405,1.48,0.607,2.771,0.607
-		c1.727,0,3.738-0.12,6.033-0.361l0.459,3.016c-1.684,0.809-4.033,1.213-7.05,1.213c-3.038,0-5.202-0.656-6.491-1.967
-		c-1.29-1.312-1.935-3.476-1.935-6.492c0-3.169,0.628-5.388,1.885-6.656c1.257-1.268,3.372-1.902,6.345-1.902
-		c2.688,0,4.634,0.464,5.836,1.393c1.202,0.93,1.814,2.345,1.836,4.247c0,1.508-0.388,2.639-1.164,3.394
-		C65.716,22.94,64.464,23.317,62.737,23.317z M56.803,20.399h4.59c0.591,0,0.989-0.142,1.197-0.426
-		c0.208-0.284,0.312-0.7,0.312-1.246c0-0.765-0.197-1.295-0.59-1.59c-0.394-0.295-1.115-0.443-2.164-0.443
-		c-1.246,0-2.099,0.246-2.558,0.737C57.131,17.924,56.868,18.912,56.803,20.399z"/>
-	<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="76.623" y1="6.7559" x2="76.623" y2="34.6041">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_5_)" d="M85.59,13.612l-5.737,16.394c-0.307,0.874-0.684,1.683-1.131,2.426
-		c-0.448,0.743-1.022,1.459-1.722,2.148c-0.7,0.688-1.568,1.197-2.606,1.524c-1.039,0.328-2.191,0.415-3.459,0.262l-0.394-2.853
-		c1.312-0.35,2.339-0.803,3.082-1.36c0.743-0.558,1.322-1.306,1.737-2.246l0.066-0.132h-0.919c-0.809,0-1.333-0.393-1.573-1.18
-		l-5.279-14.984h5.181l3.017,10.459c0.196,0.766,0.36,1.574,0.492,2.427h0.426c0.065-0.263,0.174-0.672,0.327-1.229
-		c0.153-0.558,0.263-0.957,0.329-1.197l2.983-10.459H85.59z"/>
-	<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="92.2637" y1="6.7554" x2="92.2637" y2="34.6039">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_6_)" d="M99.019,25.94l0.426,3.148c-1.661,0.721-3.749,1.082-6.263,1.082c-2.973,0-5.065-0.639-6.278-1.918
-		c-1.214-1.278-1.819-3.47-1.819-6.574c0-3.126,0.611-5.329,1.835-6.607c1.225-1.279,3.334-1.918,6.328-1.918
-		c2.448,0,4.438,0.339,5.968,1.017l-0.524,3.016c-2.361-0.043-3.902-0.066-4.623-0.066c-1.486,0-2.509,0.317-3.065,0.952
-		c-0.558,0.634-0.837,1.835-0.837,3.606c0,1.77,0.279,2.973,0.837,3.606c0.557,0.634,1.579,0.951,3.065,0.951
-		C95.969,26.235,97.619,26.137,99.019,25.94z"/>
-	<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="117.8008" y1="6.7554" x2="117.8008" y2="34.6036">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_7_)" d="M117.817,13.153c3.017,0,5.152,0.65,6.41,1.951c1.257,1.301,1.885,3.503,1.885,6.607
-		c0,3.104-0.628,5.295-1.885,6.574c-1.258,1.279-3.394,1.918-6.41,1.918c-3.038,0-5.187-0.639-6.442-1.918
-		c-1.258-1.279-1.886-3.47-1.886-6.574c0-3.125,0.628-5.333,1.886-6.623C112.631,13.798,114.779,13.153,117.817,13.153z
-		 M117.817,16.792c-1.29,0-2.153,0.327-2.59,0.983c-0.438,0.656-0.656,1.967-0.656,3.935c0,1.924,0.219,3.213,0.656,3.869
-		c0.437,0.655,1.3,0.983,2.59,0.983c1.246,0,2.093-0.328,2.541-0.983c0.447-0.656,0.672-1.945,0.672-3.869
-		c0-1.945-0.219-3.251-0.655-3.918C119.938,17.125,119.085,16.792,117.817,16.792z"/>
-	<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="134.8643" y1="6.7554" x2="134.8643" y2="34.6039">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_8_)" d="M128.323,17.219l-0.459-3.279c2.906-0.525,5.716-0.787,8.426-0.787c2.186,0,3.793,0.443,4.819,1.328
-		c1.028,0.885,1.542,2.42,1.542,4.606v10.688h-3.837l-0.491-2.459c-1.618,1.902-3.606,2.853-5.967,2.853
-		c-1.553,0-2.821-0.41-3.804-1.229c-0.983-0.819-1.476-1.961-1.476-3.426v-1.639c0-1.29,0.437-2.295,1.312-3.016
-		c0.874-0.722,2.088-1.082,3.64-1.082h5.771v-0.722c-0.022-0.83-0.214-1.388-0.574-1.672c-0.36-0.284-1.055-0.426-2.082-0.426
-		C133.35,16.956,131.077,17.044,128.323,17.219z M131.863,24.235v0.623c0,1.115,0.635,1.672,1.902,1.672
-		c1.312,0,2.656-0.524,4.033-1.573v-2.263h-4.36C132.389,22.716,131.863,23.229,131.863,24.235z"/>
-	<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="44.8223" y1="6.7554" x2="44.8223" y2="34.6041">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_9_)" d="M48.135,22.563c-0.46-0.787-0.962-1.366-1.509-1.738v-0.065c0.656-0.437,1.158-0.951,1.509-1.541
-		l4.196-5.606h-5.442l-4,5.64h-1.508c0.152-0.896,0.229-1.88,0.229-2.951V6.825h-1.506l-3.347,4.771v18.18h4.853v-5.082
-		c0-0.634-0.076-1.442-0.229-2.426h1.541l4.524,7.508h5.442L48.135,22.563z"/>
-	<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="104.8906" y1="6.7554" x2="104.8906" y2="34.604">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_10_)" d="M108.596,26.137h-1.312c-1.225,0-1.836-0.546-1.836-1.639V6.825h-1.517l-3.303,4.71V25.71
-		c0,1.421,0.415,2.52,1.245,3.295c0.83,0.776,1.968,1.164,3.41,1.164c1.748,0,3.038-0.219,3.869-0.656L108.596,26.137z"/>
-	<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="152.5859" y1="6.7554" x2="152.5859" y2="34.6041">
-		<stop  offset="0" style="stop-color:#035E93"/>
-		<stop  offset="0.5912" style="stop-color:#014A77"/>
-		<stop  offset="1" style="stop-color:#004068"/>
-	</linearGradient>
-	<path fill="url(#SVGID_11_)" d="M155.897,22.563c-0.459-0.787-0.962-1.366-1.509-1.738v-0.065c0.655-0.437,1.159-0.951,1.509-1.541
-		l4.196-5.606h-5.442l-4,5.64h-1.509c0.152-0.896,0.23-1.88,0.23-2.951V6.825h-1.506l-3.348,4.772v18.179h4.854v-5.082
-		c0-0.634-0.078-1.442-0.23-2.426h1.541l4.524,7.508h5.443L155.897,22.563z"/>
-</g>
-<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="10.4316" y1="4.6587" x2="10.4316" y2="9.7754">
-	<stop  offset="0" style="stop-color:#00639A"/>
-	<stop  offset="0.2355" style="stop-color:#00578A"/>
-	<stop  offset="0.507" style="stop-color:#004D7B"/>
-	<stop  offset="0.7167" style="stop-color:#004773"/>
-	<stop  offset="1" style="stop-color:#00446E"/>
-</linearGradient>
-<polygon fill="url(#SVGID_12_)" points="10.432,5.613 5.877,4.594 5.374,6.476 10.432,9.021 15.489,6.476 14.986,4.594 "/>
-<polyline opacity="0.2" points="10.432,9.021 15.489,6.476 14.986,4.594 10.432,5.613 "/>
-<path fill="#034672" d="M7.957,15.415c1.709,0.634,3.353,0.78,4.947,0.2l-0.142-1.119c-1.333,0.413-3.183,0.375-4.789,0.038
-	L7.957,15.415z"/>
-<path fill="#034672" d="M10.295,15.237c-0.203,1.387,0.954,2.369,0.953,3.834C13.185,16.889,10.708,16.154,10.295,15.237z"/>
-<path fill="#034672" d="M10.271,15.331c-0.06,1.614-0.202,2.808-0.876,3.646C8.178,16.594,9.74,15.797,10.271,15.331z"/>
-<circle fill="#034672" cx="10.285" cy="15.32" r="0.802"/>
-<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="15.8525" y1="30.71" x2="15.8525" y2="30.71">
-	<stop  offset="0" style="stop-color:#F6F6F6"/>
-	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
-	<stop  offset="1" style="stop-color:#DADADA"/>
-</linearGradient>
-<path fill="url(#SVGID_13_)" d="M15.852,30.709"/>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="160.651px" height="36.438px" viewBox="0 0 160.651 36.438" enable-background="new 0 0 160.651 36.438"
+	 xml:space="preserve">
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0.6514" y1="22.168" x2="32.1816" y2="22.168">
+	<stop  offset="0" style="stop-color:#FDFDFD"/>
+	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
+	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
+	<stop  offset="1" style="stop-color:#CFD1D1"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M32.182,16.033c-3.625,2.516-7.391,1.853-11.665-1.69c-2.464-2.042-5.61-1.395-7.754-0.731
+	c-1.333,0.413-3.183,0.375-4.789,0.038c-7.033-1.474-5.499,3.039-4.196,7.052c2.393,7.367-1.629,9.073-3.011,6.448
+	c-0.889,3.329,3.591,4.313,5.503,3.875c3.021-0.693,7.069-1.083,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293
+	c-0.262-0.509-0.115-1.231,0.293-1.573c1.426-1.194,2.664-0.188,4.029-0.98c1.061-0.617,1.045-1.976-0.6-2.749
+	c-0.871-0.41-0.83-1.45,0.093-1.932c1.877-0.982,4.402-0.521,5.031-2.585C30.731,18.858,31.361,17.001,32.182,16.033z"/>
+<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+	M32.182,16.033c-3.625,2.516-7.391,1.853-11.665-1.69c-2.464-2.042-5.61-1.395-7.754-0.731c-1.333,0.413-3.183,0.375-4.789,0.038
+	c-7.033-1.474-5.499,3.039-4.196,7.052c2.393,7.367-1.629,9.073-3.011,6.448c-0.889,3.329,3.591,4.313,5.503,3.875
+	c3.021-0.693,7.069-1.083,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
+	c1.426-1.194,2.664-0.188,4.029-0.98c1.061-0.617,1.045-1.976-0.6-2.749c-0.871-0.41-0.83-1.45,0.093-1.932
+	c1.877-0.982,4.402-0.521,5.031-2.585C30.731,18.858,31.361,17.001,32.182,16.033z"/>
+<path fill="#034672" d="M4.215,20.541c-1.39-3.752-3.274-8.366,3.759-6.892c1.606,0.337,3.456,0.375,4.789-0.038
+	c2.144-0.663,5.018-1.23,7.303,0.765c4.466,3.898,8.491,4.172,12.116,1.656c-0.82,0.968-1.562,2.799-1.676,3.564
+	c-0.095,0.651-0.562,0.964-1.198,1.197c-6.602,2.412-7.106-2.762-10.104-4.863c-1.59-1.114-4.53-0.96-6.299-0.317
+	c-1.595,0.58-3.238,0.435-4.947-0.2C5.105,14.356,3.189,14.916,4.215,20.541z"/>
+<path fill="#FFFFFF" d="M15.411,3.109c-0.529-0.299-2.15-1.314-2.556-1.542c-0.405-0.228-1.37-0.946-2.425-0.946
+	s-2.02,0.718-2.425,0.946C7.601,1.794,5.979,2.81,5.45,3.109c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275
+	c0,1.43,0.804,2.505,2.254,3.241c0.494,0.251,0.886,0.668,0.886,1.745c0,0.475,0.178,0.584,0.462,0.584h0.343
+	c0.314,0,0.485,0.118,0.485,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626l2.858-2.928V15.813c0,0,0-0.754,0-1.038
+	c0-0.514,0.171-0.632,0.485-0.632h0.343c0.284,0,0.462-0.11,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
+	c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275C17.285,4.134,15.816,3.337,15.411,3.109z"/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="5.1582" y1="19.2568" x2="20.673" y2="15.3991">
+	<stop  offset="0" style="stop-color:#B8D7E9"/>
+	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
+	<stop  offset="1" style="stop-color:#DFEEF9"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M14.98,3.109c-0.529-0.299-2.15-1.314-2.556-1.542C12.02,1.339,11.055,0.621,10,0.621v34.865
+	l2.425-2.483V15.813c0,0,0-0.754,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.343c0.284,0,0.462-0.11,0.462-0.584
+	c0-1.076,0.392-1.494,0.886-1.745c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275
+	C16.854,4.134,15.386,3.337,14.98,3.109z"/>
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="7.0781" y1="7.0952" x2="11.418" y2="28.3545">
+	<stop  offset="0" style="stop-color:#F1F9FE"/>
+	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+	<stop  offset="1" style="stop-color:#E4F3FD"/>
+</linearGradient>
+<path fill="url(#SVGID_3_)" d="M10.431,0.621c-1.055,0-2.02,0.718-2.425,0.946C7.601,1.794,5.979,2.81,5.45,3.109
+	c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275c0,1.43,0.804,2.505,2.254,3.241c0.494,0.251,0.886,0.668,0.886,1.745
+	c0,0.475,0.178,0.584,0.462,0.584h0.343c0.314,0,0.485,0.118,0.485,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626
+	l0.434-0.445V0.621z"/>
+<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M15.411,3.109
+	c-0.529-0.299-2.15-1.314-2.556-1.542c-0.405-0.228-1.37-0.946-2.425-0.946s-2.02,0.718-2.425,0.946
+	C7.601,1.794,5.979,2.81,5.45,3.109c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.794,0,2.275c0,1.43,0.804,2.505,2.254,3.241
+	c0.494,0.251,0.886,0.668,0.886,1.745c0,0.475,0.178,0.584,0.462,0.584h0.343c0.314,0,0.485,0.118,0.485,0.632
+	c0,0.283,0,1.038,0,1.038v18.718l1.365,1.399h0.626l2.858-2.928V15.813c0,0,0-0.754,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.343
+	c0.284,0,0.462-0.11,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745c1.45-0.736,2.254-1.811,2.254-3.241c0-0.481,0-1.616,0-2.275
+	C17.285,4.134,15.816,3.337,15.411,3.109z"/>
+<path fill="#E9F6FE" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M17.888,15.813"/>
+<g>
+	<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="59.7051" y1="6.7554" x2="59.7051" y2="34.6039">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_4_)" d="M62.737,23.317h-5.836c0.152,1.181,0.508,1.973,1.065,2.377c0.557,0.405,1.48,0.607,2.771,0.607
+		c1.727,0,3.738-0.12,6.033-0.361l0.459,3.016c-1.684,0.809-4.033,1.213-7.05,1.213c-3.038,0-5.202-0.656-6.491-1.967
+		c-1.29-1.312-1.935-3.476-1.935-6.492c0-3.169,0.628-5.388,1.885-6.656c1.257-1.268,3.372-1.902,6.345-1.902
+		c2.688,0,4.634,0.464,5.836,1.393c1.202,0.93,1.814,2.345,1.836,4.247c0,1.508-0.388,2.639-1.164,3.394
+		C65.716,22.94,64.464,23.317,62.737,23.317z M56.803,20.399h4.59c0.591,0,0.989-0.142,1.197-0.426
+		c0.208-0.284,0.312-0.7,0.312-1.246c0-0.765-0.197-1.295-0.59-1.59c-0.394-0.295-1.115-0.443-2.164-0.443
+		c-1.246,0-2.099,0.246-2.558,0.737C57.131,17.924,56.868,18.912,56.803,20.399z"/>
+	<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="76.623" y1="6.7559" x2="76.623" y2="34.6041">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_5_)" d="M85.59,13.612l-5.737,16.394c-0.307,0.874-0.684,1.683-1.131,2.426
+		c-0.448,0.743-1.022,1.459-1.722,2.148c-0.7,0.688-1.568,1.197-2.606,1.524c-1.039,0.328-2.191,0.415-3.459,0.262l-0.394-2.853
+		c1.312-0.35,2.339-0.803,3.082-1.36c0.743-0.558,1.322-1.306,1.737-2.246l0.066-0.132h-0.919c-0.809,0-1.333-0.393-1.573-1.18
+		l-5.279-14.984h5.181l3.017,10.459c0.196,0.766,0.36,1.574,0.492,2.427h0.426c0.065-0.263,0.174-0.672,0.327-1.229
+		c0.153-0.558,0.263-0.957,0.329-1.197l2.983-10.459H85.59z"/>
+	<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="92.2637" y1="6.7554" x2="92.2637" y2="34.6039">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_6_)" d="M99.019,25.94l0.426,3.148c-1.661,0.721-3.749,1.082-6.263,1.082c-2.973,0-5.065-0.639-6.278-1.918
+		c-1.214-1.278-1.819-3.47-1.819-6.574c0-3.126,0.611-5.329,1.835-6.607c1.225-1.279,3.334-1.918,6.328-1.918
+		c2.448,0,4.438,0.339,5.968,1.017l-0.524,3.016c-2.361-0.043-3.902-0.066-4.623-0.066c-1.486,0-2.509,0.317-3.065,0.952
+		c-0.558,0.634-0.837,1.835-0.837,3.606c0,1.77,0.279,2.973,0.837,3.606c0.557,0.634,1.579,0.951,3.065,0.951
+		C95.969,26.235,97.619,26.137,99.019,25.94z"/>
+	<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="117.8008" y1="6.7554" x2="117.8008" y2="34.6036">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_7_)" d="M117.817,13.153c3.017,0,5.152,0.65,6.41,1.951c1.257,1.301,1.885,3.503,1.885,6.607
+		c0,3.104-0.628,5.295-1.885,6.574c-1.258,1.279-3.394,1.918-6.41,1.918c-3.038,0-5.187-0.639-6.442-1.918
+		c-1.258-1.279-1.886-3.47-1.886-6.574c0-3.125,0.628-5.333,1.886-6.623C112.631,13.798,114.779,13.153,117.817,13.153z
+		 M117.817,16.792c-1.29,0-2.153,0.327-2.59,0.983c-0.438,0.656-0.656,1.967-0.656,3.935c0,1.924,0.219,3.213,0.656,3.869
+		c0.437,0.655,1.3,0.983,2.59,0.983c1.246,0,2.093-0.328,2.541-0.983c0.447-0.656,0.672-1.945,0.672-3.869
+		c0-1.945-0.219-3.251-0.655-3.918C119.938,17.125,119.085,16.792,117.817,16.792z"/>
+	<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="134.8643" y1="6.7554" x2="134.8643" y2="34.6039">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_8_)" d="M128.323,17.219l-0.459-3.279c2.906-0.525,5.716-0.787,8.426-0.787c2.186,0,3.793,0.443,4.819,1.328
+		c1.028,0.885,1.542,2.42,1.542,4.606v10.688h-3.837l-0.491-2.459c-1.618,1.902-3.606,2.853-5.967,2.853
+		c-1.553,0-2.821-0.41-3.804-1.229c-0.983-0.819-1.476-1.961-1.476-3.426v-1.639c0-1.29,0.437-2.295,1.312-3.016
+		c0.874-0.722,2.088-1.082,3.64-1.082h5.771v-0.722c-0.022-0.83-0.214-1.388-0.574-1.672c-0.36-0.284-1.055-0.426-2.082-0.426
+		C133.35,16.956,131.077,17.044,128.323,17.219z M131.863,24.235v0.623c0,1.115,0.635,1.672,1.902,1.672
+		c1.312,0,2.656-0.524,4.033-1.573v-2.263h-4.36C132.389,22.716,131.863,23.229,131.863,24.235z"/>
+	<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="44.8223" y1="6.7554" x2="44.8223" y2="34.6041">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_9_)" d="M48.135,22.563c-0.46-0.787-0.962-1.366-1.509-1.738v-0.065c0.656-0.437,1.158-0.951,1.509-1.541
+		l4.196-5.606h-5.442l-4,5.64h-1.508c0.152-0.896,0.229-1.88,0.229-2.951V6.825h-1.506l-3.347,4.771v18.18h4.853v-5.082
+		c0-0.634-0.076-1.442-0.229-2.426h1.541l4.524,7.508h5.442L48.135,22.563z"/>
+	<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="104.8906" y1="6.7554" x2="104.8906" y2="34.604">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_10_)" d="M108.596,26.137h-1.312c-1.225,0-1.836-0.546-1.836-1.639V6.825h-1.517l-3.303,4.71V25.71
+		c0,1.421,0.415,2.52,1.245,3.295c0.83,0.776,1.968,1.164,3.41,1.164c1.748,0,3.038-0.219,3.869-0.656L108.596,26.137z"/>
+	<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="152.5859" y1="6.7554" x2="152.5859" y2="34.6041">
+		<stop  offset="0" style="stop-color:#035E93"/>
+		<stop  offset="0.5912" style="stop-color:#014A77"/>
+		<stop  offset="1" style="stop-color:#004068"/>
+	</linearGradient>
+	<path fill="url(#SVGID_11_)" d="M155.897,22.563c-0.459-0.787-0.962-1.366-1.509-1.738v-0.065c0.655-0.437,1.159-0.951,1.509-1.541
+		l4.196-5.606h-5.442l-4,5.64h-1.509c0.152-0.896,0.23-1.88,0.23-2.951V6.825h-1.506l-3.348,4.772v18.179h4.854v-5.082
+		c0-0.634-0.078-1.442-0.23-2.426h1.541l4.524,7.508h5.443L155.897,22.563z"/>
+</g>
+<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="10.4316" y1="4.6587" x2="10.4316" y2="9.7754">
+	<stop  offset="0" style="stop-color:#00639A"/>
+	<stop  offset="0.2355" style="stop-color:#00578A"/>
+	<stop  offset="0.507" style="stop-color:#004D7B"/>
+	<stop  offset="0.7167" style="stop-color:#004773"/>
+	<stop  offset="1" style="stop-color:#00446E"/>
+</linearGradient>
+<polygon fill="url(#SVGID_12_)" points="10.432,5.613 5.877,4.594 5.374,6.476 10.432,9.021 15.489,6.476 14.986,4.594 "/>
+<polyline opacity="0.2" points="10.432,9.021 15.489,6.476 14.986,4.594 10.432,5.613 "/>
+<path fill="#034672" d="M7.957,15.415c1.709,0.634,3.353,0.78,4.947,0.2l-0.142-1.119c-1.333,0.413-3.183,0.375-4.789,0.038
+	L7.957,15.415z"/>
+<path fill="#034672" d="M10.295,15.237c-0.203,1.387,0.954,2.369,0.953,3.834C13.185,16.889,10.708,16.154,10.295,15.237z"/>
+<path fill="#034672" d="M10.271,15.331c-0.06,1.614-0.202,2.808-0.876,3.646C8.178,16.594,9.74,15.797,10.271,15.331z"/>
+<circle fill="#034672" cx="10.285" cy="15.32" r="0.802"/>
+<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="15.8525" y1="30.71" x2="15.8525" y2="30.71">
+	<stop  offset="0" style="stop-color:#F6F6F6"/>
+	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
+	<stop  offset="1" style="stop-color:#DADADA"/>
+</linearGradient>
+<path fill="url(#SVGID_13_)" d="M15.852,30.709"/>
+</svg>
diff --git a/misc/logo/logo-small-white.svg b/misc/logo/logo-small-white.svg
index 66079ad..34832e3 100644
--- a/misc/logo/logo-small-white.svg
+++ b/misc/logo/logo-small-white.svg
@@ -1,185 +1,185 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="164.254px" height="39.875px" viewBox="-0.104 1.48 164.254 39.875" enable-background="new -0.104 1.48 164.254 39.875"
-	 xml:space="preserve">
-<g>
-	
-		<path fill="none" stroke="#FFFFFF" stroke-width="4.5285" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-		M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732c-1.333,0.413-3.182,0.375-4.789,0.038
-		c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448c-0.889,3.328,3.592,4.312,5.503,3.875
-		c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
-		c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748c-0.871-0.41-0.83-1.45,0.093-1.932
-		c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
-	
-		<path fill="none" stroke="#FFFFFF" stroke-width="4.5285" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-		M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946c-1.055,0-2.02,0.718-2.425,0.946
-		C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275
-		c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584h0.342
-		c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038
-		c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
-		c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275C18.841,7.321,17.372,6.525,16.967,6.296z"/>
-</g>
-<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-277.7925" y1="960.855" x2="-246.2632" y2="960.855" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-	<stop  offset="0" style="stop-color:#FDFDFD"/>
-	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
-	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
-	<stop  offset="1" style="stop-color:#CFD1D1"/>
-</linearGradient>
-<path fill="url(#SVGID_1_)" d="M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732
-	c-1.333,0.413-3.182,0.375-4.789,0.038c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448
-	c-0.889,3.328,3.592,4.312,5.503,3.875c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293
-	c-0.262-0.509-0.115-1.231,0.293-1.573c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748
-	c-0.871-0.41-0.83-1.45,0.093-1.932c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
-<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
-	M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732c-1.333,0.413-3.182,0.375-4.789,0.038
-	c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448c-0.889,3.328,3.592,4.312,5.503,3.875
-	c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
-	c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748c-0.871-0.41-0.83-1.45,0.093-1.932
-	c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
-<path fill="#034672" d="M5.771,23.728c-1.39-3.753-3.275-8.366,3.758-6.891c1.606,0.336,3.456,0.375,4.789-0.038
-	c2.144-0.663,5.018-1.229,7.303,0.765c4.466,3.898,8.491,4.173,12.117,1.657c-0.82,0.968-1.563,2.799-1.676,3.563
-	c-0.095,0.65-0.562,0.963-1.198,1.196c-6.602,2.413-7.107-2.76-10.105-4.863c-1.589-1.114-4.53-0.96-6.298-0.317
-	c-1.595,0.58-3.239,0.435-4.947-0.199C6.661,17.543,4.745,18.103,5.771,23.728z"/>
-<path fill="#FFFFFF" d="M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946
-	c-1.055,0-2.02,0.718-2.425,0.946C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19
-	c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584
-	h0.342c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038
-	c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
-	c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275C18.841,7.321,17.372,6.525,16.967,6.296z"/>
-<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-272.8555" y1="957.9448" x2="-257.3407" y2="954.0872" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-	<stop  offset="0" style="stop-color:#B8D7E9"/>
-	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
-	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
-	<stop  offset="1" style="stop-color:#DFEEF9"/>
-</linearGradient>
-<path fill="url(#SVGID_2_)" d="M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946v34.863
-	l2.425-2.482V19.001c0,0,0-0.755,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584
-	c0-1.076,0.392-1.494,0.887-1.745c1.45-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275
-	C18.841,7.321,17.372,6.525,16.967,6.296z"/>
-<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-271.3652" y1="945.7817" x2="-267.0252" y2="967.042" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-	<stop  offset="0" style="stop-color:#F1F9FE"/>
-	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
-	<stop  offset="1" style="stop-color:#E4F3FD"/>
-</linearGradient>
-<path fill="url(#SVGID_3_)" d="M11.987,3.808c-1.055,0-2.02,0.718-2.425,0.946C9.157,4.982,7.535,5.998,7.006,6.296
-	c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745
-	c0,0.475,0.177,0.584,0.462,0.584h0.342c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626
-	l0.434-0.445L11.987,3.808L11.987,3.808z"/>
-<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M16.967,6.296
-	c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946c-1.055,0-2.02,0.718-2.425,0.946
-	C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24
-	c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584h0.342c0.315,0,0.486,0.118,0.486,0.632
-	c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.342
-	c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275
-	C18.841,7.321,17.372,6.525,16.967,6.296z"/>
-<path fill="#E9F6FE" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M19.443,19"/>
-<g>
-	
-		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-216.7974" y1="952.2349" x2="-216.7974" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_4_)" d="M66.236,26.503H60.4c0.152,1.182,0.508,1.974,1.065,2.377c0.557,0.406,1.481,0.606,2.771,0.606
-		c1.727,0,3.739-0.12,6.033-0.36l0.458,3.016c-1.683,0.809-4.033,1.213-7.049,1.213c-3.038,0-5.202-0.656-6.491-1.967
-		c-1.29-1.312-1.935-3.475-1.935-6.492c0-3.169,0.628-5.387,1.885-6.656c1.257-1.268,3.372-1.902,6.344-1.902
-		c2.689,0,4.634,0.465,5.836,1.394c1.202,0.93,1.814,2.345,1.836,4.246c0,1.508-0.388,2.639-1.164,3.395
-		C69.215,26.126,67.963,26.503,66.236,26.503z M60.302,23.585h4.59c0.59,0,0.989-0.142,1.196-0.426
-		c0.208-0.283,0.312-0.701,0.312-1.248c0-0.765-0.197-1.295-0.59-1.59s-1.115-0.443-2.164-0.443c-1.246,0-2.099,0.246-2.558,0.738
-		C60.63,21.11,60.368,22.099,60.302,23.585z"/>
-	
-		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-199.8774" y1="952.2349" x2="-199.8774" y2="977.8398" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_5_)" d="M89.089,16.799l-5.737,16.394c-0.307,0.874-0.684,1.682-1.131,2.426
-		c-0.449,0.743-1.021,1.457-1.722,2.147c-0.7,0.688-1.568,1.196-2.606,1.524c-1.039,0.328-2.191,0.414-3.459,0.262l-0.393-2.854
-		c1.311-0.35,2.338-0.805,3.082-1.359c0.743-0.557,1.322-1.309,1.737-2.248l0.066-0.131h-0.918c-0.809,0-1.333-0.393-1.574-1.182
-		l-5.278-14.982h5.18l3.017,10.458c0.197,0.766,0.361,1.574,0.492,2.426h0.426c0.065-0.262,0.174-0.672,0.328-1.229
-		c0.153-0.556,0.262-0.955,0.328-1.197l2.984-10.458L89.089,16.799L89.089,16.799z"/>
-	
-		<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-184.2358" y1="952.2349" x2="-184.2358" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_6_)" d="M102.518,29.126l0.428,3.148c-1.663,0.721-3.75,1.082-6.264,1.082c-2.972,0-5.063-0.641-6.279-1.918
-		c-1.213-1.277-1.818-3.471-1.818-6.572c0-3.127,0.611-5.329,1.834-6.607c1.227-1.278,3.333-1.918,6.328-1.918
-		c2.447,0,4.438,0.339,5.967,1.017l-0.523,3.016c-2.361-0.043-3.902-0.066-4.623-0.066c-1.486,0-2.508,0.317-3.066,0.952
-		c-0.557,0.634-0.836,1.834-0.836,3.605c0,1.771,0.279,2.973,0.836,3.606s1.58,0.95,3.066,0.95
-		C99.467,29.421,101.117,29.324,102.518,29.126z"/>
-	
-		<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-158.7007" y1="952.2349" x2="-158.7007" y2="977.8403" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_7_)" d="M121.314,16.34c3.018,0,5.153,0.651,6.412,1.951c1.256,1.301,1.885,3.503,1.885,6.607
-		s-0.629,5.295-1.885,6.573c-1.259,1.278-3.395,1.918-6.412,1.918c-3.037,0-5.187-0.64-6.441-1.918
-		c-1.257-1.278-1.885-3.47-1.885-6.573c0-3.125,0.628-5.333,1.885-6.623C116.129,16.985,118.277,16.34,121.314,16.34z
-		 M121.314,19.979c-1.289,0-2.152,0.327-2.588,0.983c-0.438,0.656-0.658,1.967-0.658,3.935c0,1.923,0.219,3.213,0.658,3.869
-		c0.436,0.655,1.299,0.983,2.588,0.983c1.248,0,2.094-0.328,2.543-0.983c0.447-0.656,0.672-1.946,0.672-3.869
-		c0-1.944-0.219-3.251-0.656-3.918S122.583,19.979,121.314,19.979z"/>
-	
-		<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-141.6396" y1="952.2349" x2="-141.6396" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_8_)" d="M131.82,20.406l-0.457-3.279c2.906-0.525,5.715-0.787,8.425-0.787c2.187,0,3.792,0.443,4.819,1.329
-		c1.029,0.885,1.541,2.421,1.541,4.606v10.688h-3.836l-0.492-2.459c-1.618,1.901-3.606,2.854-5.965,2.854
-		c-1.553,0-2.82-0.41-3.805-1.229c-0.984-0.82-1.478-1.961-1.478-3.426v-1.64c0-1.29,0.438-2.296,1.312-3.017
-		c0.874-0.723,2.086-1.082,3.639-1.082h5.771v-0.721c-0.022-0.83-0.213-1.389-0.575-1.673c-0.359-0.283-1.055-0.426-2.082-0.426
-		C136.848,20.143,134.575,20.231,131.82,20.406z M135.361,27.421v0.623c0,1.115,0.635,1.67,1.902,1.67
-		c1.312,0,2.656-0.523,4.033-1.573v-2.263h-4.359C135.887,25.903,135.361,26.417,135.361,27.421z"/>
-	
-		<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="-231.6772" y1="952.2349" x2="-231.6772" y2="977.837" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_9_)" d="M51.634,25.75c-0.459-0.787-0.962-1.365-1.508-1.737v-0.065c0.656-0.438,1.158-0.951,1.508-1.541
-		l4.197-5.608h-5.443l-4,5.64H44.88c0.152-0.896,0.229-1.88,0.229-2.951v-9.475h-1.505l-3.347,4.771v18.179h4.853V27.88
-		c0-0.635-0.077-1.442-0.229-2.426h1.541l4.524,7.508h5.442L51.634,25.75z"/>
-	
-		<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="-171.6099" y1="952.2349" x2="-171.6099" y2="977.8392" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_10_)" d="M112.094,29.324h-1.312c-1.226,0-1.834-0.546-1.834-1.639V10.012h-1.517l-3.303,4.709v14.175
-		c0,1.421,0.415,2.52,1.246,3.295s1.968,1.164,3.41,1.164c1.749,0,3.037-0.219,3.867-0.656L112.094,29.324z"/>
-	
-		<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-123.9146" y1="952.2349" x2="-123.9146" y2="977.837" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-		<stop  offset="0" style="stop-color:#FFFFFE"/>
-		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
-		<stop  offset="1" style="stop-color:#E9E7E8"/>
-	</linearGradient>
-	<path fill="url(#SVGID_11_)" d="M159.395,25.75c-0.457-0.787-0.959-1.365-1.508-1.737v-0.065c0.657-0.438,1.16-0.951,1.508-1.541
-		l4.198-5.608h-5.442l-4,5.64h-1.508c0.152-0.896,0.229-1.88,0.229-2.951v-9.475h-1.504l-3.347,4.772v18.178h4.853V27.88
-		c0-0.633-0.078-1.442-0.229-2.426h1.541l4.524,7.508h5.44L159.395,25.75z"/>
-</g>
-<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-268.0127" y1="943.3462" x2="-268.0127" y2="948.4634" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-	<stop  offset="0" style="stop-color:#00639A"/>
-	<stop  offset="0.2355" style="stop-color:#00578A"/>
-	<stop  offset="0.507" style="stop-color:#004D7B"/>
-	<stop  offset="0.7167" style="stop-color:#004773"/>
-	<stop  offset="1" style="stop-color:#00446E"/>
-</linearGradient>
-<polygon fill="url(#SVGID_12_)" points="11.988,8.8 7.433,7.781 6.93,9.663 11.988,12.208 17.045,9.663 16.542,7.781 "/>
-<polyline opacity="0.2" enable-background="new    " points="11.988,12.208 17.045,9.663 16.542,7.781 11.988,8.8 "/>
-<path fill="#034672" d="M9.513,18.602c1.708,0.635,3.352,0.78,4.947,0.199l-0.142-1.118c-1.333,0.413-3.182,0.374-4.789,0.038
-	L9.513,18.602z"/>
-<path fill="#034672" d="M11.85,18.424c-0.203,1.387,0.954,2.369,0.954,3.833C14.741,20.077,12.264,19.341,11.85,18.424z"/>
-<path fill="#034672" d="M11.827,18.518c-0.06,1.614-0.202,2.81-0.876,3.646C9.732,19.781,11.296,18.984,11.827,18.518z"/>
-<circle fill="#034672" cx="11.841" cy="18.507" r="0.802"/>
-<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="-262.5933" y1="969.396" x2="-262.5933" y2="969.396" gradientTransform="matrix(1 0 0 1 280 -935.5)">
-	<stop  offset="0" style="stop-color:#F6F6F6"/>
-	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
-	<stop  offset="1" style="stop-color:#DADADA"/>
-</linearGradient>
-<path fill="url(#SVGID_13_)" d="M17.407,33.896"/>
-</svg>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="164.254px" height="39.875px" viewBox="-0.104 1.48 164.254 39.875" enable-background="new -0.104 1.48 164.254 39.875"
+	 xml:space="preserve">
+<g>
+	
+		<path fill="none" stroke="#FFFFFF" stroke-width="4.5285" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+		M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732c-1.333,0.413-3.182,0.375-4.789,0.038
+		c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448c-0.889,3.328,3.592,4.312,5.503,3.875
+		c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
+		c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748c-0.871-0.41-0.83-1.45,0.093-1.932
+		c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
+	
+		<path fill="none" stroke="#FFFFFF" stroke-width="4.5285" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+		M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946c-1.055,0-2.02,0.718-2.425,0.946
+		C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275
+		c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584h0.342
+		c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038
+		c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
+		c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275C18.841,7.321,17.372,6.525,16.967,6.296z"/>
+</g>
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-277.7925" y1="960.855" x2="-246.2632" y2="960.855" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+	<stop  offset="0" style="stop-color:#FDFDFD"/>
+	<stop  offset="0.1452" style="stop-color:#F4F5F5"/>
+	<stop  offset="0.6844" style="stop-color:#D9DBDB"/>
+	<stop  offset="1" style="stop-color:#CFD1D1"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732
+	c-1.333,0.413-3.182,0.375-4.789,0.038c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448
+	c-0.889,3.328,3.592,4.312,5.503,3.875c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293
+	c-0.262-0.509-0.115-1.231,0.293-1.573c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748
+	c-0.871-0.41-0.83-1.45,0.093-1.932c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
+<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
+	M33.737,19.22c-3.625,2.516-7.391,1.854-11.665-1.689c-2.464-2.042-5.61-1.396-7.754-0.732c-1.333,0.413-3.182,0.375-4.789,0.038
+	c-7.033-1.475-5.5,3.038-4.196,7.052c2.394,7.366-1.628,9.073-3.01,6.448c-0.889,3.328,3.592,4.312,5.503,3.875
+	c3.022-0.693,7.07-1.084,9.582-0.315c4.802,1.468,6.604,0.258,5.808-1.293c-0.262-0.509-0.115-1.231,0.293-1.573
+	c1.426-1.195,2.664-0.188,4.029-0.98c1.061-0.616,1.045-1.975-0.599-2.748c-0.871-0.41-0.83-1.45,0.093-1.932
+	c1.877-0.982,4.403-0.521,5.032-2.586C32.287,22.044,32.917,20.188,33.737,19.22z"/>
+<path fill="#034672" d="M5.771,23.728c-1.39-3.753-3.275-8.366,3.758-6.891c1.606,0.336,3.456,0.375,4.789-0.038
+	c2.144-0.663,5.018-1.229,7.303,0.765c4.466,3.898,8.491,4.173,12.117,1.657c-0.82,0.968-1.563,2.799-1.676,3.563
+	c-0.095,0.65-0.562,0.963-1.198,1.196c-6.602,2.413-7.107-2.76-10.105-4.863c-1.589-1.114-4.53-0.96-6.298-0.317
+	c-1.595,0.58-3.239,0.435-4.947-0.199C6.661,17.543,4.745,18.103,5.771,23.728z"/>
+<path fill="#FFFFFF" d="M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946
+	c-1.055,0-2.02,0.718-2.425,0.946C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19
+	c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584
+	h0.342c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038
+	c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745
+	c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275C18.841,7.321,17.372,6.525,16.967,6.296z"/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-272.8555" y1="957.9448" x2="-257.3407" y2="954.0872" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+	<stop  offset="0" style="stop-color:#B8D7E9"/>
+	<stop  offset="0.3324" style="stop-color:#CCE3F1"/>
+	<stop  offset="0.6937" style="stop-color:#DAEBF7"/>
+	<stop  offset="1" style="stop-color:#DFEEF9"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M16.967,6.296c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946v34.863
+	l2.425-2.482V19.001c0,0,0-0.755,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.342c0.285,0,0.462-0.109,0.462-0.584
+	c0-1.076,0.392-1.494,0.887-1.745c1.45-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275
+	C18.841,7.321,17.372,6.525,16.967,6.296z"/>
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-271.3652" y1="945.7817" x2="-267.0252" y2="967.042" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+	<stop  offset="0" style="stop-color:#F1F9FE"/>
+	<stop  offset="0.4254" style="stop-color:#E9F5FD"/>
+	<stop  offset="1" style="stop-color:#E4F3FD"/>
+</linearGradient>
+<path fill="url(#SVGID_3_)" d="M11.987,3.808c-1.055,0-2.02,0.718-2.425,0.946C9.157,4.982,7.535,5.998,7.006,6.296
+	c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24c0.495,0.251,0.887,0.669,0.887,1.745
+	c0,0.475,0.177,0.584,0.462,0.584h0.342c0.315,0,0.486,0.118,0.486,0.632c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626
+	l0.434-0.445L11.987,3.808L11.987,3.808z"/>
+<path fill="none" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M16.967,6.296
+	c-0.529-0.299-2.15-1.314-2.555-1.542c-0.406-0.228-1.37-0.946-2.425-0.946c-1.055,0-2.02,0.718-2.425,0.946
+	C9.157,4.982,7.535,5.998,7.006,6.296c-0.405,0.229-1.874,1.025-1.874,3.19c0,0.659,0,1.793,0,2.275c0,1.431,0.804,2.505,2.254,3.24
+	c0.495,0.251,0.887,0.669,0.887,1.745c0,0.475,0.177,0.584,0.462,0.584h0.342c0.315,0,0.486,0.118,0.486,0.632
+	c0,0.283,0,1.038,0,1.038v18.718l1.365,1.398h0.626l2.859-2.929V19c0,0,0-0.755,0-1.038c0-0.514,0.171-0.632,0.485-0.632h0.342
+	c0.285,0,0.462-0.109,0.462-0.584c0-1.076,0.392-1.494,0.886-1.745c1.451-0.736,2.254-1.81,2.254-3.24c0-0.481,0-1.616,0-2.275
+	C18.841,7.321,17.372,6.525,16.967,6.296z"/>
+<path fill="#E9F6FE" stroke="#034672" stroke-width="1.0063" stroke-miterlimit="10" d="M19.443,19"/>
+<g>
+	
+		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-216.7974" y1="952.2349" x2="-216.7974" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_4_)" d="M66.236,26.503H60.4c0.152,1.182,0.508,1.974,1.065,2.377c0.557,0.406,1.481,0.606,2.771,0.606
+		c1.727,0,3.739-0.12,6.033-0.36l0.458,3.016c-1.683,0.809-4.033,1.213-7.049,1.213c-3.038,0-5.202-0.656-6.491-1.967
+		c-1.29-1.312-1.935-3.475-1.935-6.492c0-3.169,0.628-5.387,1.885-6.656c1.257-1.268,3.372-1.902,6.344-1.902
+		c2.689,0,4.634,0.465,5.836,1.394c1.202,0.93,1.814,2.345,1.836,4.246c0,1.508-0.388,2.639-1.164,3.395
+		C69.215,26.126,67.963,26.503,66.236,26.503z M60.302,23.585h4.59c0.59,0,0.989-0.142,1.196-0.426
+		c0.208-0.283,0.312-0.701,0.312-1.248c0-0.765-0.197-1.295-0.59-1.59s-1.115-0.443-2.164-0.443c-1.246,0-2.099,0.246-2.558,0.738
+		C60.63,21.11,60.368,22.099,60.302,23.585z"/>
+	
+		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-199.8774" y1="952.2349" x2="-199.8774" y2="977.8398" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_5_)" d="M89.089,16.799l-5.737,16.394c-0.307,0.874-0.684,1.682-1.131,2.426
+		c-0.449,0.743-1.021,1.457-1.722,2.147c-0.7,0.688-1.568,1.196-2.606,1.524c-1.039,0.328-2.191,0.414-3.459,0.262l-0.393-2.854
+		c1.311-0.35,2.338-0.805,3.082-1.359c0.743-0.557,1.322-1.309,1.737-2.248l0.066-0.131h-0.918c-0.809,0-1.333-0.393-1.574-1.182
+		l-5.278-14.982h5.18l3.017,10.458c0.197,0.766,0.361,1.574,0.492,2.426h0.426c0.065-0.262,0.174-0.672,0.328-1.229
+		c0.153-0.556,0.262-0.955,0.328-1.197l2.984-10.458L89.089,16.799L89.089,16.799z"/>
+	
+		<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-184.2358" y1="952.2349" x2="-184.2358" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_6_)" d="M102.518,29.126l0.428,3.148c-1.663,0.721-3.75,1.082-6.264,1.082c-2.972,0-5.063-0.641-6.279-1.918
+		c-1.213-1.277-1.818-3.471-1.818-6.572c0-3.127,0.611-5.329,1.834-6.607c1.227-1.278,3.333-1.918,6.328-1.918
+		c2.447,0,4.438,0.339,5.967,1.017l-0.523,3.016c-2.361-0.043-3.902-0.066-4.623-0.066c-1.486,0-2.508,0.317-3.066,0.952
+		c-0.557,0.634-0.836,1.834-0.836,3.605c0,1.771,0.279,2.973,0.836,3.606s1.58,0.95,3.066,0.95
+		C99.467,29.421,101.117,29.324,102.518,29.126z"/>
+	
+		<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-158.7007" y1="952.2349" x2="-158.7007" y2="977.8403" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_7_)" d="M121.314,16.34c3.018,0,5.153,0.651,6.412,1.951c1.256,1.301,1.885,3.503,1.885,6.607
+		s-0.629,5.295-1.885,6.573c-1.259,1.278-3.395,1.918-6.412,1.918c-3.037,0-5.187-0.64-6.441-1.918
+		c-1.257-1.278-1.885-3.47-1.885-6.573c0-3.125,0.628-5.333,1.885-6.623C116.129,16.985,118.277,16.34,121.314,16.34z
+		 M121.314,19.979c-1.289,0-2.152,0.327-2.588,0.983c-0.438,0.656-0.658,1.967-0.658,3.935c0,1.923,0.219,3.213,0.658,3.869
+		c0.436,0.655,1.299,0.983,2.588,0.983c1.248,0,2.094-0.328,2.543-0.983c0.447-0.656,0.672-1.946,0.672-3.869
+		c0-1.944-0.219-3.251-0.656-3.918S122.583,19.979,121.314,19.979z"/>
+	
+		<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-141.6396" y1="952.2349" x2="-141.6396" y2="977.84" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_8_)" d="M131.82,20.406l-0.457-3.279c2.906-0.525,5.715-0.787,8.425-0.787c2.187,0,3.792,0.443,4.819,1.329
+		c1.029,0.885,1.541,2.421,1.541,4.606v10.688h-3.836l-0.492-2.459c-1.618,1.901-3.606,2.854-5.965,2.854
+		c-1.553,0-2.82-0.41-3.805-1.229c-0.984-0.82-1.478-1.961-1.478-3.426v-1.64c0-1.29,0.438-2.296,1.312-3.017
+		c0.874-0.723,2.086-1.082,3.639-1.082h5.771v-0.721c-0.022-0.83-0.213-1.389-0.575-1.673c-0.359-0.283-1.055-0.426-2.082-0.426
+		C136.848,20.143,134.575,20.231,131.82,20.406z M135.361,27.421v0.623c0,1.115,0.635,1.67,1.902,1.67
+		c1.312,0,2.656-0.523,4.033-1.573v-2.263h-4.359C135.887,25.903,135.361,26.417,135.361,27.421z"/>
+	
+		<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="-231.6772" y1="952.2349" x2="-231.6772" y2="977.837" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_9_)" d="M51.634,25.75c-0.459-0.787-0.962-1.365-1.508-1.737v-0.065c0.656-0.438,1.158-0.951,1.508-1.541
+		l4.197-5.608h-5.443l-4,5.64H44.88c0.152-0.896,0.229-1.88,0.229-2.951v-9.475h-1.505l-3.347,4.771v18.179h4.853V27.88
+		c0-0.635-0.077-1.442-0.229-2.426h1.541l4.524,7.508h5.442L51.634,25.75z"/>
+	
+		<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="-171.6099" y1="952.2349" x2="-171.6099" y2="977.8392" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_10_)" d="M112.094,29.324h-1.312c-1.226,0-1.834-0.546-1.834-1.639V10.012h-1.517l-3.303,4.709v14.175
+		c0,1.421,0.415,2.52,1.246,3.295s1.968,1.164,3.41,1.164c1.749,0,3.037-0.219,3.867-0.656L112.094,29.324z"/>
+	
+		<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-123.9146" y1="952.2349" x2="-123.9146" y2="977.837" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+		<stop  offset="0" style="stop-color:#FFFFFE"/>
+		<stop  offset="0.4815" style="stop-color:#F2F1F1"/>
+		<stop  offset="1" style="stop-color:#E9E7E8"/>
+	</linearGradient>
+	<path fill="url(#SVGID_11_)" d="M159.395,25.75c-0.457-0.787-0.959-1.365-1.508-1.737v-0.065c0.657-0.438,1.16-0.951,1.508-1.541
+		l4.198-5.608h-5.442l-4,5.64h-1.508c0.152-0.896,0.229-1.88,0.229-2.951v-9.475h-1.504l-3.347,4.772v18.178h4.853V27.88
+		c0-0.633-0.078-1.442-0.229-2.426h1.541l4.524,7.508h5.44L159.395,25.75z"/>
+</g>
+<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-268.0127" y1="943.3462" x2="-268.0127" y2="948.4634" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+	<stop  offset="0" style="stop-color:#00639A"/>
+	<stop  offset="0.2355" style="stop-color:#00578A"/>
+	<stop  offset="0.507" style="stop-color:#004D7B"/>
+	<stop  offset="0.7167" style="stop-color:#004773"/>
+	<stop  offset="1" style="stop-color:#00446E"/>
+</linearGradient>
+<polygon fill="url(#SVGID_12_)" points="11.988,8.8 7.433,7.781 6.93,9.663 11.988,12.208 17.045,9.663 16.542,7.781 "/>
+<polyline opacity="0.2" enable-background="new    " points="11.988,12.208 17.045,9.663 16.542,7.781 11.988,8.8 "/>
+<path fill="#034672" d="M9.513,18.602c1.708,0.635,3.352,0.78,4.947,0.199l-0.142-1.118c-1.333,0.413-3.182,0.374-4.789,0.038
+	L9.513,18.602z"/>
+<path fill="#034672" d="M11.85,18.424c-0.203,1.387,0.954,2.369,0.954,3.833C14.741,20.077,12.264,19.341,11.85,18.424z"/>
+<path fill="#034672" d="M11.827,18.518c-0.06,1.614-0.202,2.81-0.876,3.646C9.732,19.781,11.296,18.984,11.827,18.518z"/>
+<circle fill="#034672" cx="11.841" cy="18.507" r="0.802"/>
+<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="-262.5933" y1="969.396" x2="-262.5933" y2="969.396" gradientTransform="matrix(1 0 0 1 280 -935.5)">
+	<stop  offset="0" style="stop-color:#F6F6F6"/>
+	<stop  offset="0.5386" style="stop-color:#E4E4E4"/>
+	<stop  offset="1" style="stop-color:#DADADA"/>
+</linearGradient>
+<path fill="url(#SVGID_13_)" d="M17.407,33.896"/>
+</svg>

model/api/pom.xml 132(+66 -66)

diff --git a/model/api/pom.xml b/model/api/pom.xml
index 9cdefbb..af4be13 100755
--- a/model/api/pom.xml
+++ b/model/api/pom.xml
@@ -1,66 +1,66 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-api</artifactId>
-    <name>Keycloak Model API</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-   </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-api</artifactId>
+    <name>Keycloak Model API</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+   </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
index cb08418..f0d0ea4 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
@@ -1,18 +1,18 @@
-package org.keycloak.migration;
-
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface MigrationModel {
-    /**
-     * Must have the form of major.minor.micro as the version is parsed and numbers are compared
-     */
-    public static final String LATEST_VERSION = "1.4.0";
-
-    String getStoredVersion();
-    void setStoredVersion(String version);
-}
+package org.keycloak.migration;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface MigrationModel {
+    /**
+     * Must have the form of major.minor.micro as the version is parsed and numbers are compared
+     */
+    public static final String LATEST_VERSION = "1.4.0";
+
+    String getStoredVersion();
+    void setStoredVersion(String version);
+}
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
index b791003..05289b2 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -1,46 +1,46 @@
-package org.keycloak.migration;
-
-import org.jboss.logging.Logger;
-import org.keycloak.migration.migrators.MigrateTo1_3_0;
-import org.keycloak.migration.migrators.MigrateTo1_4_0;
-import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
-import org.keycloak.models.KeycloakSession;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MigrationModelManager {
-    private static Logger logger = Logger.getLogger(MigrationModelManager.class);
-
-    public static void migrate(KeycloakSession session) {
-        MigrationModel model = session.realms().getMigrationModel();
-        String storedVersion = model.getStoredVersion();
-        if (MigrationModel.LATEST_VERSION.equals(storedVersion)) return;
-        ModelVersion stored = null;
-        if (storedVersion != null) {
-            stored = new ModelVersion(storedVersion);
-        }
-
-        if (stored == null || stored.lessThan(MigrationTo1_2_0_CR1.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.2.0.CR1 updates");
-            }
-            new MigrationTo1_2_0_CR1().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_3_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.3.0 updates");
-            }
-            new MigrateTo1_3_0().migrate(session);
-        }
-        if (stored == null || stored.lessThan(MigrateTo1_4_0.VERSION)) {
-            if (stored != null) {
-                logger.debug("Migrating older model to 1.4.0 updates");
-            }
-            new MigrateTo1_4_0().migrate(session);
-        }
-
-        model.setStoredVersion(MigrationModel.LATEST_VERSION);
-    }
-}
+package org.keycloak.migration;
+
+import org.jboss.logging.Logger;
+import org.keycloak.migration.migrators.MigrateTo1_3_0;
+import org.keycloak.migration.migrators.MigrateTo1_4_0;
+import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrationModelManager {
+    private static Logger logger = Logger.getLogger(MigrationModelManager.class);
+
+    public static void migrate(KeycloakSession session) {
+        MigrationModel model = session.realms().getMigrationModel();
+        String storedVersion = model.getStoredVersion();
+        if (MigrationModel.LATEST_VERSION.equals(storedVersion)) return;
+        ModelVersion stored = null;
+        if (storedVersion != null) {
+            stored = new ModelVersion(storedVersion);
+        }
+
+        if (stored == null || stored.lessThan(MigrationTo1_2_0_CR1.VERSION)) {
+            if (stored != null) {
+                logger.debug("Migrating older model to 1.2.0.CR1 updates");
+            }
+            new MigrationTo1_2_0_CR1().migrate(session);
+        }
+        if (stored == null || stored.lessThan(MigrateTo1_3_0.VERSION)) {
+            if (stored != null) {
+                logger.debug("Migrating older model to 1.3.0 updates");
+            }
+            new MigrateTo1_3_0().migrate(session);
+        }
+        if (stored == null || stored.lessThan(MigrateTo1_4_0.VERSION)) {
+            if (stored != null) {
+                logger.debug("Migrating older model to 1.4.0 updates");
+            }
+            new MigrateTo1_4_0().migrate(session);
+        }
+
+        model.setStoredVersion(MigrationModel.LATEST_VERSION);
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/migration/migrators/MigrationTo1_2_0_CR1.java b/model/api/src/main/java/org/keycloak/migration/migrators/MigrationTo1_2_0_CR1.java
index bc1c6d8..c9e10ad 100755
--- a/model/api/src/main/java/org/keycloak/migration/migrators/MigrationTo1_2_0_CR1.java
+++ b/model/api/src/main/java/org/keycloak/migration/migrators/MigrationTo1_2_0_CR1.java
@@ -1,55 +1,55 @@
-package org.keycloak.migration.migrators;
-
-import org.keycloak.migration.ModelVersion;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MigrationTo1_2_0_CR1 {
-    public static final ModelVersion VERSION = new ModelVersion("1.2.0.CR1");
-
-    public void setupBrokerService(RealmModel realm) {
-        ClientModel client = realm.getClientNameMap().get(Constants.BROKER_SERVICE_CLIENT_ID);
-        if (client == null) {
-            client = KeycloakModelUtils.createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
-            client.setEnabled(true);
-            client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}");
-            client.setFullScopeAllowed(false);
-
-            for (String role : Constants.BROKER_SERVICE_ROLES) {
-                client.addRole(role).setDescription("${role_"+ role.toLowerCase().replaceAll("_", "-") +"}");
-            }
-        }
-    }
-
-    private void setupClientNames(RealmModel realm) {
-        Map<String, ClientModel> clients = realm.getClientNameMap();
-
-        setupClientName(clients, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-        setupClientName(clients, Constants.ADMIN_CONSOLE_CLIENT_ID);
-        setupClientName(clients, Constants.REALM_MANAGEMENT_CLIENT_ID);
-    }
-
-    private void setupClientName(Map<String, ClientModel> clients, String clientId) {
-        ClientModel client = clients.get(clientId);
-        if (client != null && client.getName() == null) client.setName("${client_" + clientId + "}");
-    }
-
-    public void migrate(KeycloakSession session) {
-        List<RealmModel> realms = session.realms().getRealms();
-        for (RealmModel realm : realms) {
-            setupBrokerService(realm);
-            setupClientNames(realm);
-        }
-
-    }
-}
+package org.keycloak.migration.migrators;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrationTo1_2_0_CR1 {
+    public static final ModelVersion VERSION = new ModelVersion("1.2.0.CR1");
+
+    public void setupBrokerService(RealmModel realm) {
+        ClientModel client = realm.getClientNameMap().get(Constants.BROKER_SERVICE_CLIENT_ID);
+        if (client == null) {
+            client = KeycloakModelUtils.createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
+            client.setEnabled(true);
+            client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}");
+            client.setFullScopeAllowed(false);
+
+            for (String role : Constants.BROKER_SERVICE_ROLES) {
+                client.addRole(role).setDescription("${role_"+ role.toLowerCase().replaceAll("_", "-") +"}");
+            }
+        }
+    }
+
+    private void setupClientNames(RealmModel realm) {
+        Map<String, ClientModel> clients = realm.getClientNameMap();
+
+        setupClientName(clients, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        setupClientName(clients, Constants.ADMIN_CONSOLE_CLIENT_ID);
+        setupClientName(clients, Constants.REALM_MANAGEMENT_CLIENT_ID);
+    }
+
+    private void setupClientName(Map<String, ClientModel> clients, String clientId) {
+        ClientModel client = clients.get(clientId);
+        if (client != null && client.getName() == null) client.setName("${client_" + clientId + "}");
+    }
+
+    public void migrate(KeycloakSession session) {
+        List<RealmModel> realms = session.realms().getRealms();
+        for (RealmModel realm : realms) {
+            setupBrokerService(realm);
+            setupClientNames(realm);
+        }
+
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/migration/ModelVersion.java b/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
index 095576a..d866320 100755
--- a/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
+++ b/model/api/src/main/java/org/keycloak/migration/ModelVersion.java
@@ -1,69 +1,69 @@
-package org.keycloak.migration;
-
-import org.jboss.logging.Logger;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class ModelVersion {
-    private static Logger logger = Logger.getLogger(ModelVersion.class);
-    int major;
-    int minor;
-    int micro;
-    String qualifier;
-
-    public ModelVersion(int major, int minor, int micro) {
-        this.major = major;
-        this.minor = minor;
-        this.micro = micro;
-    }
-
-    public ModelVersion(String version) {
-        String[] split = version.split("\\.");
-        try {
-            if (split.length > 0) {
-                major = Integer.parseInt(split[0]);
-            }
-            if (split.length > 1) {
-                minor = Integer.parseInt(split[1]);
-            }
-            if (split.length > 2) {
-                micro = Integer.parseInt(split[2]);
-            }
-            if (split.length > 3) {
-                qualifier = split[3];
-            }
-        } catch (NumberFormatException e) {
-            logger.warn("failed to parse version: " + version, e);
-        }
-    }
-
-    public int getMajor() {
-        return major;
-    }
-
-    public int getMinor() {
-        return minor;
-    }
-
-    public int getMicro() {
-        return micro;
-    }
-
-    public String getQualifier() {
-        return qualifier;
-    }
-
-    public boolean lessThan(ModelVersion version) {
-        if (major < version.major) return true;
-        if (minor < version.minor) return true;
-        if (micro < version.micro) return true;
-        if (qualifier != null && qualifier.equals(version.qualifier)) return false;
-        if (qualifier == null) return false;
-        if (version.qualifier == null) return true;
-        int comp = qualifier.compareTo(version.qualifier);
-        if (comp < 0) return true;
-        return false;
-    }
-}
+package org.keycloak.migration;
+
+import org.jboss.logging.Logger;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class ModelVersion {
+    private static Logger logger = Logger.getLogger(ModelVersion.class);
+    int major;
+    int minor;
+    int micro;
+    String qualifier;
+
+    public ModelVersion(int major, int minor, int micro) {
+        this.major = major;
+        this.minor = minor;
+        this.micro = micro;
+    }
+
+    public ModelVersion(String version) {
+        String[] split = version.split("\\.");
+        try {
+            if (split.length > 0) {
+                major = Integer.parseInt(split[0]);
+            }
+            if (split.length > 1) {
+                minor = Integer.parseInt(split[1]);
+            }
+            if (split.length > 2) {
+                micro = Integer.parseInt(split[2]);
+            }
+            if (split.length > 3) {
+                qualifier = split[3];
+            }
+        } catch (NumberFormatException e) {
+            logger.warn("failed to parse version: " + version, e);
+        }
+    }
+
+    public int getMajor() {
+        return major;
+    }
+
+    public int getMinor() {
+        return minor;
+    }
+
+    public int getMicro() {
+        return micro;
+    }
+
+    public String getQualifier() {
+        return qualifier;
+    }
+
+    public boolean lessThan(ModelVersion version) {
+        if (major < version.major) return true;
+        if (minor < version.minor) return true;
+        if (micro < version.micro) return true;
+        if (qualifier != null && qualifier.equals(version.qualifier)) return false;
+        if (qualifier == null) return false;
+        if (version.qualifier == null) return true;
+        int comp = qualifier.compareTo(version.qualifier);
+        if (comp < 0) return true;
+        return false;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java b/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
index 3b959d9..f390d1f 100755
--- a/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
@@ -1,136 +1,136 @@
-package org.keycloak.models;
-
-import java.util.Comparator;
-import java.io.Serializable;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class AuthenticationExecutionModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    public static class ExecutionComparator implements Comparator<AuthenticationExecutionModel> {
-        public static final ExecutionComparator SINGLETON = new ExecutionComparator();
-
-        @Override
-        public int compare(AuthenticationExecutionModel o1, AuthenticationExecutionModel o2) {
-            return o1.priority - o2.priority;
-        }
-    }
-
-    private String id;
-    private String authenticatorConfig;
-    private String authenticator;
-    private String flowId;
-    private boolean autheticatorFlow;
-    private Requirement requirement;
-    private boolean userSetupAllowed;
-    private int priority;
-    private String parentFlow;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAuthenticatorConfig() {
-        return authenticatorConfig;
-    }
-
-    public void setAuthenticatorConfig(String authenticatorConfig) {
-        this.authenticatorConfig = authenticatorConfig;
-    }
-
-    public String getAuthenticator() {
-        return authenticator;
-    }
-
-    public void setAuthenticator(String authenticator) {
-        this.authenticator = authenticator;
-    }
-
-    public Requirement getRequirement() {
-        return requirement;
-    }
-
-    public void setRequirement(Requirement requirement) {
-        this.requirement = requirement;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public boolean isUserSetupAllowed() {
-        return userSetupAllowed;
-    }
-
-    public void setUserSetupAllowed(boolean userSetupAllowed) {
-        this.userSetupAllowed = userSetupAllowed;
-    }
-
-    public String getParentFlow() {
-        return parentFlow;
-    }
-
-    public void setParentFlow(String parentFlow) {
-        this.parentFlow = parentFlow;
-    }
-
-    /**
-     * If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel
-     *
-     * @return
-     */
-    public String getFlowId() {
-        return flowId;
-    }
-
-    public void setFlowId(String flowId) {
-        this.flowId = flowId;
-    }
-
-    /**
-     * Is the referenced authenticator a flow?
-     *
-     * @return
-     */
-    public boolean isAutheticatorFlow() {
-        return autheticatorFlow;
-    }
-
-    public void setAutheticatorFlow(boolean autheticatorFlow) {
-        this.autheticatorFlow = autheticatorFlow;
-    }
-
-    public enum Requirement {
-        REQUIRED,
-        OPTIONAL,
-        ALTERNATIVE,
-        DISABLED
-    }
-
-    public boolean isRequired() {
-        return requirement == Requirement.REQUIRED;
-    }
-    public boolean isOptional() {
-        return requirement == Requirement.OPTIONAL;
-    }
-    public boolean isAlternative() {
-        return requirement == Requirement.ALTERNATIVE;
-    }
-    public boolean isDisabled() {
-        return requirement == Requirement.DISABLED;
-    }
-    public boolean isEnabled() {
-        return requirement != Requirement.DISABLED;
-    }
-}
+package org.keycloak.models;
+
+import java.util.Comparator;
+import java.io.Serializable;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class AuthenticationExecutionModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public static class ExecutionComparator implements Comparator<AuthenticationExecutionModel> {
+        public static final ExecutionComparator SINGLETON = new ExecutionComparator();
+
+        @Override
+        public int compare(AuthenticationExecutionModel o1, AuthenticationExecutionModel o2) {
+            return o1.priority - o2.priority;
+        }
+    }
+
+    private String id;
+    private String authenticatorConfig;
+    private String authenticator;
+    private String flowId;
+    private boolean autheticatorFlow;
+    private Requirement requirement;
+    private boolean userSetupAllowed;
+    private int priority;
+    private String parentFlow;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAuthenticatorConfig() {
+        return authenticatorConfig;
+    }
+
+    public void setAuthenticatorConfig(String authenticatorConfig) {
+        this.authenticatorConfig = authenticatorConfig;
+    }
+
+    public String getAuthenticator() {
+        return authenticator;
+    }
+
+    public void setAuthenticator(String authenticator) {
+        this.authenticator = authenticator;
+    }
+
+    public Requirement getRequirement() {
+        return requirement;
+    }
+
+    public void setRequirement(Requirement requirement) {
+        this.requirement = requirement;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public boolean isUserSetupAllowed() {
+        return userSetupAllowed;
+    }
+
+    public void setUserSetupAllowed(boolean userSetupAllowed) {
+        this.userSetupAllowed = userSetupAllowed;
+    }
+
+    public String getParentFlow() {
+        return parentFlow;
+    }
+
+    public void setParentFlow(String parentFlow) {
+        this.parentFlow = parentFlow;
+    }
+
+    /**
+     * If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel
+     *
+     * @return
+     */
+    public String getFlowId() {
+        return flowId;
+    }
+
+    public void setFlowId(String flowId) {
+        this.flowId = flowId;
+    }
+
+    /**
+     * Is the referenced authenticator a flow?
+     *
+     * @return
+     */
+    public boolean isAutheticatorFlow() {
+        return autheticatorFlow;
+    }
+
+    public void setAutheticatorFlow(boolean autheticatorFlow) {
+        this.autheticatorFlow = autheticatorFlow;
+    }
+
+    public enum Requirement {
+        REQUIRED,
+        OPTIONAL,
+        ALTERNATIVE,
+        DISABLED
+    }
+
+    public boolean isRequired() {
+        return requirement == Requirement.REQUIRED;
+    }
+    public boolean isOptional() {
+        return requirement == Requirement.OPTIONAL;
+    }
+    public boolean isAlternative() {
+        return requirement == Requirement.ALTERNATIVE;
+    }
+    public boolean isDisabled() {
+        return requirement == Requirement.DISABLED;
+    }
+    public boolean isEnabled() {
+        return requirement != Requirement.DISABLED;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java b/model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java
index 4f83d63..f538d30 100755
--- a/model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java
+++ b/model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java
@@ -1,66 +1,66 @@
-package org.keycloak.models;
-
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationFlowModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String id;
-    private String alias;
-    private String description;
-    private String providerId;
-    private boolean topLevel;
-    private boolean builtIn;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public boolean isTopLevel() {
-        return topLevel;
-    }
-
-    public void setTopLevel(boolean topLevel) {
-        this.topLevel = topLevel;
-    }
-
-    public boolean isBuiltIn() {
-        return builtIn;
-    }
-
-    public void setBuiltIn(boolean builtIn) {
-        this.builtIn = builtIn;
-    }
-}
+package org.keycloak.models;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationFlowModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+    private String alias;
+    private String description;
+    private String providerId;
+    private boolean topLevel;
+    private boolean builtIn;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public boolean isTopLevel() {
+        return topLevel;
+    }
+
+    public void setTopLevel(boolean topLevel) {
+        this.topLevel = topLevel;
+    }
+
+    public boolean isBuiltIn() {
+        return builtIn;
+    }
+
+    public void setBuiltIn(boolean builtIn) {
+        this.builtIn = builtIn;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java b/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
index 9b60192..9e7f46d 100755
--- a/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
+++ b/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
@@ -1,44 +1,44 @@
-package org.keycloak.models;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class AuthenticatorConfigModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String id;
-    private String alias;
-    private Map<String, String> config = new HashMap<String, String>();
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.models;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class AuthenticatorConfigModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+    private String alias;
+    private Map<String, String> config = new HashMap<String, String>();
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java b/model/api/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
index e7d479f..9e3ebfe 100755
--- a/model/api/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
+++ b/model/api/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
@@ -1,27 +1,27 @@
-package org.keycloak.models;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class BrowserSecurityHeaders {
-    public static final Map<String, String> headerAttributeMap;
-    public static final Map<String, String> defaultHeaders;
-
-    static {
-        Map<String, String> headerMap = new HashMap<String, String>();
-        headerMap.put("xFrameOptions", "X-Frame-Options");
-        headerMap.put("contentSecurityPolicy", "Content-Security-Policy");
-
-        Map<String, String> dh = new HashMap<String, String>();
-        dh.put("xFrameOptions", "SAMEORIGIN");
-        dh.put("contentSecurityPolicy", "frame-src 'self'");
-
-        defaultHeaders = Collections.unmodifiableMap(dh);
-        headerAttributeMap = Collections.unmodifiableMap(headerMap);
-    }
-}
+package org.keycloak.models;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class BrowserSecurityHeaders {
+    public static final Map<String, String> headerAttributeMap;
+    public static final Map<String, String> defaultHeaders;
+
+    static {
+        Map<String, String> headerMap = new HashMap<String, String>();
+        headerMap.put("xFrameOptions", "X-Frame-Options");
+        headerMap.put("contentSecurityPolicy", "Content-Security-Policy");
+
+        Map<String, String> dh = new HashMap<String, String>();
+        dh.put("xFrameOptions", "SAMEORIGIN");
+        dh.put("contentSecurityPolicy", "frame-src 'self'");
+
+        defaultHeaders = Collections.unmodifiableMap(dh);
+        headerAttributeMap = Collections.unmodifiableMap(headerMap);
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ClaimMask.java b/model/api/src/main/java/org/keycloak/models/ClaimMask.java
index da8063f..20a5543 100755
--- a/model/api/src/main/java/org/keycloak/models/ClaimMask.java
+++ b/model/api/src/main/java/org/keycloak/models/ClaimMask.java
@@ -1,54 +1,54 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClaimMask {
-    public static final long NAME = 0x01l;
-    public static final long USERNAME = 0x02l;
-    public static final long PROFILE = 0x04l;
-    public static final long PICTURE = 0x08l;
-    public static final long WEBSITE = 0x10l;
-    public static final long EMAIL = 0x20l;
-    public static final long GENDER = 0x40l;
-    public static final long LOCALE = 0x80l;
-    public static final long ADDRESS = 0x100l;
-    public static final long PHONE = 0x200l;
-
-    public static final long ALL = NAME | USERNAME | PROFILE | PICTURE | WEBSITE | EMAIL | GENDER | LOCALE | ADDRESS | PHONE;
-
-    public static boolean hasName(long mask) {
-        return (mask & NAME) > 0;
-    }
-    public static boolean hasUsername(long mask) {
-        return (mask & USERNAME) > 0;
-    }
-    public static boolean hasProfile(long mask) {
-        return (mask & PROFILE) > 0;
-    }
-    public static boolean hasPicture(long mask) {
-        return (mask & PICTURE) > 0;
-    }
-    public static boolean hasWebsite(long mask) {
-        return (mask & WEBSITE) > 0;
-    }
-    public static boolean hasEmail(long mask) {
-        return (mask & EMAIL) > 0;
-    }
-    public static boolean hasGender(long mask) {
-        return (mask & GENDER) > 0;
-    }
-    public static boolean hasLocale(long mask) {
-        return (mask & LOCALE) > 0;
-    }
-    public static boolean hasAddress(long mask) {
-        return (mask & ADDRESS) > 0;
-    }
-    public static boolean hasPhone(long mask) {
-        return (mask & PHONE) > 0;
-    }
-
-
-
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClaimMask {
+    public static final long NAME = 0x01l;
+    public static final long USERNAME = 0x02l;
+    public static final long PROFILE = 0x04l;
+    public static final long PICTURE = 0x08l;
+    public static final long WEBSITE = 0x10l;
+    public static final long EMAIL = 0x20l;
+    public static final long GENDER = 0x40l;
+    public static final long LOCALE = 0x80l;
+    public static final long ADDRESS = 0x100l;
+    public static final long PHONE = 0x200l;
+
+    public static final long ALL = NAME | USERNAME | PROFILE | PICTURE | WEBSITE | EMAIL | GENDER | LOCALE | ADDRESS | PHONE;
+
+    public static boolean hasName(long mask) {
+        return (mask & NAME) > 0;
+    }
+    public static boolean hasUsername(long mask) {
+        return (mask & USERNAME) > 0;
+    }
+    public static boolean hasProfile(long mask) {
+        return (mask & PROFILE) > 0;
+    }
+    public static boolean hasPicture(long mask) {
+        return (mask & PICTURE) > 0;
+    }
+    public static boolean hasWebsite(long mask) {
+        return (mask & WEBSITE) > 0;
+    }
+    public static boolean hasEmail(long mask) {
+        return (mask & EMAIL) > 0;
+    }
+    public static boolean hasGender(long mask) {
+        return (mask & GENDER) > 0;
+    }
+    public static boolean hasLocale(long mask) {
+        return (mask & LOCALE) > 0;
+    }
+    public static boolean hasAddress(long mask) {
+        return (mask & ADDRESS) > 0;
+    }
+    public static boolean hasPhone(long mask) {
+        return (mask & PHONE) > 0;
+    }
+
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ClaimTypeModel.java b/model/api/src/main/java/org/keycloak/models/ClaimTypeModel.java
index 21c9234..83799ea 100755
--- a/model/api/src/main/java/org/keycloak/models/ClaimTypeModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClaimTypeModel.java
@@ -1,82 +1,82 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClaimTypeModel {
-
-    public static enum ValueType {
-        BOOLEAN,
-        INT,
-        STRING
-    }
-
-    private String id;
-    private String name;
-    private boolean builtIn;
-    private ValueType type;
-
-    public ClaimTypeModel(ClaimTypeModel copy) {
-        this(copy.getId(), copy.getName(), copy.isBuiltIn(), copy.getType());
-    }
-
-    public ClaimTypeModel(String id, String name, boolean builtIn, ValueType type) {
-        this.id = id;
-        this.name = name;
-        this.builtIn = builtIn;
-        this.type = type;
-    }
-
-    public ClaimTypeModel() {
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public boolean isBuiltIn() {
-        return builtIn;
-    }
-
-    public ValueType getType() {
-        return type;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public void setBuiltIn(boolean builtIn) {
-        this.builtIn = builtIn;
-    }
-
-    public void setType(ValueType type) {
-        this.type = type;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ClaimTypeModel that = (ClaimTypeModel) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClaimTypeModel {
+
+    public static enum ValueType {
+        BOOLEAN,
+        INT,
+        STRING
+    }
+
+    private String id;
+    private String name;
+    private boolean builtIn;
+    private ValueType type;
+
+    public ClaimTypeModel(ClaimTypeModel copy) {
+        this(copy.getId(), copy.getName(), copy.isBuiltIn(), copy.getType());
+    }
+
+    public ClaimTypeModel(String id, String name, boolean builtIn, ValueType type) {
+        this.id = id;
+        this.name = name;
+        this.builtIn = builtIn;
+        this.type = type;
+    }
+
+    public ClaimTypeModel() {
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isBuiltIn() {
+        return builtIn;
+    }
+
+    public ValueType getType() {
+        return type;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setBuiltIn(boolean builtIn) {
+        this.builtIn = builtIn;
+    }
+
+    public void setType(ValueType type) {
+        this.type = type;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClaimTypeModel that = (ClaimTypeModel) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java
index 5fae169..689f4cc 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -1,141 +1,141 @@
-package org.keycloak.models;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ClientModel extends RoleContainerModel {
-
-    // COMMON ATTRIBUTES
-
-    String PRIVATE_KEY = "privateKey";
-    String PUBLIC_KEY = "publicKey";
-    String X509CERTIFICATE = "X509Certificate";
-
-    void updateClient();
-
-    String getId();
-
-    String getClientId();
-
-    void setClientId(String clientId);
-
-    String getName();
-
-    void setName(String name);
-
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
-
-    boolean isSurrogateAuthRequired();
-
-    void setSurrogateAuthRequired(boolean surrogateAuthRequired);
-
-    Set<String> getWebOrigins();
-
-    void setWebOrigins(Set<String> webOrigins);
-
-    void addWebOrigin(String webOrigin);
-
-    void removeWebOrigin(String webOrigin);
-
-    Set<String> getRedirectUris();
-
-    void setRedirectUris(Set<String> redirectUris);
-
-    void addRedirectUri(String redirectUri);
-
-    void removeRedirectUri(String redirectUri);
-
-    String getManagementUrl();
-
-    void setManagementUrl(String url);
-
-    String getBaseUrl();
-
-    void setBaseUrl(String url);
-
-    List<String> getDefaultRoles();
-
-    void addDefaultRole(String name);
-
-    void updateDefaultRoles(String[] defaultRoles);
-
-    Set<RoleModel> getClientScopeMappings(ClientModel client);
-
-    boolean isBearerOnly();
-    void setBearerOnly(boolean only);
-
-    int getNodeReRegistrationTimeout();
-
-    void setNodeReRegistrationTimeout(int timeout);
-
-    boolean validateSecret(String secret);
-    String getSecret();
-    public void setSecret(String secret);
-
-    boolean isFullScopeAllowed();
-    void setFullScopeAllowed(boolean value);
-
-    String getProtocol();
-    void setProtocol(String protocol);
-
-    void setAttribute(String name, String value);
-    void removeAttribute(String name);
-    String getAttribute(String name);
-    Map<String, String> getAttributes();
-
-    boolean isFrontchannelLogout();
-    void setFrontchannelLogout(boolean flag);
-
-
-    boolean isPublicClient();
-    void setPublicClient(boolean flag);
-
-    boolean isDirectGrantsOnly();
-    void setDirectGrantsOnly(boolean flag);
-
-    boolean isConsentRequired();
-    void setConsentRequired(boolean consentRequired);
-
-    Set<RoleModel> getScopeMappings();
-    void addScopeMapping(RoleModel role);
-    void deleteScopeMapping(RoleModel role);
-    Set<RoleModel> getRealmScopeMappings();
-    boolean hasScope(RoleModel role);
-
-    RealmModel getRealm();
-
-    /**
-     * Time in seconds since epoc
-     *
-     * @return
-     */
-    int getNotBefore();
-
-    void setNotBefore(int notBefore);
-
-    Set<ProtocolMapperModel> getProtocolMappers();
-    ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model);
-    void removeProtocolMapper(ProtocolMapperModel mapping);
-    void updateProtocolMapper(ProtocolMapperModel mapping);
-    public ProtocolMapperModel getProtocolMapperById(String id);
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name);
-
-    Map<String, Integer> getRegisteredNodes();
-
-    /**
-     * Register node or just update the 'lastReRegistration' time if this node is already registered
-     *
-     * @param nodeHost
-     * @param registrationTime
-     */
-    void registerNode(String nodeHost, int registrationTime);
-
-    void unregisterNode(String nodeHost);
-}
+package org.keycloak.models;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientModel extends RoleContainerModel {
+
+    // COMMON ATTRIBUTES
+
+    String PRIVATE_KEY = "privateKey";
+    String PUBLIC_KEY = "publicKey";
+    String X509CERTIFICATE = "X509Certificate";
+
+    void updateClient();
+
+    String getId();
+
+    String getClientId();
+
+    void setClientId(String clientId);
+
+    String getName();
+
+    void setName(String name);
+
+    boolean isEnabled();
+
+    void setEnabled(boolean enabled);
+
+    boolean isSurrogateAuthRequired();
+
+    void setSurrogateAuthRequired(boolean surrogateAuthRequired);
+
+    Set<String> getWebOrigins();
+
+    void setWebOrigins(Set<String> webOrigins);
+
+    void addWebOrigin(String webOrigin);
+
+    void removeWebOrigin(String webOrigin);
+
+    Set<String> getRedirectUris();
+
+    void setRedirectUris(Set<String> redirectUris);
+
+    void addRedirectUri(String redirectUri);
+
+    void removeRedirectUri(String redirectUri);
+
+    String getManagementUrl();
+
+    void setManagementUrl(String url);
+
+    String getBaseUrl();
+
+    void setBaseUrl(String url);
+
+    List<String> getDefaultRoles();
+
+    void addDefaultRole(String name);
+
+    void updateDefaultRoles(String[] defaultRoles);
+
+    Set<RoleModel> getClientScopeMappings(ClientModel client);
+
+    boolean isBearerOnly();
+    void setBearerOnly(boolean only);
+
+    int getNodeReRegistrationTimeout();
+
+    void setNodeReRegistrationTimeout(int timeout);
+
+    boolean validateSecret(String secret);
+    String getSecret();
+    public void setSecret(String secret);
+
+    boolean isFullScopeAllowed();
+    void setFullScopeAllowed(boolean value);
+
+    String getProtocol();
+    void setProtocol(String protocol);
+
+    void setAttribute(String name, String value);
+    void removeAttribute(String name);
+    String getAttribute(String name);
+    Map<String, String> getAttributes();
+
+    boolean isFrontchannelLogout();
+    void setFrontchannelLogout(boolean flag);
+
+
+    boolean isPublicClient();
+    void setPublicClient(boolean flag);
+
+    boolean isDirectGrantsOnly();
+    void setDirectGrantsOnly(boolean flag);
+
+    boolean isConsentRequired();
+    void setConsentRequired(boolean consentRequired);
+
+    Set<RoleModel> getScopeMappings();
+    void addScopeMapping(RoleModel role);
+    void deleteScopeMapping(RoleModel role);
+    Set<RoleModel> getRealmScopeMappings();
+    boolean hasScope(RoleModel role);
+
+    RealmModel getRealm();
+
+    /**
+     * Time in seconds since epoc
+     *
+     * @return
+     */
+    int getNotBefore();
+
+    void setNotBefore(int notBefore);
+
+    Set<ProtocolMapperModel> getProtocolMappers();
+    ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model);
+    void removeProtocolMapper(ProtocolMapperModel mapping);
+    void updateProtocolMapper(ProtocolMapperModel mapping);
+    public ProtocolMapperModel getProtocolMapperById(String id);
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name);
+
+    Map<String, Integer> getRegisteredNodes();
+
+    /**
+     * Register node or just update the 'lastReRegistration' time if this node is already registered
+     *
+     * @param nodeHost
+     * @param registrationTime
+     */
+    void registerNode(String nodeHost, int registrationTime);
+
+    void unregisterNode(String nodeHost);
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
index 8531b5d..105b6ba 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -1,94 +1,94 @@
-package org.keycloak.models;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public interface ClientSessionModel {
-
-    public String getId();
-    public RealmModel getRealm();
-    public ClientModel getClient();
-
-    public UserSessionModel getUserSession();
-    public void setUserSession(UserSessionModel userSession);
-
-    public String getRedirectUri();
-    public void setRedirectUri(String uri);
-
-    public int getTimestamp();
-
-    public void setTimestamp(int timestamp);
-
-    public String getAction();
-
-    public void setAction(String action);
-
-    public Set<String> getRoles();
-    public void setRoles(Set<String> roles);
-
-    public Set<String> getProtocolMappers();
-    public void setProtocolMappers(Set<String> protocolMappers);
-
-    public Map<String, ExecutionStatus> getExecutionStatus();
-    public void setExecutionStatus(String authenticator, ExecutionStatus status);
-    public void clearExecutionStatus();
-    public UserModel getAuthenticatedUser();
-    public void setAuthenticatedUser(UserModel user);
-
-
-
-    /**
-     * Authentication request type, i.e. OAUTH, SAML 2.0, SAML 1.1, etc.
-     *
-     * @return
-     */
-    public String getAuthMethod();
-    public void setAuthMethod(String method);
-
-    public String getNote(String name);
-    public void setNote(String name, String value);
-    public void removeNote(String name);
-    public Map<String, String> getNotes();
-
-    /**
-     * These are notes you want applied to the UserSessionModel when the client session is attached to it.
-     *
-     * @param name
-     * @param value
-     */
-    public void setUserSessionNote(String name, String value);
-
-    /**
-     * These are notes you want applied to the UserSessionModel when the client session is attached to it.
-     *
-     * @return
-     */
-    public Map<String, String> getUserSessionNotes();
-
-    public void clearUserSessionNotes();
-
-    public static enum Action {
-        OAUTH_GRANT,
-        CODE_TO_TOKEN,
-        VERIFY_EMAIL,
-        UPDATE_PROFILE,
-        CONFIGURE_TOTP,
-        UPDATE_PASSWORD,
-        RECOVER_PASSWORD,
-        AUTHENTICATE,
-        SOCIAL_CALLBACK,
-        LOGGED_OUT
-    }
-
-    public enum ExecutionStatus {
-        FAILED,
-        SUCCESS,
-        SETUP_REQUIRED,
-        ATTEMPTED,
-        SKIPPED,
-        CHALLENGED
-    }
-}
+package org.keycloak.models;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface ClientSessionModel {
+
+    public String getId();
+    public RealmModel getRealm();
+    public ClientModel getClient();
+
+    public UserSessionModel getUserSession();
+    public void setUserSession(UserSessionModel userSession);
+
+    public String getRedirectUri();
+    public void setRedirectUri(String uri);
+
+    public int getTimestamp();
+
+    public void setTimestamp(int timestamp);
+
+    public String getAction();
+
+    public void setAction(String action);
+
+    public Set<String> getRoles();
+    public void setRoles(Set<String> roles);
+
+    public Set<String> getProtocolMappers();
+    public void setProtocolMappers(Set<String> protocolMappers);
+
+    public Map<String, ExecutionStatus> getExecutionStatus();
+    public void setExecutionStatus(String authenticator, ExecutionStatus status);
+    public void clearExecutionStatus();
+    public UserModel getAuthenticatedUser();
+    public void setAuthenticatedUser(UserModel user);
+
+
+
+    /**
+     * Authentication request type, i.e. OAUTH, SAML 2.0, SAML 1.1, etc.
+     *
+     * @return
+     */
+    public String getAuthMethod();
+    public void setAuthMethod(String method);
+
+    public String getNote(String name);
+    public void setNote(String name, String value);
+    public void removeNote(String name);
+    public Map<String, String> getNotes();
+
+    /**
+     * These are notes you want applied to the UserSessionModel when the client session is attached to it.
+     *
+     * @param name
+     * @param value
+     */
+    public void setUserSessionNote(String name, String value);
+
+    /**
+     * These are notes you want applied to the UserSessionModel when the client session is attached to it.
+     *
+     * @return
+     */
+    public Map<String, String> getUserSessionNotes();
+
+    public void clearUserSessionNotes();
+
+    public static enum Action {
+        OAUTH_GRANT,
+        CODE_TO_TOKEN,
+        VERIFY_EMAIL,
+        UPDATE_PROFILE,
+        CONFIGURE_TOTP,
+        UPDATE_PASSWORD,
+        RECOVER_PASSWORD,
+        AUTHENTICATE,
+        SOCIAL_CALLBACK,
+        LOGGED_OUT
+    }
+
+    public enum ExecutionStatus {
+        FAILED,
+        SUCCESS,
+        SETUP_REQUIRED,
+        ATTEMPTED,
+        SKIPPED,
+        CHALLENGED
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java
index a3104e1..b1adbfa 100755
--- a/model/api/src/main/java/org/keycloak/models/Constants.java
+++ b/model/api/src/main/java/org/keycloak/models/Constants.java
@@ -1,19 +1,19 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface Constants {
-    String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console";
-
-    String ACCOUNT_MANAGEMENT_CLIENT_ID = "account";
-    String IMPERSONATION_SERVICE_CLIENT_ID = "impersonation";
-    String BROKER_SERVICE_CLIENT_ID = "broker";
-    String REALM_MANAGEMENT_CLIENT_ID = "realm-management";
-
-    String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob";
-    String INSTALLED_APP_URL = "http://localhost";
-    String READ_TOKEN_ROLE = "read-token";
-    String[] BROKER_SERVICE_ROLES = {READ_TOKEN_ROLE};
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface Constants {
+    String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console";
+
+    String ACCOUNT_MANAGEMENT_CLIENT_ID = "account";
+    String IMPERSONATION_SERVICE_CLIENT_ID = "impersonation";
+    String BROKER_SERVICE_CLIENT_ID = "broker";
+    String REALM_MANAGEMENT_CLIENT_ID = "realm-management";
+
+    String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob";
+    String INSTALLED_APP_URL = "http://localhost";
+    String READ_TOKEN_ROLE = "read-token";
+    String[] BROKER_SERVICE_ROLES = {READ_TOKEN_ROLE};
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
index d4b21ee..d0cbd5e 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java
@@ -1,92 +1,92 @@
-package org.keycloak.models.entities;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationExecutionEntity {
-    protected String id;
-    protected String authenticator;
-    private String authenticatorConfig;
-    protected String flowId;
-    protected AuthenticationExecutionModel.Requirement requirement;
-    protected int priority;
-    private boolean userSetupAllowed;
-    private boolean authenticatorFlow;
-    private String parentFlow;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAuthenticator() {
-        return authenticator;
-    }
-
-    public void setAuthenticator(String authenticator) {
-        this.authenticator = authenticator;
-    }
-
-    public AuthenticationExecutionModel.Requirement getRequirement() {
-        return requirement;
-    }
-
-    public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
-        this.requirement = requirement;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public boolean isUserSetupAllowed() {
-        return userSetupAllowed;
-    }
-
-    public void setUserSetupAllowed(boolean userSetupAllowed) {
-        this.userSetupAllowed = userSetupAllowed;
-    }
-
-    public boolean isAuthenticatorFlow() {
-        return authenticatorFlow;
-    }
-
-    public void setAuthenticatorFlow(boolean authenticatorFlow) {
-        this.authenticatorFlow = authenticatorFlow;
-    }
-
-    public String getParentFlow() {
-        return parentFlow;
-    }
-
-    public void setParentFlow(String parentFlow) {
-        this.parentFlow = parentFlow;
-    }
-
-    public String getFlowId() {
-        return flowId;
-    }
-
-    public void setFlowId(String flowId) {
-        this.flowId = flowId;
-    }
-
-    public String getAuthenticatorConfig() {
-        return authenticatorConfig;
-    }
-
-    public void setAuthenticatorConfig(String authenticatorConfig) {
-        this.authenticatorConfig = authenticatorConfig;
-    }
-}
+package org.keycloak.models.entities;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationExecutionEntity {
+    protected String id;
+    protected String authenticator;
+    private String authenticatorConfig;
+    protected String flowId;
+    protected AuthenticationExecutionModel.Requirement requirement;
+    protected int priority;
+    private boolean userSetupAllowed;
+    private boolean authenticatorFlow;
+    private String parentFlow;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAuthenticator() {
+        return authenticator;
+    }
+
+    public void setAuthenticator(String authenticator) {
+        this.authenticator = authenticator;
+    }
+
+    public AuthenticationExecutionModel.Requirement getRequirement() {
+        return requirement;
+    }
+
+    public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
+        this.requirement = requirement;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public boolean isUserSetupAllowed() {
+        return userSetupAllowed;
+    }
+
+    public void setUserSetupAllowed(boolean userSetupAllowed) {
+        this.userSetupAllowed = userSetupAllowed;
+    }
+
+    public boolean isAuthenticatorFlow() {
+        return authenticatorFlow;
+    }
+
+    public void setAuthenticatorFlow(boolean authenticatorFlow) {
+        this.authenticatorFlow = authenticatorFlow;
+    }
+
+    public String getParentFlow() {
+        return parentFlow;
+    }
+
+    public void setParentFlow(String parentFlow) {
+        this.parentFlow = parentFlow;
+    }
+
+    public String getFlowId() {
+        return flowId;
+    }
+
+    public void setFlowId(String flowId) {
+        this.flowId = flowId;
+    }
+
+    public String getAuthenticatorConfig() {
+        return authenticatorConfig;
+    }
+
+    public void setAuthenticatorConfig(String authenticatorConfig) {
+        this.authenticatorConfig = authenticatorConfig;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationFlowEntity.java b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationFlowEntity.java
index 06d312a..a28df5d 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationFlowEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationFlowEntity.java
@@ -1,75 +1,75 @@
-package org.keycloak.models.entities;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationFlowEntity {
-    protected String id;
-    protected String alias;
-    protected String description;
-    protected String providerId;
-    private boolean topLevel;
-    private boolean builtIn;
-
-    List<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public List<AuthenticationExecutionEntity> getExecutions() {
-        return executions;
-    }
-
-    public void setExecutions(List<AuthenticationExecutionEntity> executions) {
-        this.executions = executions;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public boolean isTopLevel() {
-        return topLevel;
-    }
-
-    public void setTopLevel(boolean topLevel) {
-        this.topLevel = topLevel;
-    }
-
-    public boolean isBuiltIn() {
-        return builtIn;
-    }
-
-    public void setBuiltIn(boolean builtIn) {
-        this.builtIn = builtIn;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationFlowEntity {
+    protected String id;
+    protected String alias;
+    protected String description;
+    protected String providerId;
+    private boolean topLevel;
+    private boolean builtIn;
+
+    List<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public List<AuthenticationExecutionEntity> getExecutions() {
+        return executions;
+    }
+
+    public void setExecutions(List<AuthenticationExecutionEntity> executions) {
+        this.executions = executions;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public boolean isTopLevel() {
+        return topLevel;
+    }
+
+    public void setTopLevel(boolean topLevel) {
+        this.topLevel = topLevel;
+    }
+
+    public boolean isBuiltIn() {
+        return builtIn;
+    }
+
+    public void setBuiltIn(boolean builtIn) {
+        this.builtIn = builtIn;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/AuthenticatorConfigEntity.java b/model/api/src/main/java/org/keycloak/models/entities/AuthenticatorConfigEntity.java
index cf564ec..db97604 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/AuthenticatorConfigEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/AuthenticatorConfigEntity.java
@@ -1,37 +1,37 @@
-package org.keycloak.models.entities;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticatorConfigEntity {
-    protected String id;
-    protected String alias;
-    private Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticatorConfigEntity {
+    protected String id;
+    protected String alias;
+    private Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
index 513c4ef..109806e 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
@@ -1,245 +1,245 @@
-package org.keycloak.models.entities;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ClientEntity extends AbstractIdentifiableEntity {
-
-    private String clientId;
-    private String name;
-    private String realmId;
-    private boolean enabled;
-    private String secret;
-    private String protocol;
-    private int notBefore;
-    private boolean publicClient;
-    private boolean fullScopeAllowed;
-    private boolean frontchannelLogout;
-
-    private boolean surrogateAuthRequired;
-    private String managementUrl;
-    private String baseUrl;
-    private boolean bearerOnly;
-    private boolean consentRequired;
-    private boolean directGrantsOnly;
-    private int nodeReRegistrationTimeout;
-
-    // We are using names of defaultRoles (not ids)
-    private List<String> defaultRoles = new ArrayList<String>();
-
-    private Map<String, Integer> registeredNodes;
-
-    private Map<String, String> attributes = new HashMap<String, String>();
-
-    private List<String> webOrigins = new ArrayList<String>();
-    private List<String> redirectUris = new ArrayList<String>();
-    private List<String> scopeIds = new ArrayList<String>();
-    private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
-    private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public List<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public void setWebOrigins(List<String> webOrigins) {
-        this.webOrigins = webOrigins;
-    }
-
-    public List<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public void setRedirectUris(List<String> redirectUris) {
-        this.redirectUris = redirectUris;
-    }
-
-    public List<String> getScopeIds() {
-        return scopeIds;
-    }
-
-    public void setScopeIds(List<String> scopeIds) {
-        this.scopeIds = scopeIds;
-    }
-
-    public boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public void setFullScopeAllowed(boolean fullScopeAllowed) {
-        this.fullScopeAllowed = fullScopeAllowed;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, String> attributes) {
-        this.attributes = attributes;
-    }
-
-    public boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public void setFrontchannelLogout(boolean frontchannelLogout) {
-        this.frontchannelLogout = frontchannelLogout;
-    }
-
-    public List<ClientIdentityProviderMappingEntity> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(List<ClientIdentityProviderMappingEntity> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public List<ProtocolMapperEntity> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(List<ProtocolMapperEntity> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public boolean isSurrogateAuthRequired() {
-        return surrogateAuthRequired;
-    }
-
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        this.surrogateAuthRequired = surrogateAuthRequired;
-    }
-
-    public String getManagementUrl() {
-        return managementUrl;
-    }
-
-    public void setManagementUrl(String managementUrl) {
-        this.managementUrl = managementUrl;
-    }
-
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
-    public boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public void setBearerOnly(boolean bearerOnly) {
-        this.bearerOnly = bearerOnly;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public boolean isDirectGrantsOnly() {
-        return directGrantsOnly;
-    }
-
-    public void setDirectGrantsOnly(boolean directGrantsOnly) {
-        this.directGrantsOnly = directGrantsOnly;
-    }
-
-    public List<String> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public void setDefaultRoles(List<String> defaultRoles) {
-        this.defaultRoles = defaultRoles;
-    }
-
-    public int getNodeReRegistrationTimeout() {
-        return nodeReRegistrationTimeout;
-    }
-
-    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
-        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
-    }
-
-    public Map<String, Integer> getRegisteredNodes() {
-        return registeredNodes;
-    }
-
-    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
-        this.registeredNodes = registeredNodes;
-    }
-}
-
+package org.keycloak.models.entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ClientEntity extends AbstractIdentifiableEntity {
+
+    private String clientId;
+    private String name;
+    private String realmId;
+    private boolean enabled;
+    private String secret;
+    private String protocol;
+    private int notBefore;
+    private boolean publicClient;
+    private boolean fullScopeAllowed;
+    private boolean frontchannelLogout;
+
+    private boolean surrogateAuthRequired;
+    private String managementUrl;
+    private String baseUrl;
+    private boolean bearerOnly;
+    private boolean consentRequired;
+    private boolean directGrantsOnly;
+    private int nodeReRegistrationTimeout;
+
+    // We are using names of defaultRoles (not ids)
+    private List<String> defaultRoles = new ArrayList<String>();
+
+    private Map<String, Integer> registeredNodes;
+
+    private Map<String, String> attributes = new HashMap<String, String>();
+
+    private List<String> webOrigins = new ArrayList<String>();
+    private List<String> redirectUris = new ArrayList<String>();
+    private List<String> scopeIds = new ArrayList<String>();
+    private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
+    private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public List<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public void setWebOrigins(List<String> webOrigins) {
+        this.webOrigins = webOrigins;
+    }
+
+    public List<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public void setRedirectUris(List<String> redirectUris) {
+        this.redirectUris = redirectUris;
+    }
+
+    public List<String> getScopeIds() {
+        return scopeIds;
+    }
+
+    public void setScopeIds(List<String> scopeIds) {
+        this.scopeIds = scopeIds;
+    }
+
+    public boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public void setFullScopeAllowed(boolean fullScopeAllowed) {
+        this.fullScopeAllowed = fullScopeAllowed;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    public boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public void setFrontchannelLogout(boolean frontchannelLogout) {
+        this.frontchannelLogout = frontchannelLogout;
+    }
+
+    public List<ClientIdentityProviderMappingEntity> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public void setIdentityProviders(List<ClientIdentityProviderMappingEntity> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public List<ProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(List<ProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        this.surrogateAuthRequired = surrogateAuthRequired;
+    }
+
+    public String getManagementUrl() {
+        return managementUrl;
+    }
+
+    public void setManagementUrl(String managementUrl) {
+        this.managementUrl = managementUrl;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public void setDirectGrantsOnly(boolean directGrantsOnly) {
+        this.directGrantsOnly = directGrantsOnly;
+    }
+
+    public List<String> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(List<String> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public int getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
+        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+
+    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
+        this.registeredNodes = registeredNodes;
+    }
+}
+
diff --git a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderMapperEntity.java b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderMapperEntity.java
index edc5061..6fbcd10 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderMapperEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderMapperEntity.java
@@ -1,55 +1,55 @@
-package org.keycloak.models.entities;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class IdentityProviderMapperEntity {
-    protected String id;
-    protected String name;
-    protected String identityProviderAlias;
-    protected String identityProviderMapper;
-    protected Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public String getIdentityProviderAlias() {
-        return identityProviderAlias;
-    }
-
-    public void setIdentityProviderAlias(String identityProviderAlias) {
-        this.identityProviderAlias = identityProviderAlias;
-    }
-
-    public String getIdentityProviderMapper() {
-        return identityProviderMapper;
-    }
-
-    public void setIdentityProviderMapper(String identityProviderMapper) {
-        this.identityProviderMapper = identityProviderMapper;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IdentityProviderMapperEntity {
+    protected String id;
+    protected String name;
+    protected String identityProviderAlias;
+    protected String identityProviderMapper;
+    protected Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public String getIdentityProviderAlias() {
+        return identityProviderAlias;
+    }
+
+    public void setIdentityProviderAlias(String identityProviderAlias) {
+        this.identityProviderAlias = identityProviderAlias;
+    }
+
+    public String getIdentityProviderMapper() {
+        return identityProviderMapper;
+    }
+
+    public void setIdentityProviderMapper(String identityProviderMapper) {
+        this.identityProviderMapper = identityProviderMapper;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
index 29ffca2..8ef8ac1 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ProtocolMapperEntity.java
@@ -1,73 +1,73 @@
-package org.keycloak.models.entities;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMapperEntity {
-    protected String id;
-    protected String name;
-    protected String protocol;
-    protected String protocolMapper;
-    protected boolean consentRequired;
-    protected String consentText;
-    protected Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public String getProtocolMapper() {
-        return protocolMapper;
-    }
-
-    public void setProtocolMapper(String protocolMapper) {
-        this.protocolMapper = protocolMapper;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public String getConsentText() {
-        return consentText;
-    }
-
-    public void setConsentText(String consentText) {
-        this.consentText = consentText;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMapperEntity {
+    protected String id;
+    protected String name;
+    protected String protocol;
+    protected String protocolMapper;
+    protected boolean consentRequired;
+    protected String consentText;
+    protected Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProtocolMapper() {
+        return protocolMapper;
+    }
+
+    public void setProtocolMapper(String protocolMapper) {
+        this.protocolMapper = protocolMapper;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public String getConsentText() {
+        return consentText;
+    }
+
+    public void setConsentText(String consentText) {
+        this.consentText = consentText;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RequiredActionProviderEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RequiredActionProviderEntity.java
index 30fcf3e..86de665 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RequiredActionProviderEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RequiredActionProviderEntity.java
@@ -1,73 +1,73 @@
-package org.keycloak.models.entities;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RequiredActionProviderEntity {
-    protected String id;
-    protected String alias;
-    protected String name;
-    protected String providerId;
-    protected boolean enabled;
-    protected boolean defaultAction;
-    private Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public boolean isDefaultAction() {
-        return defaultAction;
-    }
-
-    public void setDefaultAction(boolean defaultAction) {
-        this.defaultAction = defaultAction;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RequiredActionProviderEntity {
+    protected String id;
+    protected String alias;
+    protected String name;
+    protected String providerId;
+    protected boolean enabled;
+    protected boolean defaultAction;
+    private Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isDefaultAction() {
+        return defaultAction;
+    }
+
+    public void setDefaultAction(boolean defaultAction) {
+        this.defaultAction = defaultAction;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java b/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
index bde99ec..eeae34f 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
@@ -1,152 +1,152 @@
-package org.keycloak.models.entities;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class UserEntity extends AbstractIdentifiableEntity {
-
-    private String username;
-    private Long createdTimestamp;
-    private String firstName;
-    private String lastName;
-    private String email;
-    private boolean emailVerified;
-    private boolean totp;
-    private boolean enabled;
-
-    private String realmId;
-
-    private List<String> roleIds;
-
-    private Map<String, List<String>> attributes;
-    private List<String> requiredActions;
-    private List<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
-    private List<FederatedIdentityEntity> federatedIdentities;
-    private String federationLink;
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-    
-    public Long getCreatedTimestamp() {
-        return createdTimestamp;
-    }
-
-    public void setCreatedTimestamp(Long timestamp) {
-        this.createdTimestamp = timestamp;
-    }
-
-
-    public String getFirstName() {
-        return firstName;
-    }
-
-    public void setFirstName(String firstName) {
-        this.firstName = firstName;
-    }
-
-    public String getLastName() {
-        return lastName;
-    }
-
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-    public boolean isEmailVerified() {
-        return emailVerified;
-    }
-
-    public void setEmailVerified(boolean emailVerified) {
-        this.emailVerified = emailVerified;
-    }
-
-    public boolean isTotp() {
-        return totp;
-    }
-
-    public void setTotp(boolean totp) {
-        this.totp = totp;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public List<String> getRoleIds() {
-        return roleIds;
-    }
-
-    public void setRoleIds(List<String> roleIds) {
-        this.roleIds = roleIds;
-    }
-
-    public Map<String, List<String>> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, List<String>> attributes) {
-        this.attributes = attributes;
-    }
-
-    public List<String> getRequiredActions() {
-        return requiredActions;
-    }
-
-    public void setRequiredActions(List<String> requiredActions) {
-        this.requiredActions = requiredActions;
-    }
-
-    public List<CredentialEntity> getCredentials() {
-        return credentials;
-    }
-
-    public void setCredentials(List<CredentialEntity> credentials) {
-        this.credentials = credentials;
-    }
-
-    public List<FederatedIdentityEntity> getFederatedIdentities() {
-        return federatedIdentities;
-    }
-
-    public void setFederatedIdentities(List<FederatedIdentityEntity> federatedIdentities) {
-        this.federatedIdentities = federatedIdentities;
-    }
-
-    public String getFederationLink() {
-        return federationLink;
-    }
-
-    public void setFederationLink(String federationLink) {
-        this.federationLink = federationLink;
-    }
-}
-
+package org.keycloak.models.entities;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserEntity extends AbstractIdentifiableEntity {
+
+    private String username;
+    private Long createdTimestamp;
+    private String firstName;
+    private String lastName;
+    private String email;
+    private boolean emailVerified;
+    private boolean totp;
+    private boolean enabled;
+
+    private String realmId;
+
+    private List<String> roleIds;
+
+    private Map<String, List<String>> attributes;
+    private List<String> requiredActions;
+    private List<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
+    private List<FederatedIdentityEntity> federatedIdentities;
+    private String federationLink;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+    
+    public Long getCreatedTimestamp() {
+        return createdTimestamp;
+    }
+
+    public void setCreatedTimestamp(Long timestamp) {
+        this.createdTimestamp = timestamp;
+    }
+
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public boolean isEmailVerified() {
+        return emailVerified;
+    }
+
+    public void setEmailVerified(boolean emailVerified) {
+        this.emailVerified = emailVerified;
+    }
+
+    public boolean isTotp() {
+        return totp;
+    }
+
+    public void setTotp(boolean totp) {
+        this.totp = totp;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public List<String> getRoleIds() {
+        return roleIds;
+    }
+
+    public void setRoleIds(List<String> roleIds) {
+        this.roleIds = roleIds;
+    }
+
+    public Map<String, List<String>> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, List<String>> attributes) {
+        this.attributes = attributes;
+    }
+
+    public List<String> getRequiredActions() {
+        return requiredActions;
+    }
+
+    public void setRequiredActions(List<String> requiredActions) {
+        this.requiredActions = requiredActions;
+    }
+
+    public List<CredentialEntity> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(List<CredentialEntity> credentials) {
+        this.credentials = credentials;
+    }
+
+    public List<FederatedIdentityEntity> getFederatedIdentities() {
+        return federatedIdentities;
+    }
+
+    public void setFederatedIdentities(List<FederatedIdentityEntity> federatedIdentities) {
+        this.federatedIdentities = federatedIdentities;
+    }
+
+    public String getFederationLink() {
+        return federationLink;
+    }
+
+    public void setFederationLink(String federationLink) {
+        this.federationLink = federationLink;
+    }
+}
+
diff --git a/model/api/src/main/java/org/keycloak/models/entities/UserFederationProviderEntity.java b/model/api/src/main/java/org/keycloak/models/entities/UserFederationProviderEntity.java
index fe00465..49633a3 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/UserFederationProviderEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/UserFederationProviderEntity.java
@@ -1,83 +1,83 @@
-package org.keycloak.models.entities;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserFederationProviderEntity {
-    protected String id;
-    protected String providerName;
-    protected Map<String, String> config;
-    protected int priority;
-    protected String displayName;
-    private int fullSyncPeriod;
-    private int changedSyncPeriod;
-    private int lastSync;
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getProviderName() {
-        return providerName;
-    }
-
-    public void setProviderName(String providerName) {
-        this.providerName = providerName;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public String getDisplayName() {
-        return displayName;
-    }
-
-    public void setDisplayName(String displayName) {
-        this.displayName = displayName;
-    }
-
-    public int getFullSyncPeriod() {
-        return fullSyncPeriod;
-    }
-
-    public void setFullSyncPeriod(int fullSyncPeriod) {
-        this.fullSyncPeriod = fullSyncPeriod;
-    }
-
-    public int getChangedSyncPeriod() {
-        return changedSyncPeriod;
-    }
-
-    public void setChangedSyncPeriod(int changedSyncPeriod) {
-        this.changedSyncPeriod = changedSyncPeriod;
-    }
-
-    public int getLastSync() {
-        return lastSync;
-    }
-
-    public void setLastSync(int lastSync) {
-        this.lastSync = lastSync;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserFederationProviderEntity {
+    protected String id;
+    protected String providerName;
+    protected Map<String, String> config;
+    protected int priority;
+    protected String displayName;
+    private int fullSyncPeriod;
+    private int changedSyncPeriod;
+    private int lastSync;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getProviderName() {
+        return providerName;
+    }
+
+    public void setProviderName(String providerName) {
+        this.providerName = providerName;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    public int getFullSyncPeriod() {
+        return fullSyncPeriod;
+    }
+
+    public void setFullSyncPeriod(int fullSyncPeriod) {
+        this.fullSyncPeriod = fullSyncPeriod;
+    }
+
+    public int getChangedSyncPeriod() {
+        return changedSyncPeriod;
+    }
+
+    public void setChangedSyncPeriod(int changedSyncPeriod) {
+        this.changedSyncPeriod = changedSyncPeriod;
+    }
+
+    public int getLastSync() {
+        return lastSync;
+    }
+
+    public void setLastSync(int lastSync) {
+        this.lastSync = lastSync;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/FederatedIdentityModel.java b/model/api/src/main/java/org/keycloak/models/FederatedIdentityModel.java
index 132b6a1..dc995eb 100755
--- a/model/api/src/main/java/org/keycloak/models/FederatedIdentityModel.java
+++ b/model/api/src/main/java/org/keycloak/models/FederatedIdentityModel.java
@@ -1,43 +1,43 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class FederatedIdentityModel {
-
-    private String token;
-    private final String userId;
-    private final String identityProvider;
-    private final String userName;
-
-    public FederatedIdentityModel(String identityProvider, String userId, String userName) {
-        this(identityProvider, userId, userName, null);
-    }
-
-    public FederatedIdentityModel(String providerId, String userId, String userName, String token) {
-        this.identityProvider = providerId;
-        this.userId = userId;
-        this.userName = userName;
-        this.token = token;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public String getIdentityProvider() {
-        return identityProvider;
-    }
-
-    public String getUserName() {
-        return userName;
-    }
-
-    public String getToken() {
-        return this.token;
-    }
-
-    public void setToken(String token) {
-        this.token = token;
-    }
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class FederatedIdentityModel {
+
+    private String token;
+    private final String userId;
+    private final String identityProvider;
+    private final String userName;
+
+    public FederatedIdentityModel(String identityProvider, String userId, String userName) {
+        this(identityProvider, userId, userName, null);
+    }
+
+    public FederatedIdentityModel(String providerId, String userId, String userName, String token) {
+        this.identityProvider = providerId;
+        this.userId = userId;
+        this.userName = userName;
+        this.token = token;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public String getIdentityProvider() {
+        return identityProvider;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public String getToken() {
+        return this.token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/IdentityProviderMapperModel.java b/model/api/src/main/java/org/keycloak/models/IdentityProviderMapperModel.java
index 2071323..e3acf7f 100755
--- a/model/api/src/main/java/org/keycloak/models/IdentityProviderMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/IdentityProviderMapperModel.java
@@ -1,78 +1,78 @@
-package org.keycloak.models;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * Specifies a mapping from broker login to user data.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class IdentityProviderMapperModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    protected String id;
-    protected String name;
-    protected String identityProviderAlias;
-    protected String identityProviderMapper;
-    protected Map<String, String> config;
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getIdentityProviderAlias() {
-        return identityProviderAlias;
-    }
-
-    public void setIdentityProviderAlias(String identityProviderAlias) {
-        this.identityProviderAlias = identityProviderAlias;
-    }
-
-    public String getIdentityProviderMapper() {
-        return identityProviderMapper;
-    }
-
-    public void setIdentityProviderMapper(String identityProviderMapper) {
-        this.identityProviderMapper = identityProviderMapper;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        IdentityProviderMapperModel that = (IdentityProviderMapperModel) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Specifies a mapping from broker login to user data.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class IdentityProviderMapperModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    protected String id;
+    protected String name;
+    protected String identityProviderAlias;
+    protected String identityProviderMapper;
+    protected Map<String, String> config;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getIdentityProviderAlias() {
+        return identityProviderAlias;
+    }
+
+    public void setIdentityProviderAlias(String identityProviderAlias) {
+        this.identityProviderAlias = identityProviderAlias;
+    }
+
+    public String getIdentityProviderMapper() {
+        return identityProviderMapper;
+    }
+
+    public void setIdentityProviderMapper(String identityProviderMapper) {
+        this.identityProviderMapper = identityProviderMapper;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        IdentityProviderMapperModel that = (IdentityProviderMapperModel) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ImpersonationConstants.java b/model/api/src/main/java/org/keycloak/models/ImpersonationConstants.java
index a5cb385..99f08d1 100755
--- a/model/api/src/main/java/org/keycloak/models/ImpersonationConstants.java
+++ b/model/api/src/main/java/org/keycloak/models/ImpersonationConstants.java
@@ -1,50 +1,50 @@
-package org.keycloak.models;
-
-import org.keycloak.Config;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ImpersonationConstants {
-    public static String IMPERSONATION_ROLE = "impersonation";
-
-
-    public static void setupMasterRealmRole(RealmProvider model, RealmModel realm) {
-        RealmModel adminRealm;
-        RoleModel adminRole;
-
-        if (realm.getName().equals(Config.getAdminRealm())) {
-            adminRealm = realm;
-            adminRole = realm.getRole(AdminRoles.ADMIN);
-        } else {
-            adminRealm = model.getRealmByName(Config.getAdminRealm());
-            adminRole = adminRealm.getRole(AdminRoles.ADMIN);
-        }
-        ClientModel realmAdminApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
-        if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
-        RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
-        impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
-        adminRole.addCompositeRole(impersonationRole);
-    }
-
-    public static void setupRealmRole(RealmModel realm) {
-        if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm
-        String realmAdminApplicationClientId = Constants.REALM_MANAGEMENT_CLIENT_ID;
-        ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
-        if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
-        RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
-        impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
-        RoleModel adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
-        adminRole.addCompositeRole(impersonationRole);
-    }
-
-
-    public static void setupImpersonationService(KeycloakSession session, RealmModel realm) {
-        setupMasterRealmRole(session.realms(), realm);
-        setupRealmRole(realm);
-    }
-
-
-}
+package org.keycloak.models;
+
+import org.keycloak.Config;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ImpersonationConstants {
+    public static String IMPERSONATION_ROLE = "impersonation";
+
+
+    public static void setupMasterRealmRole(RealmProvider model, RealmModel realm) {
+        RealmModel adminRealm;
+        RoleModel adminRole;
+
+        if (realm.getName().equals(Config.getAdminRealm())) {
+            adminRealm = realm;
+            adminRole = realm.getRole(AdminRoles.ADMIN);
+        } else {
+            adminRealm = model.getRealmByName(Config.getAdminRealm());
+            adminRole = adminRealm.getRole(AdminRoles.ADMIN);
+        }
+        ClientModel realmAdminApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
+        if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
+        RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
+        impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
+        adminRole.addCompositeRole(impersonationRole);
+    }
+
+    public static void setupRealmRole(RealmModel realm) {
+        if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm
+        String realmAdminApplicationClientId = Constants.REALM_MANAGEMENT_CLIENT_ID;
+        ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
+        if (realmAdminApp.getRole(IMPERSONATION_ROLE) != null) return;
+        RoleModel impersonationRole = realmAdminApp.addRole(IMPERSONATION_ROLE);
+        impersonationRole.setDescription("${role_" + IMPERSONATION_ROLE + "}");
+        RoleModel adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
+        adminRole.addCompositeRole(impersonationRole);
+    }
+
+
+    public static void setupImpersonationService(KeycloakSession session, RealmModel realm) {
+        setupMasterRealmRole(session.realms(), realm);
+        setupRealmRole(realm);
+    }
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
index b8ce57b..27a43be 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -1,63 +1,63 @@
-package org.keycloak.models;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.provider.Provider;
-
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakSession {
-
-    KeycloakContext getContext();
-
-    KeycloakTransactionManager getTransaction();
-
-    <T extends Provider> T getProvider(Class<T> clazz);
-
-    <T extends Provider> T getProvider(Class<T> clazz, String id);
-
-    <T extends Provider> Set<String> listProviderIds(Class<T> clazz);
-
-    <T extends Provider> Set<T> getAllProviders(Class<T> clazz);
-
-    void enlistForClose(Provider provider);
-
-    KeycloakSessionFactory getKeycloakSessionFactory();
-
-    /**
-     * Returns a managed provider instance.  Will start a provider transaction.  This transaction is managed by the KeycloakSession
-     * transaction.
-     *
-     * @return
-     * @throws IllegalStateException if transaction is not active
-     */
-    RealmProvider realms();
-
-    /**
-     * Returns a managed provider instance.  Will start a provider transaction.  This transaction is managed by the KeycloakSession
-     * transaction.
-     *
-     * @return
-     * @throws IllegalStateException if transaction is not active
-     */
-    UserSessionProvider sessions();
-
-
-
-    void close();
-
-    /**
-     * Possibly both cached and federated view of users depending on configuration.
-     *
-     * @return
-     */
-    UserFederationManager users();
-
-    /**
-     *  Keycloak user storage.  Non-federated, but possibly cache (if it is on) view of users.
-     */
-    UserProvider userStorage();
-}
+package org.keycloak.models;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.provider.Provider;
+
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakSession {
+
+    KeycloakContext getContext();
+
+    KeycloakTransactionManager getTransaction();
+
+    <T extends Provider> T getProvider(Class<T> clazz);
+
+    <T extends Provider> T getProvider(Class<T> clazz, String id);
+
+    <T extends Provider> Set<String> listProviderIds(Class<T> clazz);
+
+    <T extends Provider> Set<T> getAllProviders(Class<T> clazz);
+
+    void enlistForClose(Provider provider);
+
+    KeycloakSessionFactory getKeycloakSessionFactory();
+
+    /**
+     * Returns a managed provider instance.  Will start a provider transaction.  This transaction is managed by the KeycloakSession
+     * transaction.
+     *
+     * @return
+     * @throws IllegalStateException if transaction is not active
+     */
+    RealmProvider realms();
+
+    /**
+     * Returns a managed provider instance.  Will start a provider transaction.  This transaction is managed by the KeycloakSession
+     * transaction.
+     *
+     * @return
+     * @throws IllegalStateException if transaction is not active
+     */
+    UserSessionProvider sessions();
+
+
+
+    void close();
+
+    /**
+     * Possibly both cached and federated view of users depending on configuration.
+     *
+     * @return
+     */
+    UserFederationManager users();
+
+    /**
+     *  Keycloak user storage.  Non-federated, but possibly cache (if it is on) view of users.
+     */
+    UserProvider userStorage();
+}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
index b17629f..cbb3da2 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
@@ -1,23 +1,23 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderEventManager;
-import org.keycloak.provider.ProviderFactory;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakSessionFactory extends ProviderEventManager {
-    KeycloakSession create();
-
-    <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz);
-
-    <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
-
-    List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz);
-
-    void close();
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderEventManager;
+import org.keycloak.provider.ProviderFactory;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakSessionFactory extends ProviderEventManager {
+    KeycloakSession create();
+
+    <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz);
+
+    <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
+
+    List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz);
+
+    void close();
+}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakTransaction.java b/model/api/src/main/java/org/keycloak/models/KeycloakTransaction.java
index cf9103e..b9304c7 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakTransaction.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakTransaction.java
@@ -1,14 +1,14 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakTransaction {
-    void begin();
-    void commit();
-    void rollback();
-    void setRollbackOnly();
-    boolean getRollbackOnly();
-    boolean isActive();
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakTransaction {
+    void begin();
+    void commit();
+    void rollback();
+    void setRollbackOnly();
+    boolean getRollbackOnly();
+    boolean isActive();
+}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakTransactionManager.java b/model/api/src/main/java/org/keycloak/models/KeycloakTransactionManager.java
index abc64ea..e7e0ceb 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakTransactionManager.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakTransactionManager.java
@@ -1,12 +1,12 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface KeycloakTransactionManager extends KeycloakTransaction {
-
-    void enlist(KeycloakTransaction transaction);
-    void enlistAfterCompletion(KeycloakTransaction transaction);
-
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakTransactionManager extends KeycloakTransaction {
+
+    void enlist(KeycloakTransaction transaction);
+    void enlistAfterCompletion(KeycloakTransaction transaction);
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java b/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
index 34fba7e..60d528b 100755
--- a/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ProtocolMapperModel.java
@@ -1,96 +1,96 @@
-package org.keycloak.models;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * Specifies a mapping from user data to a protocol claim assertion.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMapperModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    protected String id;
-    protected String name;
-    protected String protocol;
-    protected String protocolMapper;
-    protected boolean consentRequired;
-    protected String consentText;
-    protected Map<String, String> config;
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public String getProtocolMapper() {
-        return protocolMapper;
-    }
-
-    public void setProtocolMapper(String protocolMapper) {
-        this.protocolMapper = protocolMapper;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public String getConsentText() {
-        return consentText;
-    }
-
-    public void setConsentText(String consentText) {
-        this.consentText = consentText;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ProtocolMapperModel that = (ProtocolMapperModel) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Specifies a mapping from user data to a protocol claim assertion.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMapperModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    protected String id;
+    protected String name;
+    protected String protocol;
+    protected String protocolMapper;
+    protected boolean consentRequired;
+    protected String consentText;
+    protected Map<String, String> config;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProtocolMapper() {
+        return protocolMapper;
+    }
+
+    public void setProtocolMapper(String protocolMapper) {
+        this.protocolMapper = protocolMapper;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public String getConsentText() {
+        return consentText;
+    }
+
+    public void setConsentText(String consentText) {
+        this.consentText = consentText;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ProtocolMapperModel that = (ProtocolMapperModel) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 4f3c13c..d5c7faf 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -1,303 +1,303 @@
-package org.keycloak.models;
-
-import org.keycloak.enums.SslRequired;
-import org.keycloak.provider.ProviderEvent;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RealmModel extends RoleContainerModel {
-    interface RealmCreationEvent extends ProviderEvent {
-        RealmModel getCreatedRealm();
-    }
-
-    interface ClientCreationEvent extends ProviderEvent {
-        ClientModel getCreatedClient();
-    }
-
-    interface UserFederationProviderCreationEvent extends ProviderEvent {
-        UserFederationProviderModel getCreatedFederationProvider();
-        RealmModel getRealm();
-    }
-
-    interface UserFederationMapperEvent extends ProviderEvent {
-        UserFederationMapperModel getFederationMapper();
-        RealmModel getRealm();
-        KeycloakSession getSession();
-    }
-
-    String getId();
-
-    String getName();
-
-    void setName(String name);
-
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
-
-    SslRequired getSslRequired();
-
-    void setSslRequired(SslRequired sslRequired);
-
-    boolean isRegistrationAllowed();
-
-    void setRegistrationAllowed(boolean registrationAllowed);
-
-    boolean isRegistrationEmailAsUsername();
-
-    void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername);
-
-    boolean isRememberMe();
-
-    void setRememberMe(boolean rememberMe);
-
-    boolean isEditUsernameAllowed();
-
-    void setEditUsernameAllowed(boolean editUsernameAllowed);
-
-    //--- brute force settings
-    boolean isBruteForceProtected();
-    void setBruteForceProtected(boolean value);
-    int getMaxFailureWaitSeconds();
-    void setMaxFailureWaitSeconds(int val);
-    int getWaitIncrementSeconds();
-    void setWaitIncrementSeconds(int val);
-    int getMinimumQuickLoginWaitSeconds();
-    void setMinimumQuickLoginWaitSeconds(int val);
-    long getQuickLoginCheckMilliSeconds();
-    void setQuickLoginCheckMilliSeconds(long val);
-    int getMaxDeltaTimeSeconds();
-    void setMaxDeltaTimeSeconds(int val);
-    int getFailureFactor();
-    void setFailureFactor(int failureFactor);
-    //--- end brute force settings
-
-
-    boolean isVerifyEmail();
-
-    void setVerifyEmail(boolean verifyEmail);
-
-    boolean isResetPasswordAllowed();
-
-    void setResetPasswordAllowed(boolean resetPasswordAllowed);
-
-    int getSsoSessionIdleTimeout();
-    void setSsoSessionIdleTimeout(int seconds);
-
-    int getSsoSessionMaxLifespan();
-    void setSsoSessionMaxLifespan(int seconds);
-
-    int getAccessTokenLifespan();
-
-    void setAccessTokenLifespan(int seconds);
-
-    int getAccessCodeLifespan();
-
-    void setAccessCodeLifespan(int seconds);
-
-    int getAccessCodeLifespanUserAction();
-
-    void setAccessCodeLifespanUserAction(int seconds);
-
-    int getAccessCodeLifespanLogin();
-
-    void setAccessCodeLifespanLogin(int seconds);
-
-    String getPublicKeyPem();
-
-    void setPublicKeyPem(String publicKeyPem);
-
-    String getPrivateKeyPem();
-
-    void setPrivateKeyPem(String privateKeyPem);
-
-    PublicKey getPublicKey();
-
-    void setPublicKey(PublicKey publicKey);
-
-    String getCodeSecret();
-
-    Key getCodeSecretKey();
-
-    void setCodeSecret(String codeSecret);
-
-    X509Certificate getCertificate();
-    void setCertificate(X509Certificate certificate);
-    String getCertificatePem();
-    void setCertificatePem(String certificate);
-
-    PrivateKey getPrivateKey();
-
-    void setPrivateKey(PrivateKey privateKey);
-
-    List<RequiredCredentialModel> getRequiredCredentials();
-
-    void addRequiredCredential(String cred);
-
-    PasswordPolicy getPasswordPolicy();
-
-    void setPasswordPolicy(PasswordPolicy policy);
-
-    RoleModel getRoleById(String id);
-
-    List<String> getDefaultRoles();
-
-    void addDefaultRole(String name);
-
-    void updateDefaultRoles(String[] defaultRoles);
-
-    // Key is clientId
-    Map<String, ClientModel> getClientNameMap();
-
-    List<ClientModel> getClients();
-
-    ClientModel addClient(String name);
-
-    ClientModel addClient(String id, String clientId);
-
-    boolean removeClient(String id);
-
-    ClientModel getClientById(String id);
-    ClientModel getClientByClientId(String clientId);
-
-    void updateRequiredCredentials(Set<String> creds);
-
-    Map<String, String> getBrowserSecurityHeaders();
-    void setBrowserSecurityHeaders(Map<String, String> headers);
-
-    Map<String, String> getSmtpConfig();
-
-    void setSmtpConfig(Map<String, String> smtpConfig);
-
-    List<AuthenticationFlowModel> getAuthenticationFlows();
-    AuthenticationFlowModel getFlowByAlias(String alias);
-    AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model);
-    AuthenticationFlowModel getAuthenticationFlowById(String id);
-    void removeAuthenticationFlow(AuthenticationFlowModel model);
-    void updateAuthenticationFlow(AuthenticationFlowModel model);
-
-    List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId);
-    AuthenticationExecutionModel getAuthenticationExecutionById(String id);
-    AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model);
-    void updateAuthenticatorExecution(AuthenticationExecutionModel model);
-    void removeAuthenticatorExecution(AuthenticationExecutionModel model);
-
-
-    List<AuthenticatorConfigModel> getAuthenticatorConfigs();
-    AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model);
-    void updateAuthenticatorConfig(AuthenticatorConfigModel model);
-    void removeAuthenticatorConfig(AuthenticatorConfigModel model);
-    AuthenticatorConfigModel getAuthenticatorConfigById(String id);
-    AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias);
-
-    List<RequiredActionProviderModel> getRequiredActionProviders();
-    RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model);
-    void updateRequiredActionProvider(RequiredActionProviderModel model);
-    void removeRequiredActionProvider(RequiredActionProviderModel model);
-    RequiredActionProviderModel getRequiredActionProviderById(String id);
-    RequiredActionProviderModel getRequiredActionProviderByAlias(String alias);
-
-    List<IdentityProviderModel> getIdentityProviders();
-    IdentityProviderModel getIdentityProviderByAlias(String alias);
-    void addIdentityProvider(IdentityProviderModel identityProvider);
-    void removeIdentityProviderByAlias(String alias);
-    void updateIdentityProvider(IdentityProviderModel identityProvider);
-    Set<IdentityProviderMapperModel> getIdentityProviderMappers();
-    Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias);
-    IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model);
-    void removeIdentityProviderMapper(IdentityProviderMapperModel mapping);
-    void updateIdentityProviderMapper(IdentityProviderMapperModel mapping);
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id);
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String brokerAlias, String name);
-
-    // Should return list sorted by UserFederationProviderModel.priority
-    List<UserFederationProviderModel> getUserFederationProviders();
-
-    UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync);
-    void updateUserFederationProvider(UserFederationProviderModel provider);
-    void removeUserFederationProvider(UserFederationProviderModel provider);
-    void setUserFederationProviders(List<UserFederationProviderModel> providers);
-
-    Set<UserFederationMapperModel> getUserFederationMappers();
-    Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId);
-    UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper);
-    void removeUserFederationMapper(UserFederationMapperModel mapper);
-    void updateUserFederationMapper(UserFederationMapperModel mapper);
-    UserFederationMapperModel getUserFederationMapperById(String id);
-    UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name);
-
-    String getLoginTheme();
-
-    void setLoginTheme(String name);
-
-    String getAccountTheme();
-
-    void setAccountTheme(String name);
-
-    String getAdminTheme();
-
-    void setAdminTheme(String name);
-
-    String getEmailTheme();
-
-    void setEmailTheme(String name);
-
-
-    /**
-     * Time in seconds since epoc
-     *
-     * @return
-     */
-    int getNotBefore();
-
-    void setNotBefore(int notBefore);
-
-    boolean removeRoleById(String id);
-
-    boolean isEventsEnabled();
-
-    void setEventsEnabled(boolean enabled);
-
-    long getEventsExpiration();
-
-    void setEventsExpiration(long expiration);
-
-    Set<String> getEventsListeners();
-
-    void setEventsListeners(Set<String> listeners);
-    
-    Set<String> getEnabledEventTypes();
-
-    void setEnabledEventTypes(Set<String> enabledEventTypes);
-    
-    boolean isAdminEventsEnabled();
-
-    void setAdminEventsEnabled(boolean enabled);
-    
-    boolean isAdminEventsDetailsEnabled();
-
-    void setAdminEventsDetailsEnabled(boolean enabled);
-    
-    ClientModel getMasterAdminClient();
-
-    void setMasterAdminClient(ClientModel client);
-
-    boolean isIdentityFederationEnabled();
-
-    boolean isInternationalizationEnabled();
-    void setInternationalizationEnabled(boolean enabled);
-    Set<String> getSupportedLocales();
-    void setSupportedLocales(Set<String> locales);
-    String getDefaultLocale();
-    void setDefaultLocale(String locale);
-}
+package org.keycloak.models;
+
+import org.keycloak.enums.SslRequired;
+import org.keycloak.provider.ProviderEvent;
+
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmModel extends RoleContainerModel {
+    interface RealmCreationEvent extends ProviderEvent {
+        RealmModel getCreatedRealm();
+    }
+
+    interface ClientCreationEvent extends ProviderEvent {
+        ClientModel getCreatedClient();
+    }
+
+    interface UserFederationProviderCreationEvent extends ProviderEvent {
+        UserFederationProviderModel getCreatedFederationProvider();
+        RealmModel getRealm();
+    }
+
+    interface UserFederationMapperEvent extends ProviderEvent {
+        UserFederationMapperModel getFederationMapper();
+        RealmModel getRealm();
+        KeycloakSession getSession();
+    }
+
+    String getId();
+
+    String getName();
+
+    void setName(String name);
+
+    boolean isEnabled();
+
+    void setEnabled(boolean enabled);
+
+    SslRequired getSslRequired();
+
+    void setSslRequired(SslRequired sslRequired);
+
+    boolean isRegistrationAllowed();
+
+    void setRegistrationAllowed(boolean registrationAllowed);
+
+    boolean isRegistrationEmailAsUsername();
+
+    void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername);
+
+    boolean isRememberMe();
+
+    void setRememberMe(boolean rememberMe);
+
+    boolean isEditUsernameAllowed();
+
+    void setEditUsernameAllowed(boolean editUsernameAllowed);
+
+    //--- brute force settings
+    boolean isBruteForceProtected();
+    void setBruteForceProtected(boolean value);
+    int getMaxFailureWaitSeconds();
+    void setMaxFailureWaitSeconds(int val);
+    int getWaitIncrementSeconds();
+    void setWaitIncrementSeconds(int val);
+    int getMinimumQuickLoginWaitSeconds();
+    void setMinimumQuickLoginWaitSeconds(int val);
+    long getQuickLoginCheckMilliSeconds();
+    void setQuickLoginCheckMilliSeconds(long val);
+    int getMaxDeltaTimeSeconds();
+    void setMaxDeltaTimeSeconds(int val);
+    int getFailureFactor();
+    void setFailureFactor(int failureFactor);
+    //--- end brute force settings
+
+
+    boolean isVerifyEmail();
+
+    void setVerifyEmail(boolean verifyEmail);
+
+    boolean isResetPasswordAllowed();
+
+    void setResetPasswordAllowed(boolean resetPasswordAllowed);
+
+    int getSsoSessionIdleTimeout();
+    void setSsoSessionIdleTimeout(int seconds);
+
+    int getSsoSessionMaxLifespan();
+    void setSsoSessionMaxLifespan(int seconds);
+
+    int getAccessTokenLifespan();
+
+    void setAccessTokenLifespan(int seconds);
+
+    int getAccessCodeLifespan();
+
+    void setAccessCodeLifespan(int seconds);
+
+    int getAccessCodeLifespanUserAction();
+
+    void setAccessCodeLifespanUserAction(int seconds);
+
+    int getAccessCodeLifespanLogin();
+
+    void setAccessCodeLifespanLogin(int seconds);
+
+    String getPublicKeyPem();
+
+    void setPublicKeyPem(String publicKeyPem);
+
+    String getPrivateKeyPem();
+
+    void setPrivateKeyPem(String privateKeyPem);
+
+    PublicKey getPublicKey();
+
+    void setPublicKey(PublicKey publicKey);
+
+    String getCodeSecret();
+
+    Key getCodeSecretKey();
+
+    void setCodeSecret(String codeSecret);
+
+    X509Certificate getCertificate();
+    void setCertificate(X509Certificate certificate);
+    String getCertificatePem();
+    void setCertificatePem(String certificate);
+
+    PrivateKey getPrivateKey();
+
+    void setPrivateKey(PrivateKey privateKey);
+
+    List<RequiredCredentialModel> getRequiredCredentials();
+
+    void addRequiredCredential(String cred);
+
+    PasswordPolicy getPasswordPolicy();
+
+    void setPasswordPolicy(PasswordPolicy policy);
+
+    RoleModel getRoleById(String id);
+
+    List<String> getDefaultRoles();
+
+    void addDefaultRole(String name);
+
+    void updateDefaultRoles(String[] defaultRoles);
+
+    // Key is clientId
+    Map<String, ClientModel> getClientNameMap();
+
+    List<ClientModel> getClients();
+
+    ClientModel addClient(String name);
+
+    ClientModel addClient(String id, String clientId);
+
+    boolean removeClient(String id);
+
+    ClientModel getClientById(String id);
+    ClientModel getClientByClientId(String clientId);
+
+    void updateRequiredCredentials(Set<String> creds);
+
+    Map<String, String> getBrowserSecurityHeaders();
+    void setBrowserSecurityHeaders(Map<String, String> headers);
+
+    Map<String, String> getSmtpConfig();
+
+    void setSmtpConfig(Map<String, String> smtpConfig);
+
+    List<AuthenticationFlowModel> getAuthenticationFlows();
+    AuthenticationFlowModel getFlowByAlias(String alias);
+    AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model);
+    AuthenticationFlowModel getAuthenticationFlowById(String id);
+    void removeAuthenticationFlow(AuthenticationFlowModel model);
+    void updateAuthenticationFlow(AuthenticationFlowModel model);
+
+    List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId);
+    AuthenticationExecutionModel getAuthenticationExecutionById(String id);
+    AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model);
+    void updateAuthenticatorExecution(AuthenticationExecutionModel model);
+    void removeAuthenticatorExecution(AuthenticationExecutionModel model);
+
+
+    List<AuthenticatorConfigModel> getAuthenticatorConfigs();
+    AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model);
+    void updateAuthenticatorConfig(AuthenticatorConfigModel model);
+    void removeAuthenticatorConfig(AuthenticatorConfigModel model);
+    AuthenticatorConfigModel getAuthenticatorConfigById(String id);
+    AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias);
+
+    List<RequiredActionProviderModel> getRequiredActionProviders();
+    RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model);
+    void updateRequiredActionProvider(RequiredActionProviderModel model);
+    void removeRequiredActionProvider(RequiredActionProviderModel model);
+    RequiredActionProviderModel getRequiredActionProviderById(String id);
+    RequiredActionProviderModel getRequiredActionProviderByAlias(String alias);
+
+    List<IdentityProviderModel> getIdentityProviders();
+    IdentityProviderModel getIdentityProviderByAlias(String alias);
+    void addIdentityProvider(IdentityProviderModel identityProvider);
+    void removeIdentityProviderByAlias(String alias);
+    void updateIdentityProvider(IdentityProviderModel identityProvider);
+    Set<IdentityProviderMapperModel> getIdentityProviderMappers();
+    Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias);
+    IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model);
+    void removeIdentityProviderMapper(IdentityProviderMapperModel mapping);
+    void updateIdentityProviderMapper(IdentityProviderMapperModel mapping);
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id);
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String brokerAlias, String name);
+
+    // Should return list sorted by UserFederationProviderModel.priority
+    List<UserFederationProviderModel> getUserFederationProviders();
+
+    UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync);
+    void updateUserFederationProvider(UserFederationProviderModel provider);
+    void removeUserFederationProvider(UserFederationProviderModel provider);
+    void setUserFederationProviders(List<UserFederationProviderModel> providers);
+
+    Set<UserFederationMapperModel> getUserFederationMappers();
+    Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId);
+    UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper);
+    void removeUserFederationMapper(UserFederationMapperModel mapper);
+    void updateUserFederationMapper(UserFederationMapperModel mapper);
+    UserFederationMapperModel getUserFederationMapperById(String id);
+    UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name);
+
+    String getLoginTheme();
+
+    void setLoginTheme(String name);
+
+    String getAccountTheme();
+
+    void setAccountTheme(String name);
+
+    String getAdminTheme();
+
+    void setAdminTheme(String name);
+
+    String getEmailTheme();
+
+    void setEmailTheme(String name);
+
+
+    /**
+     * Time in seconds since epoc
+     *
+     * @return
+     */
+    int getNotBefore();
+
+    void setNotBefore(int notBefore);
+
+    boolean removeRoleById(String id);
+
+    boolean isEventsEnabled();
+
+    void setEventsEnabled(boolean enabled);
+
+    long getEventsExpiration();
+
+    void setEventsExpiration(long expiration);
+
+    Set<String> getEventsListeners();
+
+    void setEventsListeners(Set<String> listeners);
+    
+    Set<String> getEnabledEventTypes();
+
+    void setEnabledEventTypes(Set<String> enabledEventTypes);
+    
+    boolean isAdminEventsEnabled();
+
+    void setAdminEventsEnabled(boolean enabled);
+    
+    boolean isAdminEventsDetailsEnabled();
+
+    void setAdminEventsDetailsEnabled(boolean enabled);
+    
+    ClientModel getMasterAdminClient();
+
+    void setMasterAdminClient(ClientModel client);
+
+    boolean isIdentityFederationEnabled();
+
+    boolean isInternationalizationEnabled();
+    void setInternationalizationEnabled(boolean enabled);
+    Set<String> getSupportedLocales();
+    void setSupportedLocales(Set<String> locales);
+    String getDefaultLocale();
+    void setDefaultLocale(String locale);
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmProvider.java b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
index 4556002..8e864cf 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
@@ -1,27 +1,27 @@
-package org.keycloak.models;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.provider.Provider;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RealmProvider extends Provider {
-
-    // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
-    MigrationModel getMigrationModel();
-    RealmModel createRealm(String name);
-    RealmModel createRealm(String id, String name);
-    RealmModel getRealm(String id);
-    RealmModel getRealmByName(String name);
-
-    RoleModel getRoleById(String id, RealmModel realm);
-    ClientModel getClientById(String id, RealmModel realm);
-    List<RealmModel> getRealms();
-    boolean removeRealm(String id);
-
-    void close();
-}
+package org.keycloak.models;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.provider.Provider;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmProvider extends Provider {
+
+    // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
+    MigrationModel getMigrationModel();
+    RealmModel createRealm(String name);
+    RealmModel createRealm(String id, String name);
+    RealmModel getRealm(String id);
+    RealmModel getRealmByName(String name);
+
+    RoleModel getRoleById(String id, RealmModel realm);
+    ClientModel getClientById(String id, RealmModel realm);
+    List<RealmModel> getRealms();
+    boolean removeRealm(String id);
+
+    void close();
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RealmProviderFactory.java b/model/api/src/main/java/org/keycloak/models/RealmProviderFactory.java
index d11f0b8..21c6fad 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmProviderFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RealmProviderFactory extends ProviderFactory<RealmProvider> {
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmProviderFactory extends ProviderFactory<RealmProvider> {
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java b/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
index a32a23c..e1c356b 100755
--- a/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RequiredActionProviderModel.java
@@ -1,82 +1,82 @@
-package org.keycloak.models;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class RequiredActionProviderModel {
-
-    private String id;
-    private String alias;
-    private String name;
-    private String providerId;
-    private boolean enabled;
-    private boolean defaultAction;
-    private Map<String, String> config = new HashMap<String, String>();
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    /**
-     * Used for display purposes.  Probably should clean this code up and make alias and name the same, but
-     * the old code references an Enum and the admin console creates a "friendly" name for each enum.
-     *
-     * @return
-     */
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public boolean isDefaultAction() {
-        return defaultAction;
-    }
-
-    public void setDefaultAction(boolean defaultAction) {
-        this.defaultAction = defaultAction;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.models;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class RequiredActionProviderModel {
+
+    private String id;
+    private String alias;
+    private String name;
+    private String providerId;
+    private boolean enabled;
+    private boolean defaultAction;
+    private Map<String, String> config = new HashMap<String, String>();
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    /**
+     * Used for display purposes.  Probably should clean this code up and make alias and name the same, but
+     * the old code references an Enum and the admin console creates a "friendly" name for each enum.
+     *
+     * @return
+     */
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public boolean isDefaultAction() {
+        return defaultAction;
+    }
+
+    public void setDefaultAction(boolean defaultAction) {
+        this.defaultAction = defaultAction;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RequiredCredentialModel.java b/model/api/src/main/java/org/keycloak/models/RequiredCredentialModel.java
index ec82abd..84cf92c 100755
--- a/model/api/src/main/java/org/keycloak/models/RequiredCredentialModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RequiredCredentialModel.java
@@ -1,96 +1,96 @@
-package org.keycloak.models;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RequiredCredentialModel implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    protected String type;
-    protected boolean input;
-    protected boolean secret;
-    protected String formLabel;
-
-    public RequiredCredentialModel() {
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public boolean isInput() {
-        return input;
-    }
-
-    public void setInput(boolean input) {
-        this.input = input;
-    }
-
-    public boolean isSecret() {
-        return secret;
-    }
-
-    public void setSecret(boolean secret) {
-        this.secret = secret;
-    }
-
-    public String getFormLabel() {
-        return formLabel;
-    }
-
-    public void setFormLabel(String formLabel) {
-        this.formLabel = formLabel;
-    }
-
-    public static final Map<String, RequiredCredentialModel> BUILT_IN;
-    public static final RequiredCredentialModel PASSWORD;
-    public static final RequiredCredentialModel TOTP;
-    public static final RequiredCredentialModel CLIENT_CERT;
-    public static final RequiredCredentialModel SECRET;
-    public static final RequiredCredentialModel KERBEROS;
-
-    static {
-        Map<String, RequiredCredentialModel> map = new HashMap<String, RequiredCredentialModel>();
-        PASSWORD = new RequiredCredentialModel();
-        PASSWORD.setType(UserCredentialModel.PASSWORD);
-        PASSWORD.setInput(true);
-        PASSWORD.setSecret(true);
-        PASSWORD.setFormLabel("password");
-        map.put(PASSWORD.getType(), PASSWORD);
-        SECRET = new RequiredCredentialModel();
-        SECRET.setType(UserCredentialModel.SECRET);
-        SECRET.setInput(false);
-        SECRET.setSecret(true);
-        SECRET.setFormLabel("secret");
-        map.put(SECRET.getType(), SECRET);
-        TOTP = new RequiredCredentialModel();
-        TOTP.setType(UserCredentialModel.TOTP);
-        TOTP.setInput(true);
-        TOTP.setSecret(false);
-        TOTP.setFormLabel("authenticatorCode");
-        map.put(TOTP.getType(), TOTP);
-        CLIENT_CERT = new RequiredCredentialModel();
-        CLIENT_CERT.setType(UserCredentialModel.CLIENT_CERT);
-        CLIENT_CERT.setInput(false);
-        CLIENT_CERT.setSecret(false);
-        CLIENT_CERT.setFormLabel("clientCertificate");
-        map.put(CLIENT_CERT.getType(), CLIENT_CERT);
-        KERBEROS = new RequiredCredentialModel();
-        KERBEROS.setType(UserCredentialModel.KERBEROS);
-        KERBEROS.setInput(false);
-        KERBEROS.setSecret(false);
-        KERBEROS.setFormLabel("kerberos");
-        map.put(KERBEROS.getType(), KERBEROS);
-        BUILT_IN = Collections.unmodifiableMap(map);
-    }
-}
+package org.keycloak.models;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RequiredCredentialModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    protected String type;
+    protected boolean input;
+    protected boolean secret;
+    protected String formLabel;
+
+    public RequiredCredentialModel() {
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public boolean isInput() {
+        return input;
+    }
+
+    public void setInput(boolean input) {
+        this.input = input;
+    }
+
+    public boolean isSecret() {
+        return secret;
+    }
+
+    public void setSecret(boolean secret) {
+        this.secret = secret;
+    }
+
+    public String getFormLabel() {
+        return formLabel;
+    }
+
+    public void setFormLabel(String formLabel) {
+        this.formLabel = formLabel;
+    }
+
+    public static final Map<String, RequiredCredentialModel> BUILT_IN;
+    public static final RequiredCredentialModel PASSWORD;
+    public static final RequiredCredentialModel TOTP;
+    public static final RequiredCredentialModel CLIENT_CERT;
+    public static final RequiredCredentialModel SECRET;
+    public static final RequiredCredentialModel KERBEROS;
+
+    static {
+        Map<String, RequiredCredentialModel> map = new HashMap<String, RequiredCredentialModel>();
+        PASSWORD = new RequiredCredentialModel();
+        PASSWORD.setType(UserCredentialModel.PASSWORD);
+        PASSWORD.setInput(true);
+        PASSWORD.setSecret(true);
+        PASSWORD.setFormLabel("password");
+        map.put(PASSWORD.getType(), PASSWORD);
+        SECRET = new RequiredCredentialModel();
+        SECRET.setType(UserCredentialModel.SECRET);
+        SECRET.setInput(false);
+        SECRET.setSecret(true);
+        SECRET.setFormLabel("secret");
+        map.put(SECRET.getType(), SECRET);
+        TOTP = new RequiredCredentialModel();
+        TOTP.setType(UserCredentialModel.TOTP);
+        TOTP.setInput(true);
+        TOTP.setSecret(false);
+        TOTP.setFormLabel("authenticatorCode");
+        map.put(TOTP.getType(), TOTP);
+        CLIENT_CERT = new RequiredCredentialModel();
+        CLIENT_CERT.setType(UserCredentialModel.CLIENT_CERT);
+        CLIENT_CERT.setInput(false);
+        CLIENT_CERT.setSecret(false);
+        CLIENT_CERT.setFormLabel("clientCertificate");
+        map.put(CLIENT_CERT.getType(), CLIENT_CERT);
+        KERBEROS = new RequiredCredentialModel();
+        KERBEROS.setType(UserCredentialModel.KERBEROS);
+        KERBEROS.setInput(false);
+        KERBEROS.setSecret(false);
+        KERBEROS.setFormLabel("kerberos");
+        map.put(KERBEROS.getType(), KERBEROS);
+        BUILT_IN = Collections.unmodifiableMap(map);
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java b/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java
index f8d0000..f288de3 100755
--- a/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RoleContainerModel.java
@@ -1,20 +1,20 @@
-package org.keycloak.models;
-
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RoleContainerModel {
-    RoleModel getRole(String name);
-
-    RoleModel addRole(String name);
-
-    RoleModel addRole(String id, String name);
-
-    boolean removeRole(RoleModel role);
-
-    Set<RoleModel> getRoles();
-
-}
+package org.keycloak.models;
+
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RoleContainerModel {
+    RoleModel getRole(String name);
+
+    RoleModel addRole(String name);
+
+    RoleModel addRole(String id, String name);
+
+    boolean removeRole(RoleModel role);
+
+    Set<RoleModel> getRoles();
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/RoleModel.java b/model/api/src/main/java/org/keycloak/models/RoleModel.java
index 49dabeb..c296795 100755
--- a/model/api/src/main/java/org/keycloak/models/RoleModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RoleModel.java
@@ -1,32 +1,32 @@
-package org.keycloak.models;
-
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RoleModel {
-    String getName();
-
-    String getDescription();
-
-    void setDescription(String description);
-
-    String getId();
-
-    void setName(String name);
-
-    boolean isComposite();
-
-    void addCompositeRole(RoleModel role);
-
-    void removeCompositeRole(RoleModel role);
-
-    Set<RoleModel> getComposites();
-
-    RoleContainerModel getContainer();
-
-    boolean hasRole(RoleModel role);
-
-}
+package org.keycloak.models;
+
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RoleModel {
+    String getName();
+
+    String getDescription();
+
+    void setDescription(String description);
+
+    String getId();
+
+    void setName(String name);
+
+    boolean isComposite();
+
+    void addCompositeRole(RoleModel role);
+
+    void removeCompositeRole(RoleModel role);
+
+    Set<RoleModel> getComposites();
+
+    RoleContainerModel getContainer();
+
+    boolean hasRole(RoleModel role);
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
index 6515ab0..4619eb4 100755
--- a/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ScopeMapperModel.java
@@ -1,9 +1,9 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ScopeMapperModel {
-
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ScopeMapperModel {
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
index 083eea8..97f6b34 100755
--- a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java
@@ -1,92 +1,92 @@
-package org.keycloak.models;
-
-import java.util.UUID;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserCredentialModel {
-    public static final String PASSWORD = "password";
-    public static final String PASSWORD_HISTORY = "password-history";
-    public static final String PASSWORD_TOKEN = "password-token";
-
-    // Secret is same as password but it is not hashed
-    public static final String SECRET = "secret";
-    public static final String TOTP = "totp";
-    public static final String CLIENT_CERT = "cert";
-    public static final String KERBEROS = "kerberos";
-
-    protected String type;
-    protected String value;
-    protected String device;
-
-    public UserCredentialModel() {
-    }
-
-    public static UserCredentialModel password(String password) {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(PASSWORD);
-        model.setValue(password);
-        return model;
-    }
-    public static UserCredentialModel passwordToken(String passwordToken) {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(PASSWORD_TOKEN);
-        model.setValue(passwordToken);
-        return model;
-    }
-
-    public static UserCredentialModel secret(String password) {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(SECRET);
-        model.setValue(password);
-        return model;
-    }
-
-    public static UserCredentialModel totp(String key) {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(TOTP);
-        model.setValue(key);
-        return model;
-    }
-
-    public static UserCredentialModel kerberos(String token) {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(KERBEROS);
-        model.setValue(token);
-        return model;
-    }
-
-    public static UserCredentialModel generateSecret() {
-        UserCredentialModel model = new UserCredentialModel();
-        model.setType(SECRET);
-        model.setValue(UUID.randomUUID().toString());
-        return model;
-    }
-
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public String getDevice() {
-        return device;
-    }
-
-    public void setDevice(String device) {
-        this.device = device;
-    }
-}
+package org.keycloak.models;
+
+import java.util.UUID;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserCredentialModel {
+    public static final String PASSWORD = "password";
+    public static final String PASSWORD_HISTORY = "password-history";
+    public static final String PASSWORD_TOKEN = "password-token";
+
+    // Secret is same as password but it is not hashed
+    public static final String SECRET = "secret";
+    public static final String TOTP = "totp";
+    public static final String CLIENT_CERT = "cert";
+    public static final String KERBEROS = "kerberos";
+
+    protected String type;
+    protected String value;
+    protected String device;
+
+    public UserCredentialModel() {
+    }
+
+    public static UserCredentialModel password(String password) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(PASSWORD);
+        model.setValue(password);
+        return model;
+    }
+    public static UserCredentialModel passwordToken(String passwordToken) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(PASSWORD_TOKEN);
+        model.setValue(passwordToken);
+        return model;
+    }
+
+    public static UserCredentialModel secret(String password) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(SECRET);
+        model.setValue(password);
+        return model;
+    }
+
+    public static UserCredentialModel totp(String key) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(TOTP);
+        model.setValue(key);
+        return model;
+    }
+
+    public static UserCredentialModel kerberos(String token) {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(KERBEROS);
+        model.setValue(token);
+        return model;
+    }
+
+    public static UserCredentialModel generateSecret() {
+        UserCredentialModel model = new UserCredentialModel();
+        model.setType(SECRET);
+        model.setValue(UUID.randomUUID().toString());
+        return model;
+    }
+
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getDevice() {
+        return device;
+    }
+
+    public void setDevice(String device) {
+        this.device = device;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
index 8bca31c..8e34a8a 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -1,450 +1,450 @@
-package org.keycloak.models;
-
-import org.jboss.logging.Logger;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserFederationManager implements UserProvider {
-
-    private static final Logger logger = Logger.getLogger(UserFederationManager.class);
-
-    protected KeycloakSession session;
-
-    // Set of already validated/proxied federation users during this session. Key is user ID
-    private Map<String, UserModel> managedUsers = new HashMap<>();
-
-    public UserFederationManager(KeycloakSession session) {
-        this.session = session;
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
-        UserModel user = session.userStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
-        return registerWithFederation(realm, user);
-    }
-
-    protected UserFederationProvider getFederationProvider(UserFederationProviderModel model) {
-        UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, model.getProviderName());
-        return factory.getInstance(session, model);
-
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String username) {
-        UserModel user = session.userStorage().addUser(realm, username.toLowerCase());
-        return registerWithFederation(realm, user);
-    }
-
-    protected UserModel registerWithFederation(RealmModel realm, UserModel user) {
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            if (fed.synchronizeRegistrations()) {
-                user.setFederationLink(federation.getId());
-                UserModel registered = fed.register(realm, user);
-                managedUsers.put(registered.getId(), registered);
-                return registered;
-            }
-        }
-        return user;
-    }
-
-    protected UserFederationProvider getFederationLink(RealmModel realm, UserModel user) {
-        if (user.getFederationLink() == null) return null;
-        for (UserFederationProviderModel fed : realm.getUserFederationProviders()) {
-            if (fed.getId().equals(user.getFederationLink())) {
-                return getFederationProvider(fed);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        UserFederationProvider link = getFederationLink(realm, user);
-        if (link != null) {
-            boolean fedRemoved = link.removeUser(realm, user);
-            if (fedRemoved) {
-                boolean localRemoved = session.userStorage().removeUser(realm, user);
-                managedUsers.remove(user.getId());
-                if (!localRemoved) {
-                    logger.warn("User removed from federation provider, but failed to remove him from keycloak model");
-                }
-                return localRemoved;
-            } else {
-                logger.warn("Failed to remove user from federation provider");
-                return false;
-            }
-        }
-        return session.userStorage().removeUser(realm, user);
-
-    }
-
-    protected void validateUser(RealmModel realm, UserModel user) {
-        if (managedUsers.containsKey(user.getId())) {
-            return;
-        }
-
-        UserFederationProvider link = getFederationLink(realm, user);
-        if (link != null  && !link.isValid(realm, user)) {
-            deleteInvalidUser(realm, user);
-            throw new IllegalStateException("Federated user no longer valid");
-        }
-
-    }
-
-    protected void deleteInvalidUser(RealmModel realm, UserModel user) {
-        KeycloakSession tx = session.getKeycloakSessionFactory().create();
-        try {
-            tx.getTransaction().begin();
-            RealmModel realmModel = tx.realms().getRealm(realm.getId());
-            if (realmModel == null) return;
-            UserModel deletedUser = tx.userStorage().getUserById(user.getId(), realmModel);
-            tx.userStorage().removeUser(realmModel, deletedUser);
-            logger.infof("Removed invalid user '%s'", user.getUsername());
-            tx.getTransaction().commit();
-        } finally {
-            tx.close();
-        }
-    }
-
-
-    protected UserModel validateAndProxyUser(RealmModel realm, UserModel user) {
-        UserModel managed = managedUsers.get(user.getId());
-        if (managed != null) {
-            return managed;
-        }
-
-        UserFederationProvider link = getFederationLink(realm, user);
-        if (link != null) {
-            UserModel validatedProxyUser = link.validateAndProxy(realm, user);
-            if (validatedProxyUser != null) {
-                managedUsers.put(user.getId(), validatedProxyUser);
-                return validatedProxyUser;
-            } else {
-                deleteInvalidUser(realm, user);
-                return null;
-            }
-        }
-        return user;
-    }
-
-    @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
-        validateUser(realm, user);
-        session.userStorage().addFederatedIdentity(realm, user, socialLink);
-    }
-
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        session.userStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
-    }
-
-    @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
-        validateUser(realm, user);
-        if (user == null) throw new IllegalStateException("Federated user no longer valid");
-        return session.userStorage().removeFederatedIdentity(realm, user, socialProvider);
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        UserModel user = session.userStorage().getUserById(id, realm);
-        if (user != null) {
-            user = validateAndProxyUser(realm, user);
-        }
-        return user;
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        UserModel user = session.userStorage().getUserByUsername(username.toLowerCase(), realm);
-        if (user != null) {
-            user = validateAndProxyUser(realm, user);
-            if (user != null) return user;
-        }
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            user = fed.getUserByUsername(realm, username);
-            if (user != null) return user;
-        }
-        return user;
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        UserModel user = session.userStorage().getUserByEmail(email.toLowerCase(), realm);
-        if (user != null) {
-            user = validateAndProxyUser(realm, user);
-            if (user != null) return user;
-        }
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            user = fed.getUserByEmail(realm, email);
-            if (user != null) return user;
-        }
-        return user;
-    }
-
-    @Override
-    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
-        UserModel user = session.userStorage().getUserByFederatedIdentity(socialLink, realm);
-        if (user != null) {
-            user = validateAndProxyUser(realm, user);
-        }
-        return user;
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return getUsers(realm, 0, Integer.MAX_VALUE - 1);
-
-    }
-
-    @Override
-    public int getUsersCount(RealmModel realm) {
-        return session.userStorage().getUsersCount(realm);
-    }
-
-    interface PaginatedQuery {
-        List<UserModel> query(RealmModel realm, int first, int max);
-    }
-
-    protected List<UserModel> query(PaginatedQuery pagedQuery, RealmModel realm, int firstResult, int maxResults) {
-        List<UserModel> results = new LinkedList<UserModel>();
-        if (maxResults == 0) return results;
-        int first = firstResult;
-        int max = maxResults;
-        do {
-            List<UserModel> query = pagedQuery.query(realm, first, max);
-            if (query == null || query.size() == 0) return results;
-            int added = 0;
-            for (UserModel user : query) {
-                user = validateAndProxyUser(realm, user);
-                if (user == null) continue;
-                results.add(user);
-                added++;
-            }
-            if (results.size() == maxResults) return results;
-            if (query.size() < max) return results;
-            first = query.size();
-            max -= added;
-            if (max <= 0) return results;
-        } while (true);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
-        return query(new PaginatedQuery() {
-            @Override
-            public List<UserModel> query(RealmModel realm, int first, int max) {
-                return session.userStorage().getUsers(realm, first, max);
-            }
-        }, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
-    }
-
-    void federationLoad(RealmModel realm, Map<String, String> attributes) {
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            fed.searchByAttributes(attributes, realm, 30);
-        }
-    }
-
-    @Override
-    public List<UserModel> searchForUser(final String search, RealmModel realm, int firstResult, int maxResults) {
-        Map<String, String> attributes = new HashMap<String, String>();
-        int spaceIndex = search.lastIndexOf(' ');
-        if (spaceIndex > -1) {
-            String firstName = search.substring(0, spaceIndex).trim();
-            String lastName = search.substring(spaceIndex).trim();
-            attributes.put(UserModel.FIRST_NAME, firstName);
-            attributes.put(UserModel.LAST_NAME, lastName);
-        } else if (search.indexOf('@') > -1) {
-            attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
-            attributes.put(UserModel.EMAIL, search.trim().toLowerCase());
-        } else {
-            attributes.put(UserModel.LAST_NAME, search.trim());
-            attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
-        }
-        federationLoad(realm, attributes);
-        return query(new PaginatedQuery() {
-            @Override
-            public List<UserModel> query(RealmModel realm, int first, int max) {
-                return session.userStorage().searchForUser(search, realm, first, max);
-            }
-        }, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return searchForUserByAttributes(attributes, realm, 0, Integer.MAX_VALUE - 1);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(final Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
-        federationLoad(realm, attributes);
-        return query(new PaginatedQuery() {
-            @Override
-            public List<UserModel> query(RealmModel realm, int first, int max) {
-                return session.userStorage().searchForUserByAttributes(attributes, realm, first, max);
-            }
-        }, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
-        validateUser(realm, user);
-        if (user == null) throw new IllegalStateException("Federated user no longer valid");
-        return session.userStorage().getFederatedIdentities(user, realm);
-    }
-
-    @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        validateUser(realm, user);
-        if (user == null) throw new IllegalStateException("Federated user no longer valid");
-        return session.userStorage().getFederatedIdentity(user, socialProvider, realm);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            fed.preRemove(realm);
-        }
-        session.userStorage().preRemove(realm);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, UserFederationProviderModel model) {
-        session.userStorage().preRemove(realm, model);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
-            UserFederationProvider fed = getFederationProvider(federation);
-            fed.preRemove(realm, role);
-        }
-        session.userStorage().preRemove(realm, role);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, ClientModel client) {
-        session.userStorage().preRemove(realm, client);
-    }
-
-    @Override
-    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
-        session.userStorage().preRemove(client, protocolMapper);
-    }
-
-    public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
-        if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
-            if (realm.getPasswordPolicy() != null) {
-                PasswordPolicy.Error error = realm.getPasswordPolicy().validate(user, credential.getValue());
-                if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
-            }
-        }
-        user.updateCredential(credential);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        UserFederationProvider link = getFederationLink(realm, user);
-        if (link != null) {
-            validateUser(realm, user);
-            Set<String> supportedCredentialTypes = link.getSupportedCredentialTypes(user);
-            if (supportedCredentialTypes.size() > 0) {
-                List<UserCredentialModel> fedCreds = new ArrayList<UserCredentialModel>();
-                List<UserCredentialModel> localCreds = new ArrayList<UserCredentialModel>();
-                for (UserCredentialModel cred : input) {
-                    if (supportedCredentialTypes.contains(cred.getType())) {
-                        fedCreds.add(cred);
-                    } else {
-                        localCreds.add(cred);
-                    }
-                }
-                if (!link.validCredentials(realm, user, fedCreds)) {
-                    return false;
-                }
-                return session.userStorage().validCredentials(realm, user, localCreds);
-            }
-        }
-        return session.userStorage().validCredentials(realm, user, input);
-    }
-
-    /**
-     * Is the user configured to use this credential type
-     *
-     * @return
-     */
-    public boolean configuredForCredentialType(String type, RealmModel realm, UserModel user) {
-        UserFederationProvider link = getFederationLink(realm, user);
-        if (link != null) {
-            Set<String> supportedCredentialTypes = link.getSupportedCredentialTypes(user);
-            if (supportedCredentialTypes.contains(type)) return true;
-        }
-        List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
-        for (UserCredentialValueModel cred : creds) {
-            if (cred.getType().equals(type)) return true;
-        }
-        return false;
-    }
-
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return validCredentials(realm, user, Arrays.asList(input));
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
-        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
-        List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
-        for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
-            fedProviders.add(getFederationProvider(fedProviderModel));
-        }
-
-        CredentialValidationOutput result = null;
-        for (UserCredentialModel cred : input) {
-            UserFederationProvider providerSupportingCreds = null;
-
-            // Find first provider, which supports required credential type
-            for (UserFederationProvider fedProvider : fedProviders) {
-                if (fedProvider.getSupportedCredentialTypes().contains(cred.getType())) {
-                    providerSupportingCreds = fedProvider;
-                    break;
-                }
-            }
-
-            if (providerSupportingCreds == null) {
-                logger.warn("Don't have provider supporting credentials of type " + cred.getType());
-                return CredentialValidationOutput.failed();
-            }
-
-            logger.debug("Found provider [" + providerSupportingCreds + "] supporting credentials of type " + cred.getType());
-            CredentialValidationOutput currentResult = providerSupportingCreds.validCredentials(realm, cred);
-            result = (result == null) ? currentResult : result.merge(currentResult);
-        }
-
-        // For now, validCredentials(realm, input) is not supported for local userProviders
-        return (result != null) ? result : CredentialValidationOutput.failed();
-    }
-
-    @Override
-    public void close() {
-    }
-}
+package org.keycloak.models;
+
+import org.jboss.logging.Logger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserFederationManager implements UserProvider {
+
+    private static final Logger logger = Logger.getLogger(UserFederationManager.class);
+
+    protected KeycloakSession session;
+
+    // Set of already validated/proxied federation users during this session. Key is user ID
+    private Map<String, UserModel> managedUsers = new HashMap<>();
+
+    public UserFederationManager(KeycloakSession session) {
+        this.session = session;
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+        UserModel user = session.userStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
+        return registerWithFederation(realm, user);
+    }
+
+    protected UserFederationProvider getFederationProvider(UserFederationProviderModel model) {
+        UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, model.getProviderName());
+        return factory.getInstance(session, model);
+
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String username) {
+        UserModel user = session.userStorage().addUser(realm, username.toLowerCase());
+        return registerWithFederation(realm, user);
+    }
+
+    protected UserModel registerWithFederation(RealmModel realm, UserModel user) {
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            if (fed.synchronizeRegistrations()) {
+                user.setFederationLink(federation.getId());
+                UserModel registered = fed.register(realm, user);
+                managedUsers.put(registered.getId(), registered);
+                return registered;
+            }
+        }
+        return user;
+    }
+
+    protected UserFederationProvider getFederationLink(RealmModel realm, UserModel user) {
+        if (user.getFederationLink() == null) return null;
+        for (UserFederationProviderModel fed : realm.getUserFederationProviders()) {
+            if (fed.getId().equals(user.getFederationLink())) {
+                return getFederationProvider(fed);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        UserFederationProvider link = getFederationLink(realm, user);
+        if (link != null) {
+            boolean fedRemoved = link.removeUser(realm, user);
+            if (fedRemoved) {
+                boolean localRemoved = session.userStorage().removeUser(realm, user);
+                managedUsers.remove(user.getId());
+                if (!localRemoved) {
+                    logger.warn("User removed from federation provider, but failed to remove him from keycloak model");
+                }
+                return localRemoved;
+            } else {
+                logger.warn("Failed to remove user from federation provider");
+                return false;
+            }
+        }
+        return session.userStorage().removeUser(realm, user);
+
+    }
+
+    protected void validateUser(RealmModel realm, UserModel user) {
+        if (managedUsers.containsKey(user.getId())) {
+            return;
+        }
+
+        UserFederationProvider link = getFederationLink(realm, user);
+        if (link != null  && !link.isValid(realm, user)) {
+            deleteInvalidUser(realm, user);
+            throw new IllegalStateException("Federated user no longer valid");
+        }
+
+    }
+
+    protected void deleteInvalidUser(RealmModel realm, UserModel user) {
+        KeycloakSession tx = session.getKeycloakSessionFactory().create();
+        try {
+            tx.getTransaction().begin();
+            RealmModel realmModel = tx.realms().getRealm(realm.getId());
+            if (realmModel == null) return;
+            UserModel deletedUser = tx.userStorage().getUserById(user.getId(), realmModel);
+            tx.userStorage().removeUser(realmModel, deletedUser);
+            logger.infof("Removed invalid user '%s'", user.getUsername());
+            tx.getTransaction().commit();
+        } finally {
+            tx.close();
+        }
+    }
+
+
+    protected UserModel validateAndProxyUser(RealmModel realm, UserModel user) {
+        UserModel managed = managedUsers.get(user.getId());
+        if (managed != null) {
+            return managed;
+        }
+
+        UserFederationProvider link = getFederationLink(realm, user);
+        if (link != null) {
+            UserModel validatedProxyUser = link.validateAndProxy(realm, user);
+            if (validatedProxyUser != null) {
+                managedUsers.put(user.getId(), validatedProxyUser);
+                return validatedProxyUser;
+            } else {
+                deleteInvalidUser(realm, user);
+                return null;
+            }
+        }
+        return user;
+    }
+
+    @Override
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
+        validateUser(realm, user);
+        session.userStorage().addFederatedIdentity(realm, user, socialLink);
+    }
+
+    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+        session.userStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
+    }
+
+    @Override
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
+        validateUser(realm, user);
+        if (user == null) throw new IllegalStateException("Federated user no longer valid");
+        return session.userStorage().removeFederatedIdentity(realm, user, socialProvider);
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        UserModel user = session.userStorage().getUserById(id, realm);
+        if (user != null) {
+            user = validateAndProxyUser(realm, user);
+        }
+        return user;
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        UserModel user = session.userStorage().getUserByUsername(username.toLowerCase(), realm);
+        if (user != null) {
+            user = validateAndProxyUser(realm, user);
+            if (user != null) return user;
+        }
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            user = fed.getUserByUsername(realm, username);
+            if (user != null) return user;
+        }
+        return user;
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        UserModel user = session.userStorage().getUserByEmail(email.toLowerCase(), realm);
+        if (user != null) {
+            user = validateAndProxyUser(realm, user);
+            if (user != null) return user;
+        }
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            user = fed.getUserByEmail(realm, email);
+            if (user != null) return user;
+        }
+        return user;
+    }
+
+    @Override
+    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
+        UserModel user = session.userStorage().getUserByFederatedIdentity(socialLink, realm);
+        if (user != null) {
+            user = validateAndProxyUser(realm, user);
+        }
+        return user;
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getUsers(realm, 0, Integer.MAX_VALUE - 1);
+
+    }
+
+    @Override
+    public int getUsersCount(RealmModel realm) {
+        return session.userStorage().getUsersCount(realm);
+    }
+
+    interface PaginatedQuery {
+        List<UserModel> query(RealmModel realm, int first, int max);
+    }
+
+    protected List<UserModel> query(PaginatedQuery pagedQuery, RealmModel realm, int firstResult, int maxResults) {
+        List<UserModel> results = new LinkedList<UserModel>();
+        if (maxResults == 0) return results;
+        int first = firstResult;
+        int max = maxResults;
+        do {
+            List<UserModel> query = pagedQuery.query(realm, first, max);
+            if (query == null || query.size() == 0) return results;
+            int added = 0;
+            for (UserModel user : query) {
+                user = validateAndProxyUser(realm, user);
+                if (user == null) continue;
+                results.add(user);
+                added++;
+            }
+            if (results.size() == maxResults) return results;
+            if (query.size() < max) return results;
+            first = query.size();
+            max -= added;
+            if (max <= 0) return results;
+        } while (true);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
+        return query(new PaginatedQuery() {
+            @Override
+            public List<UserModel> query(RealmModel realm, int first, int max) {
+                return session.userStorage().getUsers(realm, first, max);
+            }
+        }, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
+    }
+
+    void federationLoad(RealmModel realm, Map<String, String> attributes) {
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            fed.searchByAttributes(attributes, realm, 30);
+        }
+    }
+
+    @Override
+    public List<UserModel> searchForUser(final String search, RealmModel realm, int firstResult, int maxResults) {
+        Map<String, String> attributes = new HashMap<String, String>();
+        int spaceIndex = search.lastIndexOf(' ');
+        if (spaceIndex > -1) {
+            String firstName = search.substring(0, spaceIndex).trim();
+            String lastName = search.substring(spaceIndex).trim();
+            attributes.put(UserModel.FIRST_NAME, firstName);
+            attributes.put(UserModel.LAST_NAME, lastName);
+        } else if (search.indexOf('@') > -1) {
+            attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
+            attributes.put(UserModel.EMAIL, search.trim().toLowerCase());
+        } else {
+            attributes.put(UserModel.LAST_NAME, search.trim());
+            attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
+        }
+        federationLoad(realm, attributes);
+        return query(new PaginatedQuery() {
+            @Override
+            public List<UserModel> query(RealmModel realm, int first, int max) {
+                return session.userStorage().searchForUser(search, realm, first, max);
+            }
+        }, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return searchForUserByAttributes(attributes, realm, 0, Integer.MAX_VALUE - 1);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(final Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
+        federationLoad(realm, attributes);
+        return query(new PaginatedQuery() {
+            @Override
+            public List<UserModel> query(RealmModel realm, int first, int max) {
+                return session.userStorage().searchForUserByAttributes(attributes, realm, first, max);
+            }
+        }, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
+        validateUser(realm, user);
+        if (user == null) throw new IllegalStateException("Federated user no longer valid");
+        return session.userStorage().getFederatedIdentities(user, realm);
+    }
+
+    @Override
+    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
+        validateUser(realm, user);
+        if (user == null) throw new IllegalStateException("Federated user no longer valid");
+        return session.userStorage().getFederatedIdentity(user, socialProvider, realm);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            fed.preRemove(realm);
+        }
+        session.userStorage().preRemove(realm);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, UserFederationProviderModel model) {
+        session.userStorage().preRemove(realm, model);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        for (UserFederationProviderModel federation : realm.getUserFederationProviders()) {
+            UserFederationProvider fed = getFederationProvider(federation);
+            fed.preRemove(realm, role);
+        }
+        session.userStorage().preRemove(realm, role);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, ClientModel client) {
+        session.userStorage().preRemove(realm, client);
+    }
+
+    @Override
+    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
+        session.userStorage().preRemove(client, protocolMapper);
+    }
+
+    public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
+        if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
+            if (realm.getPasswordPolicy() != null) {
+                PasswordPolicy.Error error = realm.getPasswordPolicy().validate(user, credential.getValue());
+                if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
+            }
+        }
+        user.updateCredential(credential);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        UserFederationProvider link = getFederationLink(realm, user);
+        if (link != null) {
+            validateUser(realm, user);
+            Set<String> supportedCredentialTypes = link.getSupportedCredentialTypes(user);
+            if (supportedCredentialTypes.size() > 0) {
+                List<UserCredentialModel> fedCreds = new ArrayList<UserCredentialModel>();
+                List<UserCredentialModel> localCreds = new ArrayList<UserCredentialModel>();
+                for (UserCredentialModel cred : input) {
+                    if (supportedCredentialTypes.contains(cred.getType())) {
+                        fedCreds.add(cred);
+                    } else {
+                        localCreds.add(cred);
+                    }
+                }
+                if (!link.validCredentials(realm, user, fedCreds)) {
+                    return false;
+                }
+                return session.userStorage().validCredentials(realm, user, localCreds);
+            }
+        }
+        return session.userStorage().validCredentials(realm, user, input);
+    }
+
+    /**
+     * Is the user configured to use this credential type
+     *
+     * @return
+     */
+    public boolean configuredForCredentialType(String type, RealmModel realm, UserModel user) {
+        UserFederationProvider link = getFederationLink(realm, user);
+        if (link != null) {
+            Set<String> supportedCredentialTypes = link.getSupportedCredentialTypes(user);
+            if (supportedCredentialTypes.contains(type)) return true;
+        }
+        List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
+        for (UserCredentialValueModel cred : creds) {
+            if (cred.getType().equals(type)) return true;
+        }
+        return false;
+    }
+
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return validCredentials(realm, user, Arrays.asList(input));
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
+        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
+        List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
+        for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
+            fedProviders.add(getFederationProvider(fedProviderModel));
+        }
+
+        CredentialValidationOutput result = null;
+        for (UserCredentialModel cred : input) {
+            UserFederationProvider providerSupportingCreds = null;
+
+            // Find first provider, which supports required credential type
+            for (UserFederationProvider fedProvider : fedProviders) {
+                if (fedProvider.getSupportedCredentialTypes().contains(cred.getType())) {
+                    providerSupportingCreds = fedProvider;
+                    break;
+                }
+            }
+
+            if (providerSupportingCreds == null) {
+                logger.warn("Don't have provider supporting credentials of type " + cred.getType());
+                return CredentialValidationOutput.failed();
+            }
+
+            logger.debug("Found provider [" + providerSupportingCreds + "] supporting credentials of type " + cred.getType());
+            CredentialValidationOutput currentResult = providerSupportingCreds.validCredentials(realm, cred);
+            result = (result == null) ? currentResult : result.merge(currentResult);
+        }
+
+        // For now, validCredentials(realm, input) is not supported for local userProviders
+        return (result != null) ? result : CredentialValidationOutput.failed();
+    }
+
+    @Override
+    public void close() {
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java b/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
index 8fdd45a..f60c21d 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationProvider.java
@@ -1,176 +1,176 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.Provider;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * SPI for plugging in federation storage.  This class is instantiated once per session/request and is closed after
- * the session/request is finished.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserFederationProvider extends Provider {
-
-    public static final String USERNAME = UserModel.USERNAME;
-    public static final String EMAIL = UserModel.EMAIL;
-    public static final String FIRST_NAME = UserModel.FIRST_NAME;
-    public static final String LAST_NAME = UserModel.LAST_NAME;
-
-    /**
-     * Optional type that can be by implementations to describe edit mode of federation storage
-     *
-     */
-    enum EditMode {
-        /**
-         * federation storage is read-only
-         */
-        READ_ONLY,
-        /**
-         * federation storage is writable
-         *
-         */
-        WRITABLE,
-        /**
-         * updates to user are stored locally and not synced with federation storage.
-         *
-         */
-        UNSYNCED
-    }
-
-
-    /**
-     * Gives the provider an option to validate if user still exists in federation backend and then proxy UserModel loaded from local storage.
-     * This method is called whenever a UserModel is pulled from Keycloak local storage.
-     * For example, the LDAP provider proxies the UserModel and does on-demand synchronization with
-     * LDAP whenever UserModel update methods are invoked.  It also overrides UserModel.updateCredential for the
-     * credential types it supports
-     *
-     * @param realm
-     * @param local
-     * @return null if user is no longer valid or proxy object otherwise
-     */
-    UserModel validateAndProxy(RealmModel realm, UserModel local);
-
-    /**
-     * Should user registrations be synchronized with this provider?
-     * FYI, only one provider will be chosen (by priority) to have this synchronization
-     *
-     * @return
-     */
-    boolean synchronizeRegistrations();
-
-    /**
-     * Called if this federation provider has priority and supports synchronized registrations.
-     *
-     * @param realm
-     * @param user
-     * @return
-     */
-    UserModel register(RealmModel realm, UserModel user);
-    boolean removeUser(RealmModel realm, UserModel user);
-
-    /**
-     * Keycloak will search for user in local storage first.  If it can't find the UserModel is local storage,
-     * it will call this method.  You are required to import the returned UserModel into local storage.
-     *
-     * @param realm
-     * @param username
-     * @return
-     */
-    UserModel getUserByUsername(RealmModel realm, String username);
-
-    /**
-     * Keycloak will search for user in local storage first.  If it can't find the UserModel is local storage,
-     * it will call this method.  You are required to import the returned UserModel into local storage.
-     *
-     * @param realm
-     * @param email
-     * @return
-     */
-    UserModel getUserByEmail(RealmModel realm, String email);
-
-    /**
-     * Keycloak does not search in local storage first before calling this method.  The implementation must check
-     * to see if user is already in local storage (KeycloakSession.userStorage()) before doing an import.
-     * Currently only attributes USERNAME, EMAIL, FIRST_NAME and LAST_NAME will be used.
-     *
-     * @param attributes
-     * @param realm
-     * @return
-     */
-    List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults);
-
-    /**
-     * called whenever a Realm is removed
-     *
-     * @param realm
-     */
-    void preRemove(RealmModel realm);
-
-    /**
-     * called before a role is removed.
-     *
-     * @param realm
-     * @param role
-     */
-    void preRemove(RealmModel realm, RoleModel role);
-
-    /**
-     * Is the Keycloak UserModel still valid and/or existing in federated storage?  Keycloak may call this method
-     * in various user operations.  The local storage may be deleted if this method returns false.
-     *
-     * @param realm
-     * @param local
-     * @return
-     */
-    boolean isValid(RealmModel realm, UserModel local);
-
-    /**
-     * What UserCredentialModel types should be handled by this provider for this user?  Keycloak will only call
-     * validCredentials() with the credential types specified in this method.
-     *
-     * @return
-     */
-    Set<String> getSupportedCredentialTypes(UserModel user);
-
-    /**
-     * What UserCredentialModel types should be handled by this provider? This is called in scenarios when we don't know user,
-     * who is going to authenticate (For example Kerberos authentication).
-     *
-     * @return
-     */
-    Set<String> getSupportedCredentialTypes();
-
-    /**
-     * Validate credentials for this user.  This method will only be called with credential parameters supported
-     * by this provider
-     *
-     * @param realm
-     * @param user
-     * @param input
-     * @return
-     */
-    boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
-    boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
-
-    /**
-     * Validate credentials of unknown user. The authenticated user is recognized based on provided credentials and returned back in CredentialValidationOutput
-     * @param realm
-     * @param credential
-     * @return
-     */
-    CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential);
-
-    /**
-     * This method is called at the end of requests.
-     *
-     */
-    void close();
-
-
-
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.Provider;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * SPI for plugging in federation storage.  This class is instantiated once per session/request and is closed after
+ * the session/request is finished.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserFederationProvider extends Provider {
+
+    public static final String USERNAME = UserModel.USERNAME;
+    public static final String EMAIL = UserModel.EMAIL;
+    public static final String FIRST_NAME = UserModel.FIRST_NAME;
+    public static final String LAST_NAME = UserModel.LAST_NAME;
+
+    /**
+     * Optional type that can be by implementations to describe edit mode of federation storage
+     *
+     */
+    enum EditMode {
+        /**
+         * federation storage is read-only
+         */
+        READ_ONLY,
+        /**
+         * federation storage is writable
+         *
+         */
+        WRITABLE,
+        /**
+         * updates to user are stored locally and not synced with federation storage.
+         *
+         */
+        UNSYNCED
+    }
+
+
+    /**
+     * Gives the provider an option to validate if user still exists in federation backend and then proxy UserModel loaded from local storage.
+     * This method is called whenever a UserModel is pulled from Keycloak local storage.
+     * For example, the LDAP provider proxies the UserModel and does on-demand synchronization with
+     * LDAP whenever UserModel update methods are invoked.  It also overrides UserModel.updateCredential for the
+     * credential types it supports
+     *
+     * @param realm
+     * @param local
+     * @return null if user is no longer valid or proxy object otherwise
+     */
+    UserModel validateAndProxy(RealmModel realm, UserModel local);
+
+    /**
+     * Should user registrations be synchronized with this provider?
+     * FYI, only one provider will be chosen (by priority) to have this synchronization
+     *
+     * @return
+     */
+    boolean synchronizeRegistrations();
+
+    /**
+     * Called if this federation provider has priority and supports synchronized registrations.
+     *
+     * @param realm
+     * @param user
+     * @return
+     */
+    UserModel register(RealmModel realm, UserModel user);
+    boolean removeUser(RealmModel realm, UserModel user);
+
+    /**
+     * Keycloak will search for user in local storage first.  If it can't find the UserModel is local storage,
+     * it will call this method.  You are required to import the returned UserModel into local storage.
+     *
+     * @param realm
+     * @param username
+     * @return
+     */
+    UserModel getUserByUsername(RealmModel realm, String username);
+
+    /**
+     * Keycloak will search for user in local storage first.  If it can't find the UserModel is local storage,
+     * it will call this method.  You are required to import the returned UserModel into local storage.
+     *
+     * @param realm
+     * @param email
+     * @return
+     */
+    UserModel getUserByEmail(RealmModel realm, String email);
+
+    /**
+     * Keycloak does not search in local storage first before calling this method.  The implementation must check
+     * to see if user is already in local storage (KeycloakSession.userStorage()) before doing an import.
+     * Currently only attributes USERNAME, EMAIL, FIRST_NAME and LAST_NAME will be used.
+     *
+     * @param attributes
+     * @param realm
+     * @return
+     */
+    List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults);
+
+    /**
+     * called whenever a Realm is removed
+     *
+     * @param realm
+     */
+    void preRemove(RealmModel realm);
+
+    /**
+     * called before a role is removed.
+     *
+     * @param realm
+     * @param role
+     */
+    void preRemove(RealmModel realm, RoleModel role);
+
+    /**
+     * Is the Keycloak UserModel still valid and/or existing in federated storage?  Keycloak may call this method
+     * in various user operations.  The local storage may be deleted if this method returns false.
+     *
+     * @param realm
+     * @param local
+     * @return
+     */
+    boolean isValid(RealmModel realm, UserModel local);
+
+    /**
+     * What UserCredentialModel types should be handled by this provider for this user?  Keycloak will only call
+     * validCredentials() with the credential types specified in this method.
+     *
+     * @return
+     */
+    Set<String> getSupportedCredentialTypes(UserModel user);
+
+    /**
+     * What UserCredentialModel types should be handled by this provider? This is called in scenarios when we don't know user,
+     * who is going to authenticate (For example Kerberos authentication).
+     *
+     * @return
+     */
+    Set<String> getSupportedCredentialTypes();
+
+    /**
+     * Validate credentials for this user.  This method will only be called with credential parameters supported
+     * by this provider
+     *
+     * @param realm
+     * @param user
+     * @param input
+     * @return
+     */
+    boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
+    boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
+
+    /**
+     * Validate credentials of unknown user. The authenticated user is recognized based on provided credentials and returned back in CredentialValidationOutput
+     * @param realm
+     * @param credential
+     * @return
+     */
+    CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential);
+
+    /**
+     * This method is called at the end of requests.
+     *
+     */
+    void close();
+
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserFederationProviderFactory.java b/model/api/src/main/java/org/keycloak/models/UserFederationProviderFactory.java
index 215b86d..5b00ce1 100755
--- a/model/api/src/main/java/org/keycloak/models/UserFederationProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/UserFederationProviderFactory.java
@@ -1,67 +1,67 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.ProviderFactory;
-
-import java.util.Date;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserFederationProviderFactory extends ProviderFactory<UserFederationProvider> {
-    /**
-     * called per Keycloak transaction.
-     *
-     * @param session
-     * @param model
-     * @return
-     */
-    UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model);
-
-    /**
-     * Config options to display in generic admin console page for federation
-     *
-     * @return
-     */
-    Set<String> getConfigurationOptions();
-
-    /**
-     * This is the name of the provider and will be showed in the admin console as an option.
-     *
-     * @return
-     */
-    @Override
-    String getId();
-
-    /**
-     * Sync all users from the provider storage to Keycloak storage. Alternatively can update existing users or remove keycloak users, which are no longer
-     * available in federation storage (depends on the implementation)
-     *
-     * @param sessionFactory
-     * @param realmId
-     * @param model
-     * @return result with count of added/updated/removed users
-     */
-    UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model);
-
-    /**
-     * Sync just changed (added / updated / removed) users from the provider storage to Keycloak storage. This is useful in case
-     * that your storage supports "changelogs" (Tracking what users changed since specified date). It's implementation specific to
-     * decide what exactly will be changed
-     *
-     * @param sessionFactory
-     * @param realmId
-     * @param model
-     * @param lastSync
-     */
-    UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync);
-
-    /**
-     * This method is never called and is only an artifact of ProviderFactory.  Returning null with no implementation is recommended.
-     * @param session
-     * @return
-     */
-    @Override
-    UserFederationProvider create(KeycloakSession session);
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.ProviderFactory;
+
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserFederationProviderFactory extends ProviderFactory<UserFederationProvider> {
+    /**
+     * called per Keycloak transaction.
+     *
+     * @param session
+     * @param model
+     * @return
+     */
+    UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model);
+
+    /**
+     * Config options to display in generic admin console page for federation
+     *
+     * @return
+     */
+    Set<String> getConfigurationOptions();
+
+    /**
+     * This is the name of the provider and will be showed in the admin console as an option.
+     *
+     * @return
+     */
+    @Override
+    String getId();
+
+    /**
+     * Sync all users from the provider storage to Keycloak storage. Alternatively can update existing users or remove keycloak users, which are no longer
+     * available in federation storage (depends on the implementation)
+     *
+     * @param sessionFactory
+     * @param realmId
+     * @param model
+     * @return result with count of added/updated/removed users
+     */
+    UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model);
+
+    /**
+     * Sync just changed (added / updated / removed) users from the provider storage to Keycloak storage. This is useful in case
+     * that your storage supports "changelogs" (Tracking what users changed since specified date). It's implementation specific to
+     * decide what exactly will be changed
+     *
+     * @param sessionFactory
+     * @param realmId
+     * @param model
+     * @param lastSync
+     */
+    UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync);
+
+    /**
+     * This method is never called and is only an artifact of ProviderFactory.  Returning null with no implementation is recommended.
+     * @param session
+     * @return
+     */
+    @Override
+    UserFederationProvider create(KeycloakSession session);
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java
index f81e155..19fdad2 100755
--- a/model/api/src/main/java/org/keycloak/models/UserModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserModel.java
@@ -1,116 +1,116 @@
-package org.keycloak.models;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserModel {
-    public static final String USERNAME = "username";
-    public static final String LAST_NAME = "lastName";
-    public static final String FIRST_NAME = "firstName";
-    public static final String EMAIL = "email";
-    public static final String LOCALE = "locale";
-
-    String getId();
-
-    String getUsername();
-
-    void setUsername(String username);
-    
-    /**
-     * Get timestamp of user creation. May be null for old users created before this feature introduction.
-     */
-    Long getCreatedTimestamp();
-    
-    void setCreatedTimestamp(Long timestamp);
-
-    boolean isEnabled();
-
-    boolean isTotp();
-
-    void setEnabled(boolean enabled);
-
-    /**
-     * Set single value of specified attribute. Remove all other existing values
-     *
-     * @param name
-     * @param value
-     */
-    void setSingleAttribute(String name, String value);
-
-    void setAttribute(String name, List<String> values);
-
-    void removeAttribute(String name);
-
-    /**
-     * @param name
-     * @return null if there is not any value of specified attribute or first value otherwise. Don't throw exception if there are more values of the attribute
-     */
-    String getFirstAttribute(String name);
-
-    /**
-     * @param name
-     * @return list of all attribute values or empty list if there are not any values. Never return null
-     */
-    List<String> getAttribute(String name);
-
-    Map<String, List<String>> getAttributes();
-
-    Set<String> getRequiredActions();
-
-    void addRequiredAction(String action);
-
-    void removeRequiredAction(String action);
-
-    void addRequiredAction(RequiredAction action);
-
-    void removeRequiredAction(RequiredAction action);
-
-    String getFirstName();
-
-    void setFirstName(String firstName);
-
-    String getLastName();
-
-    void setLastName(String lastName);
-
-    String getEmail();
-
-    void setEmail(String email);
-
-    boolean isEmailVerified();
-
-    void setEmailVerified(boolean verified);
-
-    void setTotp(boolean totp);
-
-    void updateCredential(UserCredentialModel cred);
-
-    List<UserCredentialValueModel> getCredentialsDirectly();
-
-    void updateCredentialDirectly(UserCredentialValueModel cred);
-
-    Set<RoleModel> getRealmRoleMappings();
-    Set<RoleModel> getClientRoleMappings(ClientModel app);
-    boolean hasRole(RoleModel role);
-    void grantRole(RoleModel role);
-    Set<RoleModel> getRoleMappings();
-    void deleteRoleMapping(RoleModel role);
-
-    String getFederationLink();
-    void setFederationLink(String link);
-
-    void addConsent(UserConsentModel consent);
-    UserConsentModel getConsentByClient(String clientInternalId);
-    List<UserConsentModel> getConsents();
-    void updateConsent(UserConsentModel consent);
-    boolean revokeConsentForClient(String clientInternalId);
-
-    public static enum RequiredAction {
-        VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
-    }
+package org.keycloak.models;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserModel {
+    public static final String USERNAME = "username";
+    public static final String LAST_NAME = "lastName";
+    public static final String FIRST_NAME = "firstName";
+    public static final String EMAIL = "email";
+    public static final String LOCALE = "locale";
+
+    String getId();
+
+    String getUsername();
+
+    void setUsername(String username);
+    
+    /**
+     * Get timestamp of user creation. May be null for old users created before this feature introduction.
+     */
+    Long getCreatedTimestamp();
+    
+    void setCreatedTimestamp(Long timestamp);
+
+    boolean isEnabled();
+
+    boolean isTotp();
+
+    void setEnabled(boolean enabled);
+
+    /**
+     * Set single value of specified attribute. Remove all other existing values
+     *
+     * @param name
+     * @param value
+     */
+    void setSingleAttribute(String name, String value);
+
+    void setAttribute(String name, List<String> values);
+
+    void removeAttribute(String name);
+
+    /**
+     * @param name
+     * @return null if there is not any value of specified attribute or first value otherwise. Don't throw exception if there are more values of the attribute
+     */
+    String getFirstAttribute(String name);
+
+    /**
+     * @param name
+     * @return list of all attribute values or empty list if there are not any values. Never return null
+     */
+    List<String> getAttribute(String name);
+
+    Map<String, List<String>> getAttributes();
+
+    Set<String> getRequiredActions();
+
+    void addRequiredAction(String action);
+
+    void removeRequiredAction(String action);
+
+    void addRequiredAction(RequiredAction action);
+
+    void removeRequiredAction(RequiredAction action);
+
+    String getFirstName();
+
+    void setFirstName(String firstName);
+
+    String getLastName();
+
+    void setLastName(String lastName);
+
+    String getEmail();
+
+    void setEmail(String email);
+
+    boolean isEmailVerified();
+
+    void setEmailVerified(boolean verified);
+
+    void setTotp(boolean totp);
+
+    void updateCredential(UserCredentialModel cred);
+
+    List<UserCredentialValueModel> getCredentialsDirectly();
+
+    void updateCredentialDirectly(UserCredentialValueModel cred);
+
+    Set<RoleModel> getRealmRoleMappings();
+    Set<RoleModel> getClientRoleMappings(ClientModel app);
+    boolean hasRole(RoleModel role);
+    void grantRole(RoleModel role);
+    Set<RoleModel> getRoleMappings();
+    void deleteRoleMapping(RoleModel role);
+
+    String getFederationLink();
+    void setFederationLink(String link);
+
+    void addConsent(UserConsentModel consent);
+    UserConsentModel getConsentByClient(String clientInternalId);
+    List<UserConsentModel> getConsents();
+    void updateConsent(UserConsentModel consent);
+    boolean revokeConsentForClient(String clientInternalId);
+
+    public static enum RequiredAction {
+        VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
+    }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/UsernameLoginFailureModel.java b/model/api/src/main/java/org/keycloak/models/UsernameLoginFailureModel.java
index 59316ae..6e6013c 100755
--- a/model/api/src/main/java/org/keycloak/models/UsernameLoginFailureModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UsernameLoginFailureModel.java
@@ -1,21 +1,21 @@
-package org.keycloak.models;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UsernameLoginFailureModel
-{
-   String getUsername();
-   int getFailedLoginNotBefore();
-   void setFailedLoginNotBefore(int notBefore);
-   int getNumFailures();
-   void incrementFailures();
-   void clearFailures();
-   long getLastFailure();
-   void setLastFailure(long lastFailure);
-   String getLastIPFailure();
-   void setLastIPFailure(String ip);
-
-
-}
+package org.keycloak.models;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UsernameLoginFailureModel
+{
+   String getUsername();
+   int getFailedLoginNotBefore();
+   void setFailedLoginNotBefore(int notBefore);
+   int getNumFailures();
+   void incrementFailures();
+   void clearFailures();
+   long getLastFailure();
+   void setLastFailure(long lastFailure);
+   String getLastIPFailure();
+   void setLastIPFailure(String ip);
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserProvider.java b/model/api/src/main/java/org/keycloak/models/UserProvider.java
index b9a0079..eed008f 100755
--- a/model/api/src/main/java/org/keycloak/models/UserProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserProvider.java
@@ -1,52 +1,52 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.Provider;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserProvider extends Provider {
-    // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
-
-    UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
-    UserModel addUser(RealmModel realm, String username);
-    boolean removeUser(RealmModel realm, UserModel user);
-
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
-    void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
-
-    UserModel getUserById(String id, RealmModel realm);
-    UserModel getUserByUsername(String username, RealmModel realm);
-    UserModel getUserByEmail(String email, RealmModel realm);
-    UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
-    List<UserModel> getUsers(RealmModel realm);
-    int getUsersCount(RealmModel realm);
-    List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults);
-    List<UserModel> searchForUser(String search, RealmModel realm);
-    List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
-    List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
-    List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
-    Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
-    FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
-
-    void preRemove(RealmModel realm);
-
-    void preRemove(RealmModel realm, UserFederationProviderModel link);
-
-    void preRemove(RealmModel realm, RoleModel role);
-
-    void preRemove(RealmModel realm, ClientModel client);
-    void preRemove(ClientModel realm, ProtocolMapperModel protocolMapper);
-
-    boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
-    boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
-    CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input);
-
-    void close();
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.Provider;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserProvider extends Provider {
+    // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
+
+    UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
+    UserModel addUser(RealmModel realm, String username);
+    boolean removeUser(RealmModel realm, UserModel user);
+
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
+    void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
+
+    UserModel getUserById(String id, RealmModel realm);
+    UserModel getUserByUsername(String username, RealmModel realm);
+    UserModel getUserByEmail(String email, RealmModel realm);
+    UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
+    List<UserModel> getUsers(RealmModel realm);
+    int getUsersCount(RealmModel realm);
+    List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults);
+    List<UserModel> searchForUser(String search, RealmModel realm);
+    List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
+    List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
+    List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
+    Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
+    FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
+
+    void preRemove(RealmModel realm);
+
+    void preRemove(RealmModel realm, UserFederationProviderModel link);
+
+    void preRemove(RealmModel realm, RoleModel role);
+
+    void preRemove(RealmModel realm, ClientModel client);
+    void preRemove(ClientModel realm, ProtocolMapperModel protocolMapper);
+
+    boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
+    boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
+    CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input);
+
+    void close();
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserProviderFactory.java b/model/api/src/main/java/org/keycloak/models/UserProviderFactory.java
index f052e39..86c0f3c 100755
--- a/model/api/src/main/java/org/keycloak/models/UserProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/UserProviderFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserProviderFactory extends ProviderFactory<UserProvider> {
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserProviderFactory extends ProviderFactory<UserProvider> {
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionModel.java b/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
index 516ba26..ff3f19a 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
@@ -1,54 +1,54 @@
-package org.keycloak.models;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public interface UserSessionModel {
-
-    String getId();
-
-    /**
-     * If created via a broker external login, this is an identifier that can be
-     * used to match external broker backchannel logout requests to a UserSession
-     *
-     * @return
-     */
-    String getBrokerSessionId();
-    String getBrokerUserId();
-
-    UserModel getUser();
-
-    String getLoginUsername();
-
-    String getIpAddress();
-
-    String getAuthMethod();
-
-    boolean isRememberMe();
-
-    int getStarted();
-
-    int getLastSessionRefresh();
-
-    void setLastSessionRefresh(int seconds);
-
-    List<ClientSessionModel> getClientSessions();
-
-    public String getNote(String name);
-    public void setNote(String name, String value);
-    public void removeNote(String name);
-
-    State getState();
-    void setState(State state);
-
-    public static enum State {
-        LOGGING_IN,
-        LOGGED_IN,
-        LOGGING_OUT,
-        LOGGED_OUT
-    }
-
-}
+package org.keycloak.models;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface UserSessionModel {
+
+    String getId();
+
+    /**
+     * If created via a broker external login, this is an identifier that can be
+     * used to match external broker backchannel logout requests to a UserSession
+     *
+     * @return
+     */
+    String getBrokerSessionId();
+    String getBrokerUserId();
+
+    UserModel getUser();
+
+    String getLoginUsername();
+
+    String getIpAddress();
+
+    String getAuthMethod();
+
+    boolean isRememberMe();
+
+    int getStarted();
+
+    int getLastSessionRefresh();
+
+    void setLastSessionRefresh(int seconds);
+
+    List<ClientSessionModel> getClientSessions();
+
+    public String getNote(String name);
+    public void setNote(String name, String value);
+    public void removeNote(String name);
+
+    State getState();
+    void setState(State state);
+
+    public static enum State {
+        LOGGING_IN,
+        LOGGED_IN,
+        LOGGING_OUT,
+        LOGGED_OUT
+    }
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
index 89f8cee..2a874a8 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
@@ -1,43 +1,43 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.Provider;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserSessionProvider extends Provider {
-
-    ClientSessionModel createClientSession(RealmModel realm, ClientModel client);
-    ClientSessionModel getClientSession(RealmModel realm, String id);
-    ClientSessionModel getClientSession(String id);
-
-    UserSessionModel createUserSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId);
-    UserSessionModel getUserSession(RealmModel realm, String id);
-    List<UserSessionModel> getUserSessions(RealmModel realm, UserModel user);
-    List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client);
-    List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults);
-    List<UserSessionModel> getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId);
-    UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
-
-    List<UserSessionModel> getUserSessionsByNote(RealmModel realm, String noteName, String noteValue);
-
-    int getActiveUserSessions(RealmModel realm, ClientModel client);
-    void removeUserSession(RealmModel realm, UserSessionModel session);
-    void removeUserSessions(RealmModel realm, UserModel user);
-    void removeExpiredUserSessions(RealmModel realm);
-    void removeUserSessions(RealmModel realm);
-    void removeClientSession(RealmModel realm, ClientSessionModel clientSession);
-
-    UsernameLoginFailureModel getUserLoginFailure(RealmModel realm, String username);
-    UsernameLoginFailureModel addUserLoginFailure(RealmModel realm, String username);
-
-    void onRealmRemoved(RealmModel realm);
-    void onClientRemoved(RealmModel realm, ClientModel client);
-    void onUserRemoved(RealmModel realm, UserModel user);
-
-    void close();
-
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.Provider;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserSessionProvider extends Provider {
+
+    ClientSessionModel createClientSession(RealmModel realm, ClientModel client);
+    ClientSessionModel getClientSession(RealmModel realm, String id);
+    ClientSessionModel getClientSession(String id);
+
+    UserSessionModel createUserSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId);
+    UserSessionModel getUserSession(RealmModel realm, String id);
+    List<UserSessionModel> getUserSessions(RealmModel realm, UserModel user);
+    List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client);
+    List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults);
+    List<UserSessionModel> getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId);
+    UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
+
+    List<UserSessionModel> getUserSessionsByNote(RealmModel realm, String noteName, String noteValue);
+
+    int getActiveUserSessions(RealmModel realm, ClientModel client);
+    void removeUserSession(RealmModel realm, UserSessionModel session);
+    void removeUserSessions(RealmModel realm, UserModel user);
+    void removeExpiredUserSessions(RealmModel realm);
+    void removeUserSessions(RealmModel realm);
+    void removeClientSession(RealmModel realm, ClientSessionModel clientSession);
+
+    UsernameLoginFailureModel getUserLoginFailure(RealmModel realm, String username);
+    UsernameLoginFailureModel addUserLoginFailure(RealmModel realm, String username);
+
+    void onRealmRemoved(RealmModel realm);
+    void onClientRemoved(RealmModel realm, ClientModel client);
+    void onUserRemoved(RealmModel realm, UserModel user);
+
+    void close();
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionProviderFactory.java b/model/api/src/main/java/org/keycloak/models/UserSessionProviderFactory.java
index 5e57609..b57b55e 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionProviderFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.models;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserSessionProviderFactory extends ProviderFactory<UserSessionProvider> {
-}
+package org.keycloak.models;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserSessionProviderFactory extends ProviderFactory<UserSessionProvider> {
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/Base32.java b/model/api/src/main/java/org/keycloak/models/utils/Base32.java
index aef4422..2795da3 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/Base32.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/Base32.java
@@ -1,113 +1,113 @@
-package org.keycloak.models.utils;
-
-
-/* (PD) 2006 The Bitzi Corporation
- * Please see http://bitzi.com/publicdomain for more info.
- *
- * $Id: Base32.java,v 1.2 2006/07/14 04:58:39 gojomo Exp $
- */
-
-/**
- * Base32 - encodes and decodes RFC3548 Base32 (see http://www.faqs.org/rfcs/rfc3548.html )
- *
- * @author Robert Kaye
- * @author Gordon Mohr
- */
-public class Base32 {
-    private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
-    private static final int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
-            0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
-            0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
-            0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
-    /**
-     * Encodes byte array to Base32 String.
-     *
-     * @param bytes Bytes to encode.
-     * @return Encoded byte array <code>bytes</code> as a String.
-     *
-     */
-    public static String encode(final byte[] bytes) {
-        int i = 0, index = 0, digit = 0;
-        int currByte, nextByte;
-        StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
-
-        while (i < bytes.length) {
-            currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
-
-            /* Is the current digit going to span a byte boundary? */
-            if (index > 3) {
-                if ((i + 1) < bytes.length) {
-                    nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1] : (bytes[i + 1] + 256);
-                } else {
-                    nextByte = 0;
-                }
-
-                digit = currByte & (0xFF >> index);
-                index = (index + 5) % 8;
-                digit <<= index;
-                digit |= nextByte >> (8 - index);
-                i++;
-            } else {
-                digit = (currByte >> (8 - (index + 5))) & 0x1F;
-                index = (index + 5) % 8;
-                if (index == 0)
-                    i++;
-            }
-            base32.append(base32Chars.charAt(digit));
-        }
-
-        return base32.toString();
-    }
-
-    /**
-     * Decodes the given Base32 String to a raw byte array.
-     *
-     * @param base32
-     * @return Decoded <code>base32</code> String as a raw byte array.
-     */
-    public static byte[] decode(final String base32) {
-        int i, index, lookup, offset, digit;
-        byte[] bytes = new byte[base32.length() * 5 / 8];
-
-        for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
-            lookup = base32.charAt(i) - '0';
-
-            /* Skip chars outside the lookup table */
-            if (lookup < 0 || lookup >= base32Lookup.length) {
-                continue;
-            }
-
-            digit = base32Lookup[lookup];
-
-            /* If this digit is not in the table, ignore it */
-            if (digit == 0xFF) {
-                continue;
-            }
-
-            if (index <= 3) {
-                index = (index + 5) % 8;
-                if (index == 0) {
-                    bytes[offset] |= digit;
-                    offset++;
-                    if (offset >= bytes.length)
-                        break;
-                } else {
-                    bytes[offset] |= digit << (8 - index);
-                }
-            } else {
-                index = (index + 5) % 8;
-                bytes[offset] |= (digit >>> index);
-                offset++;
-
-                if (offset >= bytes.length) {
-                    break;
-                }
-                bytes[offset] |= digit << (8 - index);
-            }
-        }
-        return bytes;
-    }
-
+package org.keycloak.models.utils;
+
+
+/* (PD) 2006 The Bitzi Corporation
+ * Please see http://bitzi.com/publicdomain for more info.
+ *
+ * $Id: Base32.java,v 1.2 2006/07/14 04:58:39 gojomo Exp $
+ */
+
+/**
+ * Base32 - encodes and decodes RFC3548 Base32 (see http://www.faqs.org/rfcs/rfc3548.html )
+ *
+ * @author Robert Kaye
+ * @author Gordon Mohr
+ */
+public class Base32 {
+    private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+    private static final int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+            0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
+            0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+            0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+    /**
+     * Encodes byte array to Base32 String.
+     *
+     * @param bytes Bytes to encode.
+     * @return Encoded byte array <code>bytes</code> as a String.
+     *
+     */
+    public static String encode(final byte[] bytes) {
+        int i = 0, index = 0, digit = 0;
+        int currByte, nextByte;
+        StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
+
+        while (i < bytes.length) {
+            currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
+
+            /* Is the current digit going to span a byte boundary? */
+            if (index > 3) {
+                if ((i + 1) < bytes.length) {
+                    nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1] : (bytes[i + 1] + 256);
+                } else {
+                    nextByte = 0;
+                }
+
+                digit = currByte & (0xFF >> index);
+                index = (index + 5) % 8;
+                digit <<= index;
+                digit |= nextByte >> (8 - index);
+                i++;
+            } else {
+                digit = (currByte >> (8 - (index + 5))) & 0x1F;
+                index = (index + 5) % 8;
+                if (index == 0)
+                    i++;
+            }
+            base32.append(base32Chars.charAt(digit));
+        }
+
+        return base32.toString();
+    }
+
+    /**
+     * Decodes the given Base32 String to a raw byte array.
+     *
+     * @param base32
+     * @return Decoded <code>base32</code> String as a raw byte array.
+     */
+    public static byte[] decode(final String base32) {
+        int i, index, lookup, offset, digit;
+        byte[] bytes = new byte[base32.length() * 5 / 8];
+
+        for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
+            lookup = base32.charAt(i) - '0';
+
+            /* Skip chars outside the lookup table */
+            if (lookup < 0 || lookup >= base32Lookup.length) {
+                continue;
+            }
+
+            digit = base32Lookup[lookup];
+
+            /* If this digit is not in the table, ignore it */
+            if (digit == 0xFF) {
+                continue;
+            }
+
+            if (index <= 3) {
+                index = (index + 5) % 8;
+                if (index == 0) {
+                    bytes[offset] |= digit;
+                    offset++;
+                    if (offset >= bytes.length)
+                        break;
+                } else {
+                    bytes[offset] |= digit << (8 - index);
+                }
+            } else {
+                index = (index + 5) % 8;
+                bytes[offset] |= (digit >>> index);
+                offset++;
+
+                if (offset >= bytes.length) {
+                    break;
+                }
+                bytes[offset] |= digit << (8 - index);
+            }
+        }
+        return bytes;
+    }
+
 }
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
index a596c82..cefd304 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
@@ -1,161 +1,161 @@
-package org.keycloak.models.utils;
-
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.PasswordToken;
-import org.keycloak.util.Time;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CredentialValidation {
-
-    private static int hashIterations(RealmModel realm) {
-        PasswordPolicy policy = realm.getPasswordPolicy();
-        if (policy != null) {
-            return policy.getHashIterations();
-        }
-        return -1;
-
-    }
-
-    /**
-     * Will update password if hash iteration policy has changed
-     *
-     * @param realm
-     * @param user
-     * @param password
-     * @return
-     */
-    public static boolean validPassword(RealmModel realm, UserModel user, String password) {
-        boolean validated = false;
-        UserCredentialValueModel passwordCred = null;
-        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
-            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                validated = new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue(), cred.getHashIterations());
-                passwordCred = cred;
-            }
-        }
-        if (validated) {
-            int iterations = hashIterations(realm);
-            if (iterations > -1 && iterations != passwordCred.getHashIterations()) {
-                UserCredentialValueModel newCred = new UserCredentialValueModel();
-                newCred.setType(passwordCred.getType());
-                newCred.setDevice(passwordCred.getDevice());
-                newCred.setSalt(passwordCred.getSalt());
-                newCred.setHashIterations(iterations);
-                newCred.setValue(new Pbkdf2PasswordEncoder(newCred.getSalt()).encode(password, iterations));
-                user.updateCredentialDirectly(newCred);
-            }
-
-        }
-        return validated;
-
-    }
-
-    public static boolean validPasswordToken(RealmModel realm, UserModel user, String encodedPasswordToken) {
-        JWSInput jws = new JWSInput(encodedPasswordToken);
-        if (!RSAProvider.verify(jws, realm.getPublicKey())) {
-            return false;
-        }
-        try {
-            PasswordToken passwordToken = jws.readJsonContent(PasswordToken.class);
-            if (!passwordToken.getRealm().equals(realm.getName())) {
-                return false;
-            }
-            if (!passwordToken.getUser().equals(user.getId())) {
-                return false;
-            }
-            if (Time.currentTime() - passwordToken.getTimestamp() > realm.getAccessCodeLifespanUserAction()) {
-                return false;
-            }
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public static boolean validTOTP(RealmModel realm, UserModel user, String otp) {
-        UserCredentialValueModel passwordCred = null;
-        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
-            if (cred.getType().equals(UserCredentialModel.TOTP)) {
-                if (new TimeBasedOTP().validate(otp, cred.getValue().getBytes())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-
-    }
-    public static boolean validSecret(RealmModel realm, UserModel user, String secret) {
-        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
-            if (cred.getType().equals(UserCredentialModel.SECRET)) {
-                if (cred.getValue().equals(secret)) return true;
-            }
-        }
-        return false;
-
-    }
-
-    /**
-     * Must validate all credentials.  FYI, password hashes may be rehashed and updated based on realm hash password policies.
-     *
-     * @param realm
-     * @param user
-     * @param credentials
-     * @return
-     */
-    public static boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> credentials) {
-        for (UserCredentialModel credential : credentials) {
-            if (!validCredential(realm, user, credential)) return false;
-        }
-        return true;
-    }
-
-    /**
-     * Must validate all credentials.  FYI, password hashes may be rehashed and updated based on realm hash password policies.
-     *
-     * @param realm
-     * @param user
-     * @param credentials
-     * @return
-     */
-    public static boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... credentials) {
-        for (UserCredentialModel credential : credentials) {
-            if (!validCredential(realm, user, credential)) return false;
-        }
-        return true;
-    }
-
-    private static boolean validCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
-        if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
-            if (!validPassword(realm, user, credential.getValue())) {
-                return false;
-            }
-        } else if (credential.getType().equals(UserCredentialModel.PASSWORD_TOKEN)) {
-            if (!validPasswordToken(realm, user, credential.getValue())) {
-                return false;
-            }
-        } else if (credential.getType().equals(UserCredentialModel.TOTP)) {
-            if (!validTOTP(realm, user, credential.getValue())) {
-                return false;
-            }
-        } else if (credential.getType().equals(UserCredentialModel.SECRET)) {
-            if (!validSecret(realm, user, credential.getValue())) {
-                return false;
-            }
-        } else {
-            return false;
-        }
-        return true;
-    }
-}
+package org.keycloak.models.utils;
+
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.PasswordToken;
+import org.keycloak.util.Time;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CredentialValidation {
+
+    private static int hashIterations(RealmModel realm) {
+        PasswordPolicy policy = realm.getPasswordPolicy();
+        if (policy != null) {
+            return policy.getHashIterations();
+        }
+        return -1;
+
+    }
+
+    /**
+     * Will update password if hash iteration policy has changed
+     *
+     * @param realm
+     * @param user
+     * @param password
+     * @return
+     */
+    public static boolean validPassword(RealmModel realm, UserModel user, String password) {
+        boolean validated = false;
+        UserCredentialValueModel passwordCred = null;
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
+            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+                validated = new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue(), cred.getHashIterations());
+                passwordCred = cred;
+            }
+        }
+        if (validated) {
+            int iterations = hashIterations(realm);
+            if (iterations > -1 && iterations != passwordCred.getHashIterations()) {
+                UserCredentialValueModel newCred = new UserCredentialValueModel();
+                newCred.setType(passwordCred.getType());
+                newCred.setDevice(passwordCred.getDevice());
+                newCred.setSalt(passwordCred.getSalt());
+                newCred.setHashIterations(iterations);
+                newCred.setValue(new Pbkdf2PasswordEncoder(newCred.getSalt()).encode(password, iterations));
+                user.updateCredentialDirectly(newCred);
+            }
+
+        }
+        return validated;
+
+    }
+
+    public static boolean validPasswordToken(RealmModel realm, UserModel user, String encodedPasswordToken) {
+        JWSInput jws = new JWSInput(encodedPasswordToken);
+        if (!RSAProvider.verify(jws, realm.getPublicKey())) {
+            return false;
+        }
+        try {
+            PasswordToken passwordToken = jws.readJsonContent(PasswordToken.class);
+            if (!passwordToken.getRealm().equals(realm.getName())) {
+                return false;
+            }
+            if (!passwordToken.getUser().equals(user.getId())) {
+                return false;
+            }
+            if (Time.currentTime() - passwordToken.getTimestamp() > realm.getAccessCodeLifespanUserAction()) {
+                return false;
+            }
+            return true;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    public static boolean validTOTP(RealmModel realm, UserModel user, String otp) {
+        UserCredentialValueModel passwordCred = null;
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
+            if (cred.getType().equals(UserCredentialModel.TOTP)) {
+                if (new TimeBasedOTP().validate(otp, cred.getValue().getBytes())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+
+    }
+    public static boolean validSecret(RealmModel realm, UserModel user, String secret) {
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
+            if (cred.getType().equals(UserCredentialModel.SECRET)) {
+                if (cred.getValue().equals(secret)) return true;
+            }
+        }
+        return false;
+
+    }
+
+    /**
+     * Must validate all credentials.  FYI, password hashes may be rehashed and updated based on realm hash password policies.
+     *
+     * @param realm
+     * @param user
+     * @param credentials
+     * @return
+     */
+    public static boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> credentials) {
+        for (UserCredentialModel credential : credentials) {
+            if (!validCredential(realm, user, credential)) return false;
+        }
+        return true;
+    }
+
+    /**
+     * Must validate all credentials.  FYI, password hashes may be rehashed and updated based on realm hash password policies.
+     *
+     * @param realm
+     * @param user
+     * @param credentials
+     * @return
+     */
+    public static boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... credentials) {
+        for (UserCredentialModel credential : credentials) {
+            if (!validCredential(realm, user, credential)) return false;
+        }
+        return true;
+    }
+
+    private static boolean validCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
+        if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
+            if (!validPassword(realm, user, credential.getValue())) {
+                return false;
+            }
+        } else if (credential.getType().equals(UserCredentialModel.PASSWORD_TOKEN)) {
+            if (!validPasswordToken(realm, user, credential.getValue())) {
+                return false;
+            }
+        } else if (credential.getType().equals(UserCredentialModel.TOTP)) {
+            if (!validTOTP(realm, user, credential.getValue())) {
+                return false;
+            }
+        } else if (credential.getType().equals(UserCredentialModel.SECRET)) {
+            if (!validSecret(realm, user, credential.getValue())) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
index d3f5622..0952cc6 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
@@ -1,167 +1,167 @@
-package org.keycloak.models.utils;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.RealmModel;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DefaultAuthenticationFlows {
-
-    public static final String REGISTRATION_FLOW = "registration";
-    public static final String REGISTRATION_FORM_FLOW = "registration form";
-    public static final String BROWSER_FLOW = "browser";
-    public static final String LOGIN_FORMS_FLOW = "forms";
-
-    public static void addFlows(RealmModel realm) {
-        if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
-        if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
-    }
-
-    public static void registrationFlow(RealmModel realm) {
-        AuthenticationFlowModel registrationFlow = new AuthenticationFlowModel();
-        registrationFlow.setAlias(REGISTRATION_FLOW);
-        registrationFlow.setDescription("registration flow");
-        registrationFlow.setProviderId("basic-flow");
-        registrationFlow.setTopLevel(true);
-        registrationFlow.setBuiltIn(true);
-        registrationFlow = realm.addAuthenticationFlow(registrationFlow);
-
-        AuthenticationFlowModel registrationFormFlow = new AuthenticationFlowModel();
-        registrationFormFlow.setAlias(REGISTRATION_FORM_FLOW);
-        registrationFormFlow.setDescription("registration form");
-        registrationFormFlow.setProviderId("form-flow");
-        registrationFormFlow.setTopLevel(false);
-        registrationFormFlow.setBuiltIn(true);
-        registrationFormFlow = realm.addAuthenticationFlow(registrationFormFlow);
-
-        AuthenticationExecutionModel execution;
-
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(registrationFlow.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("registration-page-form");
-        execution.setPriority(10);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(true);
-        execution.setFlowId(registrationFormFlow.getId());
-        realm.addAuthenticatorExecution(execution);
-
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(registrationFormFlow.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("registration-user-creation");
-        execution.setPriority(20);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(registrationFormFlow.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("registration-profile-action");
-        execution.setPriority(40);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(registrationFormFlow.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("registration-password-action");
-        execution.setPriority(50);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-
-        //AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel();
-        //captchaConfig.setAlias("Recaptcha Config");
-        //Map<String, String> config = new HashMap<>();
-        //config.put("site.key", "6LcFEAkTAAAAAOaY-5RJk3zIYw4AalNtqfac27Bn");
-        //config.put("secret", "6LcFEAkTAAAAAM0SErEs9NlfhYpOTRj_vOVJSAMI");
-        //captchaConfig.setConfig(config);
-        //captchaConfig = realm.addAuthenticatorConfig(captchaConfig);
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(registrationFormFlow.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
-        execution.setAuthenticator("registration-recaptcha-action");
-        execution.setPriority(60);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        //execution.setAuthenticatorConfig(captchaConfig.getId());
-        realm.addAuthenticatorExecution(execution);
-
-
-
-    }
-
-    public static void browserFlow(RealmModel realm) {
-        AuthenticationFlowModel browser = new AuthenticationFlowModel();
-        browser.setAlias(BROWSER_FLOW);
-        browser.setDescription("browser based authentication");
-        browser.setProviderId("basic-flow");
-        browser.setTopLevel(true);
-        browser.setBuiltIn(true);
-        browser = realm.addAuthenticationFlow(browser);
-        AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(browser.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
-        execution.setAuthenticator("auth-cookie");
-        execution.setPriority(10);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(browser.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
-        execution.setAuthenticator("auth-spnego");
-        execution.setPriority(20);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-
-
-        AuthenticationFlowModel forms = new AuthenticationFlowModel();
-        forms.setTopLevel(false);
-        forms.setBuiltIn(true);
-        forms.setAlias(LOGIN_FORMS_FLOW);
-        forms.setDescription("Username, password, otp and other auth forms.");
-        forms.setProviderId("basic-flow");
-        forms = realm.addAuthenticationFlow(forms);
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(browser.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
-        execution.setFlowId(forms.getId());
-        execution.setPriority(30);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(true);
-        realm.addAuthenticatorExecution(execution);
-
-        // forms
-        // Username Password processing
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(forms.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("auth-username-password-form");
-        execution.setPriority(10);
-        execution.setUserSetupAllowed(false);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-
-        // otp processing
-        execution = new AuthenticationExecutionModel();
-        execution.setParentFlow(forms.getId());
-        execution.setRequirement(AuthenticationExecutionModel.Requirement.OPTIONAL);
-        execution.setAuthenticator("auth-otp-form");
-        execution.setPriority(20);
-        execution.setUserSetupAllowed(true);
-        execution.setAutheticatorFlow(false);
-        realm.addAuthenticatorExecution(execution);
-    }
-}
+package org.keycloak.models.utils;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.RealmModel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DefaultAuthenticationFlows {
+
+    public static final String REGISTRATION_FLOW = "registration";
+    public static final String REGISTRATION_FORM_FLOW = "registration form";
+    public static final String BROWSER_FLOW = "browser";
+    public static final String LOGIN_FORMS_FLOW = "forms";
+
+    public static void addFlows(RealmModel realm) {
+        if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
+        if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
+    }
+
+    public static void registrationFlow(RealmModel realm) {
+        AuthenticationFlowModel registrationFlow = new AuthenticationFlowModel();
+        registrationFlow.setAlias(REGISTRATION_FLOW);
+        registrationFlow.setDescription("registration flow");
+        registrationFlow.setProviderId("basic-flow");
+        registrationFlow.setTopLevel(true);
+        registrationFlow.setBuiltIn(true);
+        registrationFlow = realm.addAuthenticationFlow(registrationFlow);
+
+        AuthenticationFlowModel registrationFormFlow = new AuthenticationFlowModel();
+        registrationFormFlow.setAlias(REGISTRATION_FORM_FLOW);
+        registrationFormFlow.setDescription("registration form");
+        registrationFormFlow.setProviderId("form-flow");
+        registrationFormFlow.setTopLevel(false);
+        registrationFormFlow.setBuiltIn(true);
+        registrationFormFlow = realm.addAuthenticationFlow(registrationFormFlow);
+
+        AuthenticationExecutionModel execution;
+
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(registrationFlow.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
+        execution.setAuthenticator("registration-page-form");
+        execution.setPriority(10);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(true);
+        execution.setFlowId(registrationFormFlow.getId());
+        realm.addAuthenticatorExecution(execution);
+
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(registrationFormFlow.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
+        execution.setAuthenticator("registration-user-creation");
+        execution.setPriority(20);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(registrationFormFlow.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
+        execution.setAuthenticator("registration-profile-action");
+        execution.setPriority(40);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(registrationFormFlow.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
+        execution.setAuthenticator("registration-password-action");
+        execution.setPriority(50);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+
+        //AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel();
+        //captchaConfig.setAlias("Recaptcha Config");
+        //Map<String, String> config = new HashMap<>();
+        //config.put("site.key", "6LcFEAkTAAAAAOaY-5RJk3zIYw4AalNtqfac27Bn");
+        //config.put("secret", "6LcFEAkTAAAAAM0SErEs9NlfhYpOTRj_vOVJSAMI");
+        //captchaConfig.setConfig(config);
+        //captchaConfig = realm.addAuthenticatorConfig(captchaConfig);
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(registrationFormFlow.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
+        execution.setAuthenticator("registration-recaptcha-action");
+        execution.setPriority(60);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        //execution.setAuthenticatorConfig(captchaConfig.getId());
+        realm.addAuthenticatorExecution(execution);
+
+
+
+    }
+
+    public static void browserFlow(RealmModel realm) {
+        AuthenticationFlowModel browser = new AuthenticationFlowModel();
+        browser.setAlias(BROWSER_FLOW);
+        browser.setDescription("browser based authentication");
+        browser.setProviderId("basic-flow");
+        browser.setTopLevel(true);
+        browser.setBuiltIn(true);
+        browser = realm.addAuthenticationFlow(browser);
+        AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(browser.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
+        execution.setAuthenticator("auth-cookie");
+        execution.setPriority(10);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(browser.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
+        execution.setAuthenticator("auth-spnego");
+        execution.setPriority(20);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+
+
+        AuthenticationFlowModel forms = new AuthenticationFlowModel();
+        forms.setTopLevel(false);
+        forms.setBuiltIn(true);
+        forms.setAlias(LOGIN_FORMS_FLOW);
+        forms.setDescription("Username, password, otp and other auth forms.");
+        forms.setProviderId("basic-flow");
+        forms = realm.addAuthenticationFlow(forms);
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(browser.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
+        execution.setFlowId(forms.getId());
+        execution.setPriority(30);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(true);
+        realm.addAuthenticatorExecution(execution);
+
+        // forms
+        // Username Password processing
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(forms.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
+        execution.setAuthenticator("auth-username-password-form");
+        execution.setPriority(10);
+        execution.setUserSetupAllowed(false);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+
+        // otp processing
+        execution = new AuthenticationExecutionModel();
+        execution.setParentFlow(forms.getId());
+        execution.setRequirement(AuthenticationExecutionModel.Requirement.OPTIONAL);
+        execution.setAuthenticator("auth-otp-form");
+        execution.setPriority(20);
+        execution.setUserSetupAllowed(true);
+        execution.setAutheticatorFlow(false);
+        realm.addAuthenticatorExecution(execution);
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultRequiredActions.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultRequiredActions.java
index d0ddee1..34c45f1 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/DefaultRequiredActions.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultRequiredActions.java
@@ -1,66 +1,66 @@
-package org.keycloak.models.utils;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.UserModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DefaultRequiredActions {
-    public static void addActions(RealmModel realm) {
-        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.VERIFY_EMAIL.name()) == null) {
-            RequiredActionProviderModel verifyEmail = new RequiredActionProviderModel();
-            verifyEmail.setEnabled(true);
-            verifyEmail.setAlias(UserModel.RequiredAction.VERIFY_EMAIL.name());
-            verifyEmail.setName("Verify Email");
-            verifyEmail.setProviderId(UserModel.RequiredAction.VERIFY_EMAIL.name());
-            verifyEmail.setDefaultAction(false);
-            realm.addRequiredActionProvider(verifyEmail);
-
-        }
-
-        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_PROFILE.name()) == null) {
-            RequiredActionProviderModel updateProfile = new RequiredActionProviderModel();
-            updateProfile.setEnabled(true);
-            updateProfile.setAlias(UserModel.RequiredAction.UPDATE_PROFILE.name());
-            updateProfile.setName("Update Profile");
-            updateProfile.setProviderId(UserModel.RequiredAction.UPDATE_PROFILE.name());
-            updateProfile.setDefaultAction(false);
-            realm.addRequiredActionProvider(updateProfile);
-        }
-
-        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name()) == null) {
-            RequiredActionProviderModel totp = new RequiredActionProviderModel();
-            totp.setEnabled(true);
-            totp.setAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
-            totp.setName("Configure Totp");
-            totp.setProviderId(UserModel.RequiredAction.CONFIGURE_TOTP.name());
-            totp.setDefaultAction(false);
-            realm.addRequiredActionProvider(totp);
-        }
-
-        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_PASSWORD.name()) == null) {
-            RequiredActionProviderModel updatePassword = new RequiredActionProviderModel();
-            updatePassword.setEnabled(true);
-            updatePassword.setAlias(UserModel.RequiredAction.UPDATE_PASSWORD.name());
-            updatePassword.setName("Update Password");
-            updatePassword.setProviderId(UserModel.RequiredAction.UPDATE_PASSWORD.name());
-            updatePassword.setDefaultAction(false);
-            realm.addRequiredActionProvider(updatePassword);
-        }
-
-        if (realm.getRequiredActionProviderByAlias("terms_and_conditions") == null) {
-            RequiredActionProviderModel termsAndConditions = new RequiredActionProviderModel();
-            termsAndConditions.setEnabled(false);
-            termsAndConditions.setAlias("terms_and_conditions");
-            termsAndConditions.setName("Terms and Conditions");
-            termsAndConditions.setProviderId("terms_and_conditions");
-            termsAndConditions.setDefaultAction(false);
-            realm.addRequiredActionProvider(termsAndConditions);
-        }
-
-
-    }
-}
+package org.keycloak.models.utils;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.UserModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DefaultRequiredActions {
+    public static void addActions(RealmModel realm) {
+        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.VERIFY_EMAIL.name()) == null) {
+            RequiredActionProviderModel verifyEmail = new RequiredActionProviderModel();
+            verifyEmail.setEnabled(true);
+            verifyEmail.setAlias(UserModel.RequiredAction.VERIFY_EMAIL.name());
+            verifyEmail.setName("Verify Email");
+            verifyEmail.setProviderId(UserModel.RequiredAction.VERIFY_EMAIL.name());
+            verifyEmail.setDefaultAction(false);
+            realm.addRequiredActionProvider(verifyEmail);
+
+        }
+
+        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_PROFILE.name()) == null) {
+            RequiredActionProviderModel updateProfile = new RequiredActionProviderModel();
+            updateProfile.setEnabled(true);
+            updateProfile.setAlias(UserModel.RequiredAction.UPDATE_PROFILE.name());
+            updateProfile.setName("Update Profile");
+            updateProfile.setProviderId(UserModel.RequiredAction.UPDATE_PROFILE.name());
+            updateProfile.setDefaultAction(false);
+            realm.addRequiredActionProvider(updateProfile);
+        }
+
+        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name()) == null) {
+            RequiredActionProviderModel totp = new RequiredActionProviderModel();
+            totp.setEnabled(true);
+            totp.setAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+            totp.setName("Configure Totp");
+            totp.setProviderId(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+            totp.setDefaultAction(false);
+            realm.addRequiredActionProvider(totp);
+        }
+
+        if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_PASSWORD.name()) == null) {
+            RequiredActionProviderModel updatePassword = new RequiredActionProviderModel();
+            updatePassword.setEnabled(true);
+            updatePassword.setAlias(UserModel.RequiredAction.UPDATE_PASSWORD.name());
+            updatePassword.setName("Update Password");
+            updatePassword.setProviderId(UserModel.RequiredAction.UPDATE_PASSWORD.name());
+            updatePassword.setDefaultAction(false);
+            realm.addRequiredActionProvider(updatePassword);
+        }
+
+        if (realm.getRequiredActionProviderByAlias("terms_and_conditions") == null) {
+            RequiredActionProviderModel termsAndConditions = new RequiredActionProviderModel();
+            termsAndConditions.setEnabled(false);
+            termsAndConditions.setAlias("terms_and_conditions");
+            termsAndConditions.setName("Terms and Conditions");
+            termsAndConditions.setProviderId("terms_and_conditions");
+            termsAndConditions.setDefaultAction(false);
+            realm.addRequiredActionProvider(termsAndConditions);
+        }
+
+
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 9f0f365..8219edc 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -1,472 +1,472 @@
-package org.keycloak.models.utils;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-
-import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
-import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
-import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.FederatedIdentityRepresentation;
-import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
-import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.UserConsentRepresentation;
-import org.keycloak.representations.idm.UserFederationMapperRepresentation;
-import org.keycloak.representations.idm.UserFederationProviderRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.representations.idm.UserSessionRepresentation;
-import org.keycloak.util.Time;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ModelToRepresentation {
-    public static UserRepresentation toRepresentation(UserModel user) {
-        UserRepresentation rep = new UserRepresentation();
-        rep.setId(user.getId());
-        rep.setUsername(user.getUsername());
-        rep.setCreatedTimestamp(user.getCreatedTimestamp());
-        rep.setLastName(user.getLastName());
-        rep.setFirstName(user.getFirstName());
-        rep.setEmail(user.getEmail());
-        rep.setEnabled(user.isEnabled());
-        rep.setEmailVerified(user.isEmailVerified());
-        rep.setTotp(user.isTotp());
-        rep.setFederationLink(user.getFederationLink());
-
-        List<String> reqActions = new ArrayList<String>();
-        Set<String> requiredActions = user.getRequiredActions();
-        for (String ra : requiredActions){
-            reqActions.add(ra);
-        }
-
-        rep.setRequiredActions(reqActions);
-
-        if (user.getAttributes() != null && !user.getAttributes().isEmpty()) {
-            Map<String, Object> attrs = new HashMap<>();
-            attrs.putAll(user.getAttributes());
-            rep.setAttributes(attrs);
-        }
-        return rep;
-    }
-
-    public static RoleRepresentation toRepresentation(RoleModel role) {
-        RoleRepresentation rep = new RoleRepresentation();
-        rep.setId(role.getId());
-        rep.setName(role.getName());
-        rep.setDescription(role.getDescription());
-        rep.setComposite(role.isComposite());
-        return rep;
-    }
-
-    public static RealmRepresentation toRepresentation(RealmModel realm, boolean internal) {
-        RealmRepresentation rep = new RealmRepresentation();
-        rep.setId(realm.getId());
-        rep.setRealm(realm.getName());
-        rep.setEnabled(realm.isEnabled());
-        rep.setNotBefore(realm.getNotBefore());
-        rep.setSslRequired(realm.getSslRequired().name().toLowerCase());
-        rep.setPublicKey(realm.getPublicKeyPem());
-        if (internal) {
-            rep.setPrivateKey(realm.getPrivateKeyPem());
-            String privateKeyPem = realm.getPrivateKeyPem();
-            if (realm.getCertificatePem() == null && privateKeyPem != null) {
-                KeycloakModelUtils.generateRealmCertificate(realm);
-            }
-            rep.setCodeSecret(realm.getCodeSecret());
-        }
-        rep.setCertificate(realm.getCertificatePem());
-        rep.setRegistrationAllowed(realm.isRegistrationAllowed());
-        rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername());
-        rep.setRememberMe(realm.isRememberMe());
-        rep.setBruteForceProtected(realm.isBruteForceProtected());
-        rep.setMaxFailureWaitSeconds(realm.getMaxFailureWaitSeconds());
-        rep.setMinimumQuickLoginWaitSeconds(realm.getMinimumQuickLoginWaitSeconds());
-        rep.setWaitIncrementSeconds(realm.getWaitIncrementSeconds());
-        rep.setQuickLoginCheckMilliSeconds(realm.getQuickLoginCheckMilliSeconds());
-        rep.setMaxDeltaTimeSeconds(realm.getMaxDeltaTimeSeconds());
-        rep.setFailureFactor(realm.getFailureFactor());
-
-        rep.setEventsEnabled(realm.isEventsEnabled());
-        if (realm.getEventsExpiration() != 0) {
-            rep.setEventsExpiration(realm.getEventsExpiration());
-        }
-        if (realm.getEventsListeners() != null) {
-            rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
-        }
-        if (realm.getEnabledEventTypes() != null) {
-            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
-        }
-
-        rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
-        rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
-
-        rep.setVerifyEmail(realm.isVerifyEmail());
-        rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
-        rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
-        rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
-        rep.setSsoSessionIdleTimeout(realm.getSsoSessionIdleTimeout());
-        rep.setSsoSessionMaxLifespan(realm.getSsoSessionMaxLifespan());
-        rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
-        rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
-        rep.setAccessCodeLifespanLogin(realm.getAccessCodeLifespanLogin());
-        rep.setSmtpServer(realm.getSmtpConfig());
-        rep.setBrowserSecurityHeaders(realm.getBrowserSecurityHeaders());
-        rep.setAccountTheme(realm.getAccountTheme());
-        rep.setLoginTheme(realm.getLoginTheme());
-        rep.setAdminTheme(realm.getAdminTheme());
-        rep.setEmailTheme(realm.getEmailTheme());
-        if (realm.getPasswordPolicy() != null) {
-            rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
-        }
-
-        List<String> defaultRoles = realm.getDefaultRoles();
-        if (!defaultRoles.isEmpty()) {
-            List<String> roleStrings = new ArrayList<String>();
-            roleStrings.addAll(defaultRoles);
-            rep.setDefaultRoles(roleStrings);
-        }
-
-        List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
-        if (requiredCredentialModels.size() > 0) {
-            rep.setRequiredCredentials(new HashSet<String>());
-            for (RequiredCredentialModel cred : requiredCredentialModels) {
-                rep.getRequiredCredentials().add(cred.getType());
-            }
-        }
-
-        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
-        if (fedProviderModels.size() > 0) {
-            List<UserFederationProviderRepresentation> fedProviderReps = new ArrayList<UserFederationProviderRepresentation>();
-            for (UserFederationProviderModel model : fedProviderModels) {
-                UserFederationProviderRepresentation fedProvRep = toRepresentation(model);
-                fedProviderReps.add(fedProvRep);
-            }
-            rep.setUserFederationProviders(fedProviderReps);
-        }
-
-        for (UserFederationMapperModel mapper : realm.getUserFederationMappers()) {
-            rep.addUserFederationMapper(toRepresentation(realm, mapper));
-        }
-
-        for (IdentityProviderModel provider : realm.getIdentityProviders()) {
-            rep.addIdentityProvider(toRepresentation(provider));
-        }
-
-        for (IdentityProviderMapperModel mapper : realm.getIdentityProviderMappers()) {
-            rep.addIdentityProviderMapper(toRepresentation(mapper));
-        }
-
-        rep.setInternationalizationEnabled(realm.isInternationalizationEnabled());
-        rep.getSupportedLocales().addAll(realm.getSupportedLocales());
-        rep.setDefaultLocale(realm.getDefaultLocale());
-        if (internal) {
-            exportAuthenticationFlows(realm, rep);
-        }
-        return rep;
-    }
-
-    public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) {
-        rep.setAuthenticationFlows(new LinkedList<AuthenticationFlowRepresentation>());
-        rep.setAuthenticatorConfig(new LinkedList<AuthenticatorConfigRepresentation>());
-        for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) {
-            AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model);
-            rep.getAuthenticationFlows().add(flowRep);
-        }
-        for (AuthenticatorConfigModel model : realm.getAuthenticatorConfigs()) {
-            rep.getAuthenticatorConfig().add(toRepresentation(model));
-        }
-
-    }
-
-
-    public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) {
-        RealmEventsConfigRepresentation rep = new RealmEventsConfigRepresentation();
-        rep.setEventsEnabled(realm.isEventsEnabled());
-
-        if (realm.getEventsExpiration() != 0) {
-            rep.setEventsExpiration(realm.getEventsExpiration());
-        }
-
-        if (realm.getEventsListeners() != null) {
-            rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
-        }
-        
-        if(realm.getEnabledEventTypes() != null) {
-            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
-        }
-        
-        rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
-        
-        rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
-        
-        return rep;
-    }
-
-    public static CredentialRepresentation toRepresentation(UserCredentialModel cred) {
-        CredentialRepresentation rep = new CredentialRepresentation();
-        rep.setType(CredentialRepresentation.SECRET);
-        rep.setValue(cred.getValue());
-        return rep;
-    }
-
-    public static FederatedIdentityRepresentation toRepresentation(FederatedIdentityModel socialLink) {
-        FederatedIdentityRepresentation rep = new FederatedIdentityRepresentation();
-        rep.setUserName(socialLink.getUserName());
-        rep.setIdentityProvider(socialLink.getIdentityProvider());
-        rep.setUserId(socialLink.getUserId());
-        return rep;
-    }
-
-    public static UserSessionRepresentation toRepresentation(UserSessionModel session) {
-        UserSessionRepresentation rep = new UserSessionRepresentation();
-        rep.setId(session.getId());
-        rep.setStart(Time.toMillis(session.getStarted()));
-        rep.setLastAccess(Time.toMillis(session.getLastSessionRefresh()));
-        rep.setUsername(session.getUser().getUsername());
-        rep.setUserId(session.getUser().getId());
-        rep.setIpAddress(session.getIpAddress());
-        for (ClientSessionModel clientSession : session.getClientSessions()) {
-            ClientModel client = clientSession.getClient();
-            rep.getClients().put(client.getId(), client.getClientId());
-        }
-        return rep;
-    }
-
-    public static ClientRepresentation toRepresentation(ClientModel clientModel) {
-        ClientRepresentation rep = new ClientRepresentation();
-        rep.setId(clientModel.getId());
-        rep.setClientId(clientModel.getClientId());
-        rep.setName(clientModel.getName());
-        rep.setEnabled(clientModel.isEnabled());
-        rep.setAdminUrl(clientModel.getManagementUrl());
-        rep.setPublicClient(clientModel.isPublicClient());
-        rep.setFrontchannelLogout(clientModel.isFrontchannelLogout());
-        rep.setProtocol(clientModel.getProtocol());
-        rep.setAttributes(clientModel.getAttributes());
-        rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
-        rep.setBearerOnly(clientModel.isBearerOnly());
-        rep.setConsentRequired(clientModel.isConsentRequired());
-        rep.setDirectGrantsOnly(clientModel.isDirectGrantsOnly());
-        rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired());
-        rep.setBaseUrl(clientModel.getBaseUrl());
-        rep.setNotBefore(clientModel.getNotBefore());
-        rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
-
-        Set<String> redirectUris = clientModel.getRedirectUris();
-        if (redirectUris != null) {
-            rep.setRedirectUris(new LinkedList<>(redirectUris));
-        }
-
-        Set<String> webOrigins = clientModel.getWebOrigins();
-        if (webOrigins != null) {
-            rep.setWebOrigins(new LinkedList<>(webOrigins));
-        }
-
-        if (!clientModel.getDefaultRoles().isEmpty()) {
-            rep.setDefaultRoles(clientModel.getDefaultRoles().toArray(new String[0]));
-        }
-
-        if (!clientModel.getRegisteredNodes().isEmpty()) {
-            rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
-        }
-
-        if (!clientModel.getProtocolMappers().isEmpty()) {
-            List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
-            for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
-                mappings.add(toRepresentation(model));
-            }
-            rep.setProtocolMappers(mappings);
-        }
-
-        return rep;
-    }
-
-    public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
-        UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
-        rep.setId(model.getId());
-        rep.setConfig(model.getConfig());
-        rep.setProviderName(model.getProviderName());
-        rep.setPriority(model.getPriority());
-        rep.setDisplayName(model.getDisplayName());
-        rep.setFullSyncPeriod(model.getFullSyncPeriod());
-        rep.setChangedSyncPeriod(model.getChangedSyncPeriod());
-        rep.setLastSync(model.getLastSync());
-        return rep;
-    }
-
-    public static UserFederationMapperRepresentation toRepresentation(RealmModel realm, UserFederationMapperModel model) {
-        UserFederationMapperRepresentation rep = new UserFederationMapperRepresentation();
-        rep.setId(model.getId());
-        rep.setName(model.getName());
-        rep.setFederationMapperType(model.getFederationMapperType());
-        Map<String, String> config = new HashMap<String, String>();
-        config.putAll(model.getConfig());
-        rep.setConfig(config);
-
-        UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderById(model.getFederationProviderId(), realm);
-        if (fedProvider == null) {
-            throw new ModelException("Couldn't find federation provider with ID " + model.getId());
-        }
-        rep.setFederationProviderDisplayName(fedProvider.getDisplayName());
-
-        return rep;
-    }
-
-    public static IdentityProviderRepresentation toRepresentation(IdentityProviderModel identityProviderModel) {
-        IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();
-
-        providerRep.setInternalId(identityProviderModel.getInternalId());
-        providerRep.setProviderId(identityProviderModel.getProviderId());
-        providerRep.setAlias(identityProviderModel.getAlias());
-        providerRep.setEnabled(identityProviderModel.isEnabled());
-        providerRep.setStoreToken(identityProviderModel.isStoreToken());
-        providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
-        providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
-        providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
-        providerRep.setConfig(identityProviderModel.getConfig());
-        providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate());
-
-        return providerRep;
-    }
-
-    public static ProtocolMapperRepresentation toRepresentation(ProtocolMapperModel model) {
-        ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
-        rep.setId(model.getId());
-        rep.setProtocol(model.getProtocol());
-        Map<String, String> config = new HashMap<String, String>();
-        config.putAll(model.getConfig());
-        rep.setConfig(config);
-        rep.setName(model.getName());
-        rep.setProtocolMapper(model.getProtocolMapper());
-        rep.setConsentText(model.getConsentText());
-        rep.setConsentRequired(model.isConsentRequired());
-        return rep;
-    }
-
-    public static IdentityProviderMapperRepresentation toRepresentation(IdentityProviderMapperModel model) {
-        IdentityProviderMapperRepresentation rep = new IdentityProviderMapperRepresentation();
-        rep.setId(model.getId());
-        rep.setIdentityProviderMapper(model.getIdentityProviderMapper());
-        rep.setIdentityProviderAlias(model.getIdentityProviderAlias());
-        Map<String, String> config = new HashMap<String, String>();
-        config.putAll(model.getConfig());
-        rep.setConfig(config);
-        rep.setName(model.getName());
-        return rep;
-    }
-
-    public static UserConsentRepresentation toRepresentation(UserConsentModel model) {
-        String clientId = model.getClient().getClientId();
-
-        Map<String, List<String>> grantedProtocolMappers = new HashMap<String, List<String>>();
-        for (ProtocolMapperModel protocolMapper : model.getGrantedProtocolMappers()) {
-            String protocol = protocolMapper.getProtocol();
-            List<String> currentProtocolMappers = grantedProtocolMappers.get(protocol);
-            if (currentProtocolMappers == null) {
-                currentProtocolMappers = new LinkedList<String>();
-                grantedProtocolMappers.put(protocol, currentProtocolMappers);
-            }
-            currentProtocolMappers.add(protocolMapper.getName());
-        }
-
-        List<String> grantedRealmRoles = new LinkedList<String>();
-        Map<String, List<String>> grantedClientRoles = new HashMap<String, List<String>>();
-        for (RoleModel role : model.getGrantedRoles()) {
-            if (role.getContainer() instanceof RealmModel) {
-                grantedRealmRoles.add(role.getName());
-            } else {
-                ClientModel client2 = (ClientModel) role.getContainer();
-
-                String clientId2 = client2.getClientId();
-                List<String> currentClientRoles = grantedClientRoles.get(clientId2);
-                if (currentClientRoles == null) {
-                    currentClientRoles = new LinkedList<String>();
-                    grantedClientRoles.put(clientId2, currentClientRoles);
-                }
-                currentClientRoles.add(role.getName());
-            }
-        }
-
-
-        UserConsentRepresentation consentRep = new UserConsentRepresentation();
-        consentRep.setClientId(clientId);
-        consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
-        consentRep.setGrantedRealmRoles(grantedRealmRoles);
-        consentRep.setGrantedClientRoles(grantedClientRoles);
-        return consentRep;
-    }
-
-    public static AuthenticationFlowRepresentation  toRepresentation(RealmModel realm, AuthenticationFlowModel model) {
-        AuthenticationFlowRepresentation rep = new AuthenticationFlowRepresentation();
-        rep.setBuiltIn(model.isBuiltIn());
-        rep.setTopLevel(model.isTopLevel());
-        rep.setProviderId(model.getProviderId());
-        rep.setAlias(model.getAlias());
-        rep.setDescription(model.getDescription());
-        rep.setAuthenticationExecutions(new LinkedList<AuthenticationExecutionRepresentation>());
-        for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(model.getId())) {
-            rep.getAuthenticationExecutions().add(toRepresentation(realm, execution));
-        }
-        return rep;
-
-    }
-
-    public static AuthenticationExecutionRepresentation toRepresentation(RealmModel realm, AuthenticationExecutionModel model) {
-        AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
-        if (model.getAuthenticatorConfig() != null) {
-            AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(model.getAuthenticatorConfig());
-            rep.setAuthenticatorConfig(config.getAlias());
-        }
-        rep.setAuthenticator(model.getAuthenticator());
-        rep.setAutheticatorFlow(model.isAutheticatorFlow());
-        if (model.getFlowId() != null) {
-            AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
-            rep.setFlowAlias(flow.getAlias());
-       }
-        rep.setPriority(model.getPriority());
-        rep.setUserSetupAllowed(model.isUserSetupAllowed());
-        rep.setRequirement(model.getRequirement().name());
-        return rep;
-    }
-
-    public static AuthenticatorConfigRepresentation toRepresentation(AuthenticatorConfigModel model) {
-        AuthenticatorConfigRepresentation rep = new AuthenticatorConfigRepresentation();
-        rep.setAlias(model.getAlias());
-        rep.setConfig(model.getConfig());
-        return rep;
-    }
-
-
-}
+package org.keycloak.models.utils;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+
+import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.FederatedIdentityRepresentation;
+import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserConsentRepresentation;
+import org.keycloak.representations.idm.UserFederationMapperRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.util.Time;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ModelToRepresentation {
+    public static UserRepresentation toRepresentation(UserModel user) {
+        UserRepresentation rep = new UserRepresentation();
+        rep.setId(user.getId());
+        rep.setUsername(user.getUsername());
+        rep.setCreatedTimestamp(user.getCreatedTimestamp());
+        rep.setLastName(user.getLastName());
+        rep.setFirstName(user.getFirstName());
+        rep.setEmail(user.getEmail());
+        rep.setEnabled(user.isEnabled());
+        rep.setEmailVerified(user.isEmailVerified());
+        rep.setTotp(user.isTotp());
+        rep.setFederationLink(user.getFederationLink());
+
+        List<String> reqActions = new ArrayList<String>();
+        Set<String> requiredActions = user.getRequiredActions();
+        for (String ra : requiredActions){
+            reqActions.add(ra);
+        }
+
+        rep.setRequiredActions(reqActions);
+
+        if (user.getAttributes() != null && !user.getAttributes().isEmpty()) {
+            Map<String, Object> attrs = new HashMap<>();
+            attrs.putAll(user.getAttributes());
+            rep.setAttributes(attrs);
+        }
+        return rep;
+    }
+
+    public static RoleRepresentation toRepresentation(RoleModel role) {
+        RoleRepresentation rep = new RoleRepresentation();
+        rep.setId(role.getId());
+        rep.setName(role.getName());
+        rep.setDescription(role.getDescription());
+        rep.setComposite(role.isComposite());
+        return rep;
+    }
+
+    public static RealmRepresentation toRepresentation(RealmModel realm, boolean internal) {
+        RealmRepresentation rep = new RealmRepresentation();
+        rep.setId(realm.getId());
+        rep.setRealm(realm.getName());
+        rep.setEnabled(realm.isEnabled());
+        rep.setNotBefore(realm.getNotBefore());
+        rep.setSslRequired(realm.getSslRequired().name().toLowerCase());
+        rep.setPublicKey(realm.getPublicKeyPem());
+        if (internal) {
+            rep.setPrivateKey(realm.getPrivateKeyPem());
+            String privateKeyPem = realm.getPrivateKeyPem();
+            if (realm.getCertificatePem() == null && privateKeyPem != null) {
+                KeycloakModelUtils.generateRealmCertificate(realm);
+            }
+            rep.setCodeSecret(realm.getCodeSecret());
+        }
+        rep.setCertificate(realm.getCertificatePem());
+        rep.setRegistrationAllowed(realm.isRegistrationAllowed());
+        rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername());
+        rep.setRememberMe(realm.isRememberMe());
+        rep.setBruteForceProtected(realm.isBruteForceProtected());
+        rep.setMaxFailureWaitSeconds(realm.getMaxFailureWaitSeconds());
+        rep.setMinimumQuickLoginWaitSeconds(realm.getMinimumQuickLoginWaitSeconds());
+        rep.setWaitIncrementSeconds(realm.getWaitIncrementSeconds());
+        rep.setQuickLoginCheckMilliSeconds(realm.getQuickLoginCheckMilliSeconds());
+        rep.setMaxDeltaTimeSeconds(realm.getMaxDeltaTimeSeconds());
+        rep.setFailureFactor(realm.getFailureFactor());
+
+        rep.setEventsEnabled(realm.isEventsEnabled());
+        if (realm.getEventsExpiration() != 0) {
+            rep.setEventsExpiration(realm.getEventsExpiration());
+        }
+        if (realm.getEventsListeners() != null) {
+            rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
+        }
+        if (realm.getEnabledEventTypes() != null) {
+            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
+        }
+
+        rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
+        rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
+
+        rep.setVerifyEmail(realm.isVerifyEmail());
+        rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
+        rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
+        rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
+        rep.setSsoSessionIdleTimeout(realm.getSsoSessionIdleTimeout());
+        rep.setSsoSessionMaxLifespan(realm.getSsoSessionMaxLifespan());
+        rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
+        rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
+        rep.setAccessCodeLifespanLogin(realm.getAccessCodeLifespanLogin());
+        rep.setSmtpServer(realm.getSmtpConfig());
+        rep.setBrowserSecurityHeaders(realm.getBrowserSecurityHeaders());
+        rep.setAccountTheme(realm.getAccountTheme());
+        rep.setLoginTheme(realm.getLoginTheme());
+        rep.setAdminTheme(realm.getAdminTheme());
+        rep.setEmailTheme(realm.getEmailTheme());
+        if (realm.getPasswordPolicy() != null) {
+            rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
+        }
+
+        List<String> defaultRoles = realm.getDefaultRoles();
+        if (!defaultRoles.isEmpty()) {
+            List<String> roleStrings = new ArrayList<String>();
+            roleStrings.addAll(defaultRoles);
+            rep.setDefaultRoles(roleStrings);
+        }
+
+        List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
+        if (requiredCredentialModels.size() > 0) {
+            rep.setRequiredCredentials(new HashSet<String>());
+            for (RequiredCredentialModel cred : requiredCredentialModels) {
+                rep.getRequiredCredentials().add(cred.getType());
+            }
+        }
+
+        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
+        if (fedProviderModels.size() > 0) {
+            List<UserFederationProviderRepresentation> fedProviderReps = new ArrayList<UserFederationProviderRepresentation>();
+            for (UserFederationProviderModel model : fedProviderModels) {
+                UserFederationProviderRepresentation fedProvRep = toRepresentation(model);
+                fedProviderReps.add(fedProvRep);
+            }
+            rep.setUserFederationProviders(fedProviderReps);
+        }
+
+        for (UserFederationMapperModel mapper : realm.getUserFederationMappers()) {
+            rep.addUserFederationMapper(toRepresentation(realm, mapper));
+        }
+
+        for (IdentityProviderModel provider : realm.getIdentityProviders()) {
+            rep.addIdentityProvider(toRepresentation(provider));
+        }
+
+        for (IdentityProviderMapperModel mapper : realm.getIdentityProviderMappers()) {
+            rep.addIdentityProviderMapper(toRepresentation(mapper));
+        }
+
+        rep.setInternationalizationEnabled(realm.isInternationalizationEnabled());
+        rep.getSupportedLocales().addAll(realm.getSupportedLocales());
+        rep.setDefaultLocale(realm.getDefaultLocale());
+        if (internal) {
+            exportAuthenticationFlows(realm, rep);
+        }
+        return rep;
+    }
+
+    public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) {
+        rep.setAuthenticationFlows(new LinkedList<AuthenticationFlowRepresentation>());
+        rep.setAuthenticatorConfig(new LinkedList<AuthenticatorConfigRepresentation>());
+        for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) {
+            AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model);
+            rep.getAuthenticationFlows().add(flowRep);
+        }
+        for (AuthenticatorConfigModel model : realm.getAuthenticatorConfigs()) {
+            rep.getAuthenticatorConfig().add(toRepresentation(model));
+        }
+
+    }
+
+
+    public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) {
+        RealmEventsConfigRepresentation rep = new RealmEventsConfigRepresentation();
+        rep.setEventsEnabled(realm.isEventsEnabled());
+
+        if (realm.getEventsExpiration() != 0) {
+            rep.setEventsExpiration(realm.getEventsExpiration());
+        }
+
+        if (realm.getEventsListeners() != null) {
+            rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
+        }
+        
+        if(realm.getEnabledEventTypes() != null) {
+            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
+        }
+        
+        rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
+        
+        rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
+        
+        return rep;
+    }
+
+    public static CredentialRepresentation toRepresentation(UserCredentialModel cred) {
+        CredentialRepresentation rep = new CredentialRepresentation();
+        rep.setType(CredentialRepresentation.SECRET);
+        rep.setValue(cred.getValue());
+        return rep;
+    }
+
+    public static FederatedIdentityRepresentation toRepresentation(FederatedIdentityModel socialLink) {
+        FederatedIdentityRepresentation rep = new FederatedIdentityRepresentation();
+        rep.setUserName(socialLink.getUserName());
+        rep.setIdentityProvider(socialLink.getIdentityProvider());
+        rep.setUserId(socialLink.getUserId());
+        return rep;
+    }
+
+    public static UserSessionRepresentation toRepresentation(UserSessionModel session) {
+        UserSessionRepresentation rep = new UserSessionRepresentation();
+        rep.setId(session.getId());
+        rep.setStart(Time.toMillis(session.getStarted()));
+        rep.setLastAccess(Time.toMillis(session.getLastSessionRefresh()));
+        rep.setUsername(session.getUser().getUsername());
+        rep.setUserId(session.getUser().getId());
+        rep.setIpAddress(session.getIpAddress());
+        for (ClientSessionModel clientSession : session.getClientSessions()) {
+            ClientModel client = clientSession.getClient();
+            rep.getClients().put(client.getId(), client.getClientId());
+        }
+        return rep;
+    }
+
+    public static ClientRepresentation toRepresentation(ClientModel clientModel) {
+        ClientRepresentation rep = new ClientRepresentation();
+        rep.setId(clientModel.getId());
+        rep.setClientId(clientModel.getClientId());
+        rep.setName(clientModel.getName());
+        rep.setEnabled(clientModel.isEnabled());
+        rep.setAdminUrl(clientModel.getManagementUrl());
+        rep.setPublicClient(clientModel.isPublicClient());
+        rep.setFrontchannelLogout(clientModel.isFrontchannelLogout());
+        rep.setProtocol(clientModel.getProtocol());
+        rep.setAttributes(clientModel.getAttributes());
+        rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
+        rep.setBearerOnly(clientModel.isBearerOnly());
+        rep.setConsentRequired(clientModel.isConsentRequired());
+        rep.setDirectGrantsOnly(clientModel.isDirectGrantsOnly());
+        rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired());
+        rep.setBaseUrl(clientModel.getBaseUrl());
+        rep.setNotBefore(clientModel.getNotBefore());
+        rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
+
+        Set<String> redirectUris = clientModel.getRedirectUris();
+        if (redirectUris != null) {
+            rep.setRedirectUris(new LinkedList<>(redirectUris));
+        }
+
+        Set<String> webOrigins = clientModel.getWebOrigins();
+        if (webOrigins != null) {
+            rep.setWebOrigins(new LinkedList<>(webOrigins));
+        }
+
+        if (!clientModel.getDefaultRoles().isEmpty()) {
+            rep.setDefaultRoles(clientModel.getDefaultRoles().toArray(new String[0]));
+        }
+
+        if (!clientModel.getRegisteredNodes().isEmpty()) {
+            rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
+        }
+
+        if (!clientModel.getProtocolMappers().isEmpty()) {
+            List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
+            for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
+                mappings.add(toRepresentation(model));
+            }
+            rep.setProtocolMappers(mappings);
+        }
+
+        return rep;
+    }
+
+    public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
+        UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
+        rep.setId(model.getId());
+        rep.setConfig(model.getConfig());
+        rep.setProviderName(model.getProviderName());
+        rep.setPriority(model.getPriority());
+        rep.setDisplayName(model.getDisplayName());
+        rep.setFullSyncPeriod(model.getFullSyncPeriod());
+        rep.setChangedSyncPeriod(model.getChangedSyncPeriod());
+        rep.setLastSync(model.getLastSync());
+        return rep;
+    }
+
+    public static UserFederationMapperRepresentation toRepresentation(RealmModel realm, UserFederationMapperModel model) {
+        UserFederationMapperRepresentation rep = new UserFederationMapperRepresentation();
+        rep.setId(model.getId());
+        rep.setName(model.getName());
+        rep.setFederationMapperType(model.getFederationMapperType());
+        Map<String, String> config = new HashMap<String, String>();
+        config.putAll(model.getConfig());
+        rep.setConfig(config);
+
+        UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderById(model.getFederationProviderId(), realm);
+        if (fedProvider == null) {
+            throw new ModelException("Couldn't find federation provider with ID " + model.getId());
+        }
+        rep.setFederationProviderDisplayName(fedProvider.getDisplayName());
+
+        return rep;
+    }
+
+    public static IdentityProviderRepresentation toRepresentation(IdentityProviderModel identityProviderModel) {
+        IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();
+
+        providerRep.setInternalId(identityProviderModel.getInternalId());
+        providerRep.setProviderId(identityProviderModel.getProviderId());
+        providerRep.setAlias(identityProviderModel.getAlias());
+        providerRep.setEnabled(identityProviderModel.isEnabled());
+        providerRep.setStoreToken(identityProviderModel.isStoreToken());
+        providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
+        providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
+        providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
+        providerRep.setConfig(identityProviderModel.getConfig());
+        providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate());
+
+        return providerRep;
+    }
+
+    public static ProtocolMapperRepresentation toRepresentation(ProtocolMapperModel model) {
+        ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
+        rep.setId(model.getId());
+        rep.setProtocol(model.getProtocol());
+        Map<String, String> config = new HashMap<String, String>();
+        config.putAll(model.getConfig());
+        rep.setConfig(config);
+        rep.setName(model.getName());
+        rep.setProtocolMapper(model.getProtocolMapper());
+        rep.setConsentText(model.getConsentText());
+        rep.setConsentRequired(model.isConsentRequired());
+        return rep;
+    }
+
+    public static IdentityProviderMapperRepresentation toRepresentation(IdentityProviderMapperModel model) {
+        IdentityProviderMapperRepresentation rep = new IdentityProviderMapperRepresentation();
+        rep.setId(model.getId());
+        rep.setIdentityProviderMapper(model.getIdentityProviderMapper());
+        rep.setIdentityProviderAlias(model.getIdentityProviderAlias());
+        Map<String, String> config = new HashMap<String, String>();
+        config.putAll(model.getConfig());
+        rep.setConfig(config);
+        rep.setName(model.getName());
+        return rep;
+    }
+
+    public static UserConsentRepresentation toRepresentation(UserConsentModel model) {
+        String clientId = model.getClient().getClientId();
+
+        Map<String, List<String>> grantedProtocolMappers = new HashMap<String, List<String>>();
+        for (ProtocolMapperModel protocolMapper : model.getGrantedProtocolMappers()) {
+            String protocol = protocolMapper.getProtocol();
+            List<String> currentProtocolMappers = grantedProtocolMappers.get(protocol);
+            if (currentProtocolMappers == null) {
+                currentProtocolMappers = new LinkedList<String>();
+                grantedProtocolMappers.put(protocol, currentProtocolMappers);
+            }
+            currentProtocolMappers.add(protocolMapper.getName());
+        }
+
+        List<String> grantedRealmRoles = new LinkedList<String>();
+        Map<String, List<String>> grantedClientRoles = new HashMap<String, List<String>>();
+        for (RoleModel role : model.getGrantedRoles()) {
+            if (role.getContainer() instanceof RealmModel) {
+                grantedRealmRoles.add(role.getName());
+            } else {
+                ClientModel client2 = (ClientModel) role.getContainer();
+
+                String clientId2 = client2.getClientId();
+                List<String> currentClientRoles = grantedClientRoles.get(clientId2);
+                if (currentClientRoles == null) {
+                    currentClientRoles = new LinkedList<String>();
+                    grantedClientRoles.put(clientId2, currentClientRoles);
+                }
+                currentClientRoles.add(role.getName());
+            }
+        }
+
+
+        UserConsentRepresentation consentRep = new UserConsentRepresentation();
+        consentRep.setClientId(clientId);
+        consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
+        consentRep.setGrantedRealmRoles(grantedRealmRoles);
+        consentRep.setGrantedClientRoles(grantedClientRoles);
+        return consentRep;
+    }
+
+    public static AuthenticationFlowRepresentation  toRepresentation(RealmModel realm, AuthenticationFlowModel model) {
+        AuthenticationFlowRepresentation rep = new AuthenticationFlowRepresentation();
+        rep.setBuiltIn(model.isBuiltIn());
+        rep.setTopLevel(model.isTopLevel());
+        rep.setProviderId(model.getProviderId());
+        rep.setAlias(model.getAlias());
+        rep.setDescription(model.getDescription());
+        rep.setAuthenticationExecutions(new LinkedList<AuthenticationExecutionRepresentation>());
+        for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(model.getId())) {
+            rep.getAuthenticationExecutions().add(toRepresentation(realm, execution));
+        }
+        return rep;
+
+    }
+
+    public static AuthenticationExecutionRepresentation toRepresentation(RealmModel realm, AuthenticationExecutionModel model) {
+        AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
+        if (model.getAuthenticatorConfig() != null) {
+            AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(model.getAuthenticatorConfig());
+            rep.setAuthenticatorConfig(config.getAlias());
+        }
+        rep.setAuthenticator(model.getAuthenticator());
+        rep.setAutheticatorFlow(model.isAutheticatorFlow());
+        if (model.getFlowId() != null) {
+            AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
+            rep.setFlowAlias(flow.getAlias());
+       }
+        rep.setPriority(model.getPriority());
+        rep.setUserSetupAllowed(model.isUserSetupAllowed());
+        rep.setRequirement(model.getRequirement().name());
+        return rep;
+    }
+
+    public static AuthenticatorConfigRepresentation toRepresentation(AuthenticatorConfigModel model) {
+        AuthenticatorConfigRepresentation rep = new AuthenticatorConfigRepresentation();
+        rep.setAlias(model.getAlias());
+        rep.setConfig(model.getConfig());
+        return rep;
+    }
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 3bdaffd..d339875 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1,1082 +1,1082 @@
-package org.keycloak.models.utils;
-
-import net.iharder.Base64;
-import org.jboss.logging.Logger;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.migration.MigrationProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.BrowserSecurityHeaders;
-import org.keycloak.models.ClaimMask;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.ApplicationRepresentation;
-import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
-import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
-import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
-import org.keycloak.representations.idm.ClaimRepresentation;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.FederatedIdentityRepresentation;
-import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
-import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.ScopeMappingRepresentation;
-import org.keycloak.representations.idm.SocialLinkRepresentation;
-import org.keycloak.representations.idm.UserConsentRepresentation;
-import org.keycloak.representations.idm.UserFederationMapperRepresentation;
-import org.keycloak.representations.idm.UserFederationProviderRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.util.UriUtils;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class RepresentationToModel {
-
-    private static Logger logger = Logger.getLogger(RepresentationToModel.class);
-
-    public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) {
-        convertDeprecatedSocialProviders(rep);
-        convertDeprecatedApplications(session, rep);
-
-        newRealm.setName(rep.getRealm());
-        if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
-        if (rep.isBruteForceProtected() != null) newRealm.setBruteForceProtected(rep.isBruteForceProtected());
-        if (rep.getMaxFailureWaitSeconds() != null) newRealm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
-        if (rep.getMinimumQuickLoginWaitSeconds() != null) newRealm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
-        if (rep.getWaitIncrementSeconds() != null) newRealm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
-        if (rep.getQuickLoginCheckMilliSeconds() != null) newRealm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
-        if (rep.getMaxDeltaTimeSeconds() != null) newRealm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
-        if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
-        if (rep.isEventsEnabled() != null) newRealm.setEventsEnabled(rep.isEventsEnabled());
-        if (rep.getEventsExpiration() != null) newRealm.setEventsExpiration(rep.getEventsExpiration());
-        if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
-        if (rep.isAdminEventsEnabled() != null) newRealm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
-        if (rep.isAdminEventsDetailsEnabled() != null) newRealm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
-
-        if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
-
-        if (rep.getAccessTokenLifespan() != null) newRealm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
-        else newRealm.setAccessTokenLifespan(300);
-
-        if (rep.getSsoSessionIdleTimeout() != null) newRealm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
-        else newRealm.setSsoSessionIdleTimeout(1800);
-        if (rep.getSsoSessionMaxLifespan() != null) newRealm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
-        else newRealm.setSsoSessionMaxLifespan(36000);
-
-        if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
-        else newRealm.setAccessCodeLifespan(60);
-
-        if (rep.getAccessCodeLifespanUserAction() != null)
-            newRealm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
-        else newRealm.setAccessCodeLifespanUserAction(300);
-
-        if (rep.getAccessCodeLifespanLogin() != null)
-            newRealm.setAccessCodeLifespanLogin(rep.getAccessCodeLifespanLogin());
-        else newRealm.setAccessCodeLifespanLogin(1800);
-
-        if (rep.getSslRequired() != null) newRealm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
-        if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
-        if (rep.isRegistrationEmailAsUsername() != null)
-            newRealm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
-        if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
-        if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
-        if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
-        if (rep.isEditUsernameAllowed() != null) newRealm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
-        if (rep.getPrivateKey() == null || rep.getPublicKey() == null) {
-            KeycloakModelUtils.generateRealmKeys(newRealm);
-        } else {
-            newRealm.setPrivateKeyPem(rep.getPrivateKey());
-            newRealm.setPublicKeyPem(rep.getPublicKey());
-        }
-        if (rep.getCertificate() == null) {
-            KeycloakModelUtils.generateRealmCertificate(newRealm);
-        } else {
-            newRealm.setCertificatePem(rep.getCertificate());
-        }
-        if (rep.getCodeSecret() == null) {
-            newRealm.setCodeSecret(KeycloakModelUtils.generateCodeSecret());
-        } else {
-            newRealm.setCodeSecret(rep.getCodeSecret());
-        }
-
-        if (rep.getLoginTheme() != null) newRealm.setLoginTheme(rep.getLoginTheme());
-        if (rep.getAccountTheme() != null) newRealm.setAccountTheme(rep.getAccountTheme());
-        if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAdminTheme());
-        if (rep.getEmailTheme() != null) newRealm.setEmailTheme(rep.getEmailTheme());
-
-        if (rep.getRequiredCredentials() != null) {
-            for (String requiredCred : rep.getRequiredCredentials()) {
-                addRequiredCredential(newRealm, requiredCred);
-            }
-        } else {
-            addRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
-        }
-
-        if (rep.getPasswordPolicy() != null) newRealm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
-
-        importIdentityProviders(rep, newRealm);
-        importIdentityProviderMappers(rep, newRealm);
-
-        if (rep.getClients() != null) {
-            createClients(session, rep, newRealm);
-        }
-
-        if (rep.getRoles() != null) {
-            if (rep.getRoles().getRealm() != null) { // realm roles
-                for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
-                    createRole(newRealm, roleRep);
-                }
-            }
-            if (rep.getRoles().getClient() != null) {
-                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
-                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
-                    if (client == null) {
-                        throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
-                    }
-                    for (RoleRepresentation roleRep : entry.getValue()) {
-                        // Application role may already exists (for example if it is defaultRole)
-                        RoleModel role = roleRep.getId()!=null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName());
-                        role.setDescription(roleRep.getDescription());
-                    }
-                }
-            }
-            // now that all roles are created, re-iterate and set up composites
-            if (rep.getRoles().getRealm() != null) { // realm roles
-                for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
-                    RoleModel role = newRealm.getRole(roleRep.getName());
-                    addComposites(role, roleRep, newRealm);
-                }
-            }
-            if (rep.getRoles().getClient() != null) {
-                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
-                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
-                    if (client == null) {
-                        throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
-                    }
-                    for (RoleRepresentation roleRep : entry.getValue()) {
-                        RoleModel role = client.getRole(roleRep.getName());
-                        addComposites(role, roleRep, newRealm);
-                    }
-                }
-            }
-        }
-
-        // Setup realm default roles
-        if (rep.getDefaultRoles() != null) {
-            for (String roleString : rep.getDefaultRoles()) {
-                newRealm.addDefaultRole(roleString.trim());
-            }
-        }
-        // Setup client default roles
-        if (rep.getClients() != null) {
-            for (ClientRepresentation resourceRep : rep.getClients()) {
-                if (resourceRep.getDefaultRoles() != null) {
-                    ClientModel clientModel = newRealm.getClientByClientId(resourceRep.getClientId());
-                    clientModel.updateDefaultRoles(resourceRep.getDefaultRoles());
-                }
-            }
-        }
-
-        // Now that all possible roles and clients are created, create scope mappings
-
-        Map<String, ClientModel> appMap = newRealm.getClientNameMap();
-
-        if (rep.getClientScopeMappings() != null) {
-
-            for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getClientScopeMappings().entrySet()) {
-                ClientModel app = appMap.get(entry.getKey());
-                if (app == null) {
-                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
-                }
-                createClientScopeMappings(newRealm, app, entry.getValue());
-            }
-        }
-
-        if (rep.getScopeMappings() != null) {
-            for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
-                ClientModel client = newRealm.getClientByClientId(scope.getClient());
-                if (client == null) {
-                    throw new RuntimeException("Unknown client specification in realm scope mappings");
-                }
-                for (String roleString : scope.getRoles()) {
-                    RoleModel role = newRealm.getRole(roleString.trim());
-                    if (role == null) {
-                        role = newRealm.addRole(roleString.trim());
-                    }
-                    client.addScopeMapping(role);
-                }
-
-            }
-        }
-
-        if (rep.getSmtpServer() != null) {
-            newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
-        }
-
-        if (rep.getBrowserSecurityHeaders() != null) {
-            newRealm.setBrowserSecurityHeaders(rep.getBrowserSecurityHeaders());
-        } else {
-            newRealm.setBrowserSecurityHeaders(BrowserSecurityHeaders.defaultHeaders);
-        }
-
-        List<UserFederationProviderModel> providerModels = null;
-        if (rep.getUserFederationProviders() != null) {
-            providerModels = convertFederationProviders(rep.getUserFederationProviders());
-            newRealm.setUserFederationProviders(providerModels);
-        }
-        if (rep.getUserFederationMappers() != null) {
-
-            // Remove builtin mappers for federation providers, which have some mappers already provided in JSON (likely due to previous export)
-            if (rep.getUserFederationProviders() != null) {
-                Set<String> providerNames = new TreeSet<String>();
-                for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
-                    providerNames.add(representation.getFederationProviderDisplayName());
-                }
-                for (String providerName : providerNames) {
-                    for (UserFederationProviderModel providerModel : providerModels) {
-                        if (providerName.equals(providerModel.getDisplayName())) {
-                            Set<UserFederationMapperModel> toDelete = newRealm.getUserFederationMappersByFederationProvider(providerModel.getId());
-                            for (UserFederationMapperModel mapperModel : toDelete) {
-                                newRealm.removeUserFederationMapper(mapperModel);
-                            }
-                        }
-                    }
-                }
-            }
-
-            for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
-                newRealm.addUserFederationMapper(toModel(newRealm, representation));
-            }
-        }
-
-        // create users and their role mappings and social mappings
-
-        if (rep.getUsers() != null) {
-            for (UserRepresentation userRep : rep.getUsers()) {
-                UserModel user = createUser(session, newRealm, userRep, appMap);
-            }
-        }
-
-        if(rep.isInternationalizationEnabled() != null){
-            newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
-        }
-        if(rep.getSupportedLocales() != null){
-            newRealm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
-        }
-        if(rep.getDefaultLocale() != null){
-            newRealm.setDefaultLocale(rep.getDefaultLocale());
-        }
-
-        importAuthenticationFlows(newRealm, rep);
-    }
-
-    public static void importAuthenticationFlows(RealmModel newRealm, RealmRepresentation rep) {
-        if (rep.getAuthenticationFlows() == null) {
-            // assume this is an old version being imported
-            DefaultAuthenticationFlows.addFlows(newRealm);
-        } else {
-            for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) {
-                AuthenticatorConfigModel model = toModel(configRep);
-                newRealm.addAuthenticatorConfig(model);
-            }
-            for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
-                AuthenticationFlowModel model = toModel(flowRep);
-                model = newRealm.addAuthenticationFlow(model);
-            }
-            for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
-                AuthenticationFlowModel model = newRealm.getFlowByAlias(flowRep.getAlias());
-                for (AuthenticationExecutionRepresentation exeRep : flowRep.getAuthenticationExecutions()) {
-                    AuthenticationExecutionModel execution = toModel(newRealm, exeRep);
-                    execution.setParentFlow(model.getId());
-                    newRealm.addAuthenticatorExecution(execution);
-                }
-            }
-         }
-
-    }
-
-    private static void convertDeprecatedSocialProviders(RealmRepresentation rep) {
-        if (rep.isSocial() != null && rep.isSocial() && rep.getSocialProviders() != null && !rep.getSocialProviders().isEmpty() && rep.getIdentityProviders() == null) {
-            Boolean updateProfileFirstLogin = rep.isUpdateProfileOnInitialSocialLogin() != null && rep.isUpdateProfileOnInitialSocialLogin();
-            if (rep.getSocialProviders() != null) {
-
-                logger.warn("Using deprecated 'social' configuration in JSON representation. It will be removed in future versions");
-                List<IdentityProviderRepresentation> identityProviders = new LinkedList<>();
-                for (String k : rep.getSocialProviders().keySet()) {
-                    if (k.endsWith(".key")) {
-                        String providerId = k.split("\\.")[0];
-                        String key = rep.getSocialProviders().get(k);
-                        String secret = rep.getSocialProviders().get(k.replace(".key", ".secret"));
-
-                        IdentityProviderRepresentation identityProvider = new IdentityProviderRepresentation();
-                        identityProvider.setAlias(providerId);
-                        identityProvider.setProviderId(providerId);
-                        identityProvider.setEnabled(true);
-                        identityProvider.setUpdateProfileFirstLogin(updateProfileFirstLogin);
-
-                        Map<String, String> config = new HashMap<>();
-                        config.put("clientId", key);
-                        config.put("clientSecret", secret);
-                        identityProvider.setConfig(config);
-
-                        identityProviders.add(identityProvider);
-                    }
-                }
-                rep.setIdentityProviders(identityProviders);
-            }
-        }
-    }
-
-    private static void convertDeprecatedSocialProviders(UserRepresentation user) {
-        if (user.getSocialLinks() != null && !user.getSocialLinks().isEmpty() && user.getFederatedIdentities() == null) {
-
-            logger.warnf("Using deprecated 'socialLinks' configuration in JSON representation for user '%s'. It will be removed in future versions", user.getUsername());
-            List<FederatedIdentityRepresentation> federatedIdentities = new LinkedList<>();
-            for (SocialLinkRepresentation social : user.getSocialLinks()) {
-                FederatedIdentityRepresentation federatedIdentity = new FederatedIdentityRepresentation();
-                federatedIdentity.setIdentityProvider(social.getSocialProvider());
-                federatedIdentity.setUserId(social.getSocialUserId());
-                federatedIdentity.setUserName(social.getSocialUsername());
-                federatedIdentities.add(federatedIdentity);
-            }
-            user.setFederatedIdentities(federatedIdentities);
-        }
-
-        user.setSocialLinks(null);
-    }
-
-    private static void convertDeprecatedApplications(KeycloakSession session, RealmRepresentation realm) {
-        if (realm.getApplications() != null || realm.getOauthClients() != null) {
-            if (realm.getClients() == null) {
-                realm.setClients(new LinkedList<ClientRepresentation>());
-            }
-
-            List<ApplicationRepresentation> clients = new LinkedList<>();
-            if (realm.getApplications() != null) {
-                clients.addAll(realm.getApplications());
-            }
-            if (realm.getOauthClients() != null) {
-                clients.addAll(realm.getOauthClients());
-            }
-
-            for (ApplicationRepresentation app : clients) {
-                app.setClientId(app.getName());
-                app.setName(null);
-
-                if (app instanceof OAuthClientRepresentation) {
-                    app.setConsentRequired(true);
-                    app.setFullScopeAllowed(false);
-                }
-
-                if (app.getProtocolMappers() == null && app.getClaims() != null) {
-                    long mask = getClaimsMask(app.getClaims());
-                    List<ProtocolMapperRepresentation> convertedProtocolMappers = session.getProvider(MigrationProvider.class).getMappersForClaimMask(mask);
-                    app.setProtocolMappers(convertedProtocolMappers);
-                    app.setClaims(null);
-                }
-
-                realm.getClients().add(app);
-            }
-        }
-
-        if (realm.getApplicationScopeMappings() != null && realm.getClientScopeMappings() == null) {
-            realm.setClientScopeMappings(realm.getApplicationScopeMappings());
-        }
-
-        if (realm.getRoles() != null && realm.getRoles().getApplication() != null && realm.getRoles().getClient() == null) {
-            realm.getRoles().setClient(realm.getRoles().getApplication());
-        }
-
-        if (realm.getUsers() != null) {
-            for (UserRepresentation user : realm.getUsers()) {
-                if (user.getApplicationRoles() != null && user.getClientRoles() == null) {
-                    user.setClientRoles(user.getApplicationRoles());
-                }
-            }
-        }
-
-        if (realm.getRoles() != null && realm.getRoles().getRealm() != null) {
-            for (RoleRepresentation role : realm.getRoles().getRealm()) {
-                if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
-                    role.getComposites().setClient(role.getComposites().getApplication());
-                }
-            }
-        }
-
-        if (realm.getRoles() != null && realm.getRoles().getClient() != null) {
-            for (Map.Entry<String, List<RoleRepresentation>> clientRoles : realm.getRoles().getClient().entrySet()) {
-                for (RoleRepresentation role : clientRoles.getValue()) {
-                    if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
-                        role.getComposites().setClient(role.getComposites().getApplication());
-                    }
-                }
-            }
-        }
-    }
-
-    public static void updateRealm(RealmRepresentation rep, RealmModel realm) {
-        if (rep.getRealm() != null) {
-            realm.setName(rep.getRealm());
-        }
-        if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
-        if (rep.isBruteForceProtected() != null) realm.setBruteForceProtected(rep.isBruteForceProtected());
-        if (rep.getMaxFailureWaitSeconds() != null) realm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
-        if (rep.getMinimumQuickLoginWaitSeconds() != null) realm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
-        if (rep.getWaitIncrementSeconds() != null) realm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
-        if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
-        if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
-        if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
-        if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
-        if (rep.isRegistrationEmailAsUsername() != null) realm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
-        if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
-        if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
-        if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
-        if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
-        if (rep.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
-        if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
-        if (rep.getAccessCodeLifespanUserAction() != null) realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
-        if (rep.getAccessCodeLifespanLogin() != null) realm.setAccessCodeLifespanLogin(rep.getAccessCodeLifespanLogin());
-        if (rep.getNotBefore() != null) realm.setNotBefore(rep.getNotBefore());
-        if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
-        if (rep.getSsoSessionIdleTimeout() != null) realm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
-        if (rep.getSsoSessionMaxLifespan() != null) realm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
-        if (rep.getRequiredCredentials() != null) {
-            realm.updateRequiredCredentials(rep.getRequiredCredentials());
-        }
-        if (rep.getLoginTheme() != null) realm.setLoginTheme(rep.getLoginTheme());
-        if (rep.getAccountTheme() != null) realm.setAccountTheme(rep.getAccountTheme());
-        if (rep.getAdminTheme() != null) realm.setAdminTheme(rep.getAdminTheme());
-        if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
-        
-        if (rep.isEventsEnabled() != null) realm.setEventsEnabled(rep.isEventsEnabled());
-        if (rep.getEventsExpiration() != null) realm.setEventsExpiration(rep.getEventsExpiration());
-        if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
-        if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<>(rep.getEnabledEventTypes()));
-        
-        if (rep.isAdminEventsEnabled() != null) realm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
-        if (rep.isAdminEventsDetailsEnabled() != null) realm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
-        
-
-        if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
-
-        if (rep.getDefaultRoles() != null) {
-            realm.updateDefaultRoles(rep.getDefaultRoles().toArray(new String[rep.getDefaultRoles().size()]));
-        }
-
-        if (rep.getSmtpServer() != null) {
-            realm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
-        }
-
-        if (rep.getBrowserSecurityHeaders() != null) {
-            realm.setBrowserSecurityHeaders(rep.getBrowserSecurityHeaders());
-        }
-
-        if (rep.getUserFederationProviders() != null) {
-            List<UserFederationProviderModel> providerModels = convertFederationProviders(rep.getUserFederationProviders());
-            realm.setUserFederationProviders(providerModels);
-        }
-
-        if ("GENERATE".equals(rep.getPublicKey())) {
-            KeycloakModelUtils.generateRealmKeys(realm);
-        }
-
-        if(rep.isInternationalizationEnabled() != null){
-            realm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
-        }
-        if(rep.getSupportedLocales() != null){
-            realm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
-        }
-        if(rep.getDefaultLocale() != null){
-            realm.setDefaultLocale(rep.getDefaultLocale());
-        }
-    }
-
-    // Basic realm stuff
-
-    public static void addRequiredCredential(RealmModel newRealm, String requiredCred) {
-        newRealm.addRequiredCredential(requiredCred);
-    }
-
-
-    private static List<UserFederationProviderModel> convertFederationProviders(List<UserFederationProviderRepresentation> providers) {
-        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
-
-        for (UserFederationProviderRepresentation representation : providers) {
-            UserFederationProviderModel model = new UserFederationProviderModel(representation.getId(), representation.getProviderName(),
-                    representation.getConfig(), representation.getPriority(), representation.getDisplayName(),
-                    representation.getFullSyncPeriod(), representation.getChangedSyncPeriod(), representation.getLastSync());
-            result.add(model);
-        }
-        return result;
-    }
-
-    public static UserFederationMapperModel toModel(RealmModel realm, UserFederationMapperRepresentation rep) {
-        UserFederationMapperModel model = new UserFederationMapperModel();
-        model.setId(rep.getId());
-        model.setName(rep.getName());
-        model.setFederationMapperType(rep.getFederationMapperType());
-        model.setConfig(rep.getConfig());
-
-        UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderByDisplayName(rep.getFederationProviderDisplayName(), realm);
-        if (fedProvider == null) {
-            throw new ModelException("Couldn't find federation provider with display name [" + rep.getFederationProviderDisplayName() + "] referenced from mapper ["
-                    + rep.getName());
-        }
-        model.setFederationProviderId(fedProvider.getId());
-
-        return model;
-    }
-
-    // Roles
-
-    public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
-        RoleModel role = roleRep.getId()!=null ? newRealm.addRole(roleRep.getId(), roleRep.getName()) : newRealm.addRole(roleRep.getName());
-        if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
-    }
-
-    private static void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
-        if (roleRep.getComposites() == null) return;
-        if (roleRep.getComposites().getRealm() != null) {
-            for (String roleStr : roleRep.getComposites().getRealm()) {
-                RoleModel realmRole = realm.getRole(roleStr);
-                if (realmRole == null) throw new RuntimeException("Unable to find composite realm role: " + roleStr);
-                role.addCompositeRole(realmRole);
-            }
-        }
-        if (roleRep.getComposites().getClient() != null) {
-            for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getClient().entrySet()) {
-                ClientModel client = realm.getClientByClientId(entry.getKey());
-                if (client == null) {
-                    throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName());
-                }
-                for (String roleStr : entry.getValue()) {
-                    RoleModel clientRole = client.getRole(roleStr);
-                    if (clientRole == null) throw new RuntimeException("Unable to find composite client role: " + roleStr);
-                    role.addCompositeRole(clientRole);
-                }
-            }
-
-        }
-
-    }
-
-    // CLIENTS
-
-    private static Map<String, ClientModel> createClients(KeycloakSession session, RealmRepresentation rep, RealmModel realm) {
-        Map<String, ClientModel> appMap = new HashMap<String, ClientModel>();
-        for (ClientRepresentation resourceRep : rep.getClients()) {
-            ClientModel app = createClient(session, realm, resourceRep, false);
-            appMap.put(app.getClientId(), app);
-        }
-        return appMap;
-    }
-
-    /**
-     * Does not create scope or role mappings!
-     *
-     * @param realm
-     * @param resourceRep
-     * @return
-     */
-    public static ClientModel createClient(KeycloakSession session, RealmModel realm, ClientRepresentation resourceRep, boolean addDefaultRoles) {
-        logger.debug("Create client: {0}" + resourceRep.getClientId());
-
-        ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId());
-        if (resourceRep.getName() != null) client.setName(resourceRep.getName());
-        if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled());
-        client.setManagementUrl(resourceRep.getAdminUrl());
-        if (resourceRep.isSurrogateAuthRequired() != null)
-            client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
-        if (resourceRep.getBaseUrl() != null) client.setBaseUrl(resourceRep.getBaseUrl());
-        if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
-        if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
-        if (resourceRep.isDirectGrantsOnly() != null) client.setDirectGrantsOnly(resourceRep.isDirectGrantsOnly());
-        if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
-        if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
-        if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol());
-        if (resourceRep.isFullScopeAllowed() != null) {
-            client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
-        } else {
-            client.setFullScopeAllowed(!client.isConsentRequired());
-        }
-        if (resourceRep.getNodeReRegistrationTimeout() != null) {
-            client.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout());
-        } else {
-            client.setNodeReRegistrationTimeout(-1);
-        }
-        client.updateClient();
-
-        if (resourceRep.getNotBefore() != null) {
-            client.setNotBefore(resourceRep.getNotBefore());
-        }
-
-        client.setSecret(resourceRep.getSecret());
-        if (client.getSecret() == null) {
-            KeycloakModelUtils.generateSecret(client);
-        }
-
-        if (resourceRep.getAttributes() != null) {
-            for (Map.Entry<String, String> entry : resourceRep.getAttributes().entrySet()) {
-                client.setAttribute(entry.getKey(), entry.getValue());
-            }
-        }
-
-
-        if (resourceRep.getRedirectUris() != null) {
-            for (String redirectUri : resourceRep.getRedirectUris()) {
-                client.addRedirectUri(redirectUri);
-            }
-        }
-        if (resourceRep.getWebOrigins() != null) {
-            for (String webOrigin : resourceRep.getWebOrigins()) {
-                logger.debugv("Client: {0} webOrigin: {1}", resourceRep.getClientId(), webOrigin);
-                client.addWebOrigin(webOrigin);
-            }
-        } else {
-            // add origins from redirect uris
-            if (resourceRep.getRedirectUris() != null) {
-                Set<String> origins = new HashSet<String>();
-                for (String redirectUri : resourceRep.getRedirectUris()) {
-                    logger.debugv("add redirect-uri to origin: {0}", redirectUri);
-                    if (redirectUri.startsWith("http")) {
-                        String origin = UriUtils.getOrigin(redirectUri);
-                        logger.debugv("adding default client origin: {0}" , origin);
-                        origins.add(origin);
-                    }
-                }
-                if (origins.size() > 0) {
-                    client.setWebOrigins(origins);
-                }
-            }
-        }
-
-        if (resourceRep.getRegisteredNodes() != null) {
-            for (Map.Entry<String, Integer> entry : resourceRep.getRegisteredNodes().entrySet()) {
-                client.registerNode(entry.getKey(), entry.getValue());
-            }
-        }
-
-        if (addDefaultRoles && resourceRep.getDefaultRoles() != null) {
-            client.updateDefaultRoles(resourceRep.getDefaultRoles());
-        }
-
-        if (resourceRep.getProtocolMappers() != null) {
-            // first, remove all default/built in mappers
-            Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
-            for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper);
-
-            for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) {
-                client.addProtocolMapper(toModel(mapper));
-            }
-        }
-
-        return client;
-    }
-
-    public static void updateClient(ClientRepresentation rep, ClientModel resource) {
-        if (rep.getClientId() != null) resource.setClientId(rep.getClientId());
-        if (rep.getName() != null) resource.setName(rep.getName());
-        if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
-        if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
-        if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
-        if (rep.isDirectGrantsOnly() != null) resource.setDirectGrantsOnly(rep.isDirectGrantsOnly());
-        if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
-        if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
-        if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
-        if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
-        if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
-        if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
-        if (rep.getNodeReRegistrationTimeout() != null) resource.setNodeReRegistrationTimeout(rep.getNodeReRegistrationTimeout());
-        resource.updateClient();
-
-        if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
-        if (rep.getAttributes() != null) {
-            for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
-                resource.setAttribute(entry.getKey(), entry.getValue());
-            }
-        }
-
-
-        if (rep.getNotBefore() != null) {
-            resource.setNotBefore(rep.getNotBefore());
-        }
-        if (rep.getDefaultRoles() != null) {
-            resource.updateDefaultRoles(rep.getDefaultRoles());
-        }
-
-        List<String> redirectUris = rep.getRedirectUris();
-        if (redirectUris != null) {
-            resource.setRedirectUris(new HashSet<String>(redirectUris));
-        }
-
-        List<String> webOrigins = rep.getWebOrigins();
-        if (webOrigins != null) {
-            resource.setWebOrigins(new HashSet<String>(webOrigins));
-        }
-
-        if (rep.getRegisteredNodes() != null) {
-            for (Map.Entry<String, Integer> entry : rep.getRegisteredNodes().entrySet()) {
-                resource.registerNode(entry.getKey(), entry.getValue());
-            }
-        }
-
-    }
-
-    public static long getClaimsMask(ClaimRepresentation rep) {
-        long mask = ClaimMask.ALL;
-
-        if (rep.getAddress()) {
-            mask |= ClaimMask.ADDRESS;
-        } else {
-            mask &= ~ClaimMask.ADDRESS;
-        }
-        if (rep.getEmail()) {
-            mask |= ClaimMask.EMAIL;
-        } else {
-            mask &= ~ClaimMask.EMAIL;
-        }
-        if (rep.getGender()) {
-            mask |= ClaimMask.GENDER;
-        } else {
-            mask &= ~ClaimMask.GENDER;
-        }
-        if (rep.getLocale()) {
-            mask |= ClaimMask.LOCALE;
-        } else {
-            mask &= ~ClaimMask.LOCALE;
-        }
-        if (rep.getName()) {
-            mask |= ClaimMask.NAME;
-        } else {
-            mask &= ~ClaimMask.NAME;
-        }
-        if (rep.getPhone()) {
-            mask |= ClaimMask.PHONE;
-        } else {
-            mask &= ~ClaimMask.PHONE;
-        }
-        if (rep.getPicture()) {
-            mask |= ClaimMask.PICTURE;
-        } else {
-            mask &= ~ClaimMask.PICTURE;
-        }
-        if (rep.getProfile()) {
-            mask |= ClaimMask.PROFILE;
-        } else {
-            mask &= ~ClaimMask.PROFILE;
-        }
-        if (rep.getUsername()) {
-            mask |= ClaimMask.USERNAME;
-        } else {
-            mask &= ~ClaimMask.USERNAME;
-        }
-        if (rep.getWebsite()) {
-            mask |= ClaimMask.WEBSITE;
-        } else {
-            mask &= ~ClaimMask.WEBSITE;
-        }
-        return mask;
-    }
-
-    // Scope mappings
-
-    public static void createClientScopeMappings(RealmModel realm, ClientModel clientModel, List<ScopeMappingRepresentation> mappings) {
-        for (ScopeMappingRepresentation mapping : mappings) {
-            ClientModel client = realm.getClientByClientId(mapping.getClient());
-            if (client == null) {
-                throw new RuntimeException("Unknown client specified in client scope mappings");
-            }
-            for (String roleString : mapping.getRoles()) {
-                RoleModel role = clientModel.getRole(roleString.trim());
-                if (role == null) {
-                    role = clientModel.addRole(roleString.trim());
-                }
-                client.addScopeMapping(role);
-            }
-        }
-    }
-
-    // Users
-
-    public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map<String, ClientModel> clientMap) {
-        convertDeprecatedSocialProviders(userRep);
-
-        // Import users just to user storage. Don't federate
-        UserModel user = session.userStorage().addUser(newRealm, userRep.getId(), userRep.getUsername(), false, false);
-        user.setEnabled(userRep.isEnabled());
-        user.setCreatedTimestamp(userRep.getCreatedTimestamp());
-        user.setEmail(userRep.getEmail());
-        user.setEmailVerified(userRep.isEmailVerified());
-        user.setFirstName(userRep.getFirstName());
-        user.setLastName(userRep.getLastName());
-        user.setFederationLink(userRep.getFederationLink());
-        user.setTotp(userRep.isTotp());
-        if (userRep.getAttributes() != null) {
-            for (Map.Entry<String, Object> entry : userRep.getAttributes().entrySet()) {
-                Object value = entry.getValue();
-
-                if (value instanceof Collection) {
-                    Collection<String> colVal = (Collection<String>) value;
-                    user.setAttribute(entry.getKey(), new ArrayList<>(colVal));
-                } else if (value instanceof String) {
-                    // TODO: This is here just for backwards compatibility with KC 1.3 and earlier
-                    String stringVal = (String) value;
-                    user.setSingleAttribute(entry.getKey(), stringVal);
-                }
-            }
-        }
-        if (userRep.getRequiredActions() != null) {
-            for (String requiredAction : userRep.getRequiredActions()) {
-                user.addRequiredAction(UserModel.RequiredAction.valueOf(requiredAction));
-            }
-        }
-        if (userRep.getCredentials() != null) {
-            for (CredentialRepresentation cred : userRep.getCredentials()) {
-                updateCredential(user, cred);
-            }
-        }
-        if (userRep.getFederatedIdentities() != null) {
-            for (FederatedIdentityRepresentation identity : userRep.getFederatedIdentities()) {
-                FederatedIdentityModel mappingModel = new FederatedIdentityModel(identity.getIdentityProvider(), identity.getUserId(), identity.getUserName());
-                session.users().addFederatedIdentity(newRealm, user, mappingModel);
-            }
-        }
-        if (userRep.getRealmRoles() != null) {
-            for (String roleString : userRep.getRealmRoles()) {
-                RoleModel role = newRealm.getRole(roleString.trim());
-                if (role == null) {
-                    role = newRealm.addRole(roleString.trim());
-                }
-                user.grantRole(role);
-            }
-        }
-        if (userRep.getClientRoles() != null) {
-            for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
-                ClientModel client = clientMap.get(entry.getKey());
-                if (client == null) {
-                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
-                }
-                createClientRoleMappings(client, user, entry.getValue());
-            }
-        }
-        if (userRep.getClientConsents() != null) {
-            for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
-                UserConsentModel consentModel = toModel(newRealm, consentRep);
-                user.addConsent(consentModel);
-            }
-        }
-        return user;
-    }
-
-    // Detect if it is "plain-text" or "hashed" representation and update model according to it
-    private static void updateCredential(UserModel user, CredentialRepresentation cred) {
-        if (cred.getValue() != null) {
-            UserCredentialModel plainTextCred = convertCredential(cred);
-            user.updateCredential(plainTextCred);
-        } else {
-            UserCredentialValueModel hashedCred = new UserCredentialValueModel();
-            hashedCred.setType(cred.getType());
-            hashedCred.setDevice(cred.getDevice());
-            hashedCred.setHashIterations(cred.getHashIterations());
-            try {
-                if (cred.getSalt() != null) hashedCred.setSalt(Base64.decode(cred.getSalt()));
-            } catch (IOException ioe) {
-                throw new RuntimeException(ioe);
-            }
-            hashedCred.setValue(cred.getHashedSaltedValue());
-            user.updateCredentialDirectly(hashedCred);
-        }
-    }
-
-    public static UserCredentialModel convertCredential(CredentialRepresentation cred) {
-        UserCredentialModel credential = new UserCredentialModel();
-        credential.setType(cred.getType());
-        credential.setValue(cred.getValue());
-        return credential;
-    }
-
-    // Role mappings
-
-    public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List<String> roleNames) {
-        if (user == null) {
-            throw new RuntimeException("User not found");
-        }
-
-        for (String roleName : roleNames) {
-            RoleModel role = clientModel.getRole(roleName.trim());
-            if (role == null) {
-                role = clientModel.addRole(roleName.trim());
-            }
-            user.grantRole(role);
-
-        }
-    }
-
-    private static void importIdentityProviders(RealmRepresentation rep, RealmModel newRealm) {
-        if (rep.getIdentityProviders() != null) {
-            for (IdentityProviderRepresentation representation : rep.getIdentityProviders()) {
-                newRealm.addIdentityProvider(toModel(representation));
-            }
-        }
-    }
-    private static void importIdentityProviderMappers(RealmRepresentation rep, RealmModel newRealm) {
-        if (rep.getIdentityProviderMappers() != null) {
-            for (IdentityProviderMapperRepresentation representation : rep.getIdentityProviderMappers()) {
-                newRealm.addIdentityProviderMapper(toModel(representation));
-            }
-        }
-    }
-   public static IdentityProviderModel toModel(IdentityProviderRepresentation representation) {
-        IdentityProviderModel identityProviderModel = new IdentityProviderModel();
-
-        identityProviderModel.setInternalId(representation.getInternalId());
-        identityProviderModel.setAlias(representation.getAlias());
-        identityProviderModel.setProviderId(representation.getProviderId());
-        identityProviderModel.setEnabled(representation.isEnabled());
-        identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
-        identityProviderModel.setTrustEmail(representation.isTrustEmail());
-        identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
-        identityProviderModel.setStoreToken(representation.isStoreToken());
-        identityProviderModel.setAddReadTokenRoleOnCreate(representation.isAddReadTokenRoleOnCreate());
-        identityProviderModel.setConfig(representation.getConfig());
-
-        return identityProviderModel;
-    }
-
-    public static ProtocolMapperModel toModel(ProtocolMapperRepresentation rep) {
-        ProtocolMapperModel model = new ProtocolMapperModel();
-        model.setId(rep.getId());
-        model.setName(rep.getName());
-        model.setConsentRequired(rep.isConsentRequired());
-        model.setConsentText(rep.getConsentText());
-        model.setProtocol(rep.getProtocol());
-        model.setProtocolMapper(rep.getProtocolMapper());
-        model.setConfig(rep.getConfig());
-        return model;
-    }
-
-    public static IdentityProviderMapperModel toModel(IdentityProviderMapperRepresentation rep) {
-        IdentityProviderMapperModel model = new IdentityProviderMapperModel();
-        model.setId(rep.getId());
-        model.setName(rep.getName());
-        model.setIdentityProviderAlias(rep.getIdentityProviderAlias());
-        model.setIdentityProviderMapper(rep.getIdentityProviderMapper());
-        model.setConfig(rep.getConfig());
-        return model;
-    }
-
-    public static UserConsentModel toModel(RealmModel newRealm, UserConsentRepresentation consentRep) {
-        ClientModel client = newRealm.getClientByClientId(consentRep.getClientId());
-        if (client == null) {
-            throw new RuntimeException("Unable to find client consent mappings for client: " + consentRep.getClientId());
-        }
-
-        UserConsentModel consentModel = new UserConsentModel(client);
-
-        if (consentRep.getGrantedRealmRoles() != null) {
-            for (String roleName : consentRep.getGrantedRealmRoles()) {
-                RoleModel role = newRealm.getRole(roleName);
-                if (role == null) {
-                    throw new RuntimeException("Unable to find realm role referenced in consent mappings of user. Role name: " + roleName);
-                }
-                consentModel.addGrantedRole(role);
-            }
-        }
-        if (consentRep.getGrantedClientRoles() != null) {
-            for (Map.Entry<String, List<String>> entry : consentRep.getGrantedClientRoles().entrySet()) {
-                String clientId2 = entry.getKey();
-                ClientModel client2 = newRealm.getClientByClientId(clientId2);
-                if (client2 == null) {
-                    throw new RuntimeException("Unable to find client referenced in consent mappings. Client ID: " + clientId2);
-                }
-                for (String clientRoleName : entry.getValue()) {
-                    RoleModel clientRole = client2.getRole(clientRoleName);
-                    if (clientRole == null) {
-                        throw new RuntimeException("Unable to find client role referenced in consent mappings of user. Role name: " + clientRole + ", Client: " + clientId2);
-                    }
-                    consentModel.addGrantedRole(clientRole);
-                }
-            }
-        }
-        if (consentRep.getGrantedProtocolMappers() != null) {
-            for (Map.Entry<String, List<String>> protocolEntry : consentRep.getGrantedProtocolMappers().entrySet()) {
-                String protocol = protocolEntry.getKey();
-                for (String protocolMapperName : protocolEntry.getValue()) {
-                    ProtocolMapperModel protocolMapper = client.getProtocolMapperByName(protocol, protocolMapperName);
-                    if (protocolMapper == null) {
-                        throw new RuntimeException("Unable to find protocol mapper for protocol " + protocol + ", mapper name " + protocolMapperName);
-                    }
-
-                    consentModel.addGrantedProtocolMapper(protocolMapper);
-                }
-            }
-        }
-        return consentModel;
-    }
-
-    public static AuthenticationFlowModel toModel(AuthenticationFlowRepresentation rep) {
-        AuthenticationFlowModel model = new AuthenticationFlowModel();
-        model.setBuiltIn(rep.isBuiltIn());
-        model.setTopLevel(rep.isTopLevel());
-        model.setProviderId(rep.getProviderId());
-        model.setAlias(rep.getAlias());
-        model.setDescription(rep.getDescription());
-        return model;
-
-    }
-
-    public static AuthenticationExecutionModel toModel(RealmModel realm, AuthenticationExecutionRepresentation rep) {
-        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
-        if (rep.getAuthenticatorConfig() != null) {
-            AuthenticatorConfigModel config = realm.getAuthenticatorConfigByAlias(rep.getAuthenticatorConfig());
-            model.setAuthenticatorConfig(config.getId());
-        }
-        model.setAuthenticator(rep.getAuthenticator());
-        model.setAutheticatorFlow(rep.isAutheticatorFlow());
-        if (rep.getFlowAlias() != null) {
-            AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
-            model.setFlowId(flow.getId());
-        }
-        model.setPriority(rep.getPriority());
-        model.setUserSetupAllowed(rep.isUserSetupAllowed());
-        model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
-        return model;
-    }
-
-    public static AuthenticatorConfigModel toModel(AuthenticatorConfigRepresentation rep) {
-        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
-        model.setAlias(rep.getAlias());
-        model.setConfig(rep.getConfig());
-        return model;
-    }
-
-
-}
+package org.keycloak.models.utils;
+
+import net.iharder.Base64;
+import org.jboss.logging.Logger;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.migration.MigrationProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.BrowserSecurityHeaders;
+import org.keycloak.models.ClaimMask;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
+import org.keycloak.representations.idm.ClaimRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.FederatedIdentityRepresentation;
+import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.ScopeMappingRepresentation;
+import org.keycloak.representations.idm.SocialLinkRepresentation;
+import org.keycloak.representations.idm.UserConsentRepresentation;
+import org.keycloak.representations.idm.UserFederationMapperRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.util.UriUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class RepresentationToModel {
+
+    private static Logger logger = Logger.getLogger(RepresentationToModel.class);
+
+    public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) {
+        convertDeprecatedSocialProviders(rep);
+        convertDeprecatedApplications(session, rep);
+
+        newRealm.setName(rep.getRealm());
+        if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
+        if (rep.isBruteForceProtected() != null) newRealm.setBruteForceProtected(rep.isBruteForceProtected());
+        if (rep.getMaxFailureWaitSeconds() != null) newRealm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
+        if (rep.getMinimumQuickLoginWaitSeconds() != null) newRealm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
+        if (rep.getWaitIncrementSeconds() != null) newRealm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
+        if (rep.getQuickLoginCheckMilliSeconds() != null) newRealm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
+        if (rep.getMaxDeltaTimeSeconds() != null) newRealm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
+        if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
+        if (rep.isEventsEnabled() != null) newRealm.setEventsEnabled(rep.isEventsEnabled());
+        if (rep.getEventsExpiration() != null) newRealm.setEventsExpiration(rep.getEventsExpiration());
+        if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
+        if (rep.isAdminEventsEnabled() != null) newRealm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
+        if (rep.isAdminEventsDetailsEnabled() != null) newRealm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
+
+        if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
+
+        if (rep.getAccessTokenLifespan() != null) newRealm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
+        else newRealm.setAccessTokenLifespan(300);
+
+        if (rep.getSsoSessionIdleTimeout() != null) newRealm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
+        else newRealm.setSsoSessionIdleTimeout(1800);
+        if (rep.getSsoSessionMaxLifespan() != null) newRealm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
+        else newRealm.setSsoSessionMaxLifespan(36000);
+
+        if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
+        else newRealm.setAccessCodeLifespan(60);
+
+        if (rep.getAccessCodeLifespanUserAction() != null)
+            newRealm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
+        else newRealm.setAccessCodeLifespanUserAction(300);
+
+        if (rep.getAccessCodeLifespanLogin() != null)
+            newRealm.setAccessCodeLifespanLogin(rep.getAccessCodeLifespanLogin());
+        else newRealm.setAccessCodeLifespanLogin(1800);
+
+        if (rep.getSslRequired() != null) newRealm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
+        if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
+        if (rep.isRegistrationEmailAsUsername() != null)
+            newRealm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
+        if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
+        if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
+        if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
+        if (rep.isEditUsernameAllowed() != null) newRealm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
+        if (rep.getPrivateKey() == null || rep.getPublicKey() == null) {
+            KeycloakModelUtils.generateRealmKeys(newRealm);
+        } else {
+            newRealm.setPrivateKeyPem(rep.getPrivateKey());
+            newRealm.setPublicKeyPem(rep.getPublicKey());
+        }
+        if (rep.getCertificate() == null) {
+            KeycloakModelUtils.generateRealmCertificate(newRealm);
+        } else {
+            newRealm.setCertificatePem(rep.getCertificate());
+        }
+        if (rep.getCodeSecret() == null) {
+            newRealm.setCodeSecret(KeycloakModelUtils.generateCodeSecret());
+        } else {
+            newRealm.setCodeSecret(rep.getCodeSecret());
+        }
+
+        if (rep.getLoginTheme() != null) newRealm.setLoginTheme(rep.getLoginTheme());
+        if (rep.getAccountTheme() != null) newRealm.setAccountTheme(rep.getAccountTheme());
+        if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAdminTheme());
+        if (rep.getEmailTheme() != null) newRealm.setEmailTheme(rep.getEmailTheme());
+
+        if (rep.getRequiredCredentials() != null) {
+            for (String requiredCred : rep.getRequiredCredentials()) {
+                addRequiredCredential(newRealm, requiredCred);
+            }
+        } else {
+            addRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
+        }
+
+        if (rep.getPasswordPolicy() != null) newRealm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
+
+        importIdentityProviders(rep, newRealm);
+        importIdentityProviderMappers(rep, newRealm);
+
+        if (rep.getClients() != null) {
+            createClients(session, rep, newRealm);
+        }
+
+        if (rep.getRoles() != null) {
+            if (rep.getRoles().getRealm() != null) { // realm roles
+                for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
+                    createRole(newRealm, roleRep);
+                }
+            }
+            if (rep.getRoles().getClient() != null) {
+                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
+                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
+                    if (client == null) {
+                        throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
+                    }
+                    for (RoleRepresentation roleRep : entry.getValue()) {
+                        // Application role may already exists (for example if it is defaultRole)
+                        RoleModel role = roleRep.getId()!=null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName());
+                        role.setDescription(roleRep.getDescription());
+                    }
+                }
+            }
+            // now that all roles are created, re-iterate and set up composites
+            if (rep.getRoles().getRealm() != null) { // realm roles
+                for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
+                    RoleModel role = newRealm.getRole(roleRep.getName());
+                    addComposites(role, roleRep, newRealm);
+                }
+            }
+            if (rep.getRoles().getClient() != null) {
+                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
+                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
+                    if (client == null) {
+                        throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
+                    }
+                    for (RoleRepresentation roleRep : entry.getValue()) {
+                        RoleModel role = client.getRole(roleRep.getName());
+                        addComposites(role, roleRep, newRealm);
+                    }
+                }
+            }
+        }
+
+        // Setup realm default roles
+        if (rep.getDefaultRoles() != null) {
+            for (String roleString : rep.getDefaultRoles()) {
+                newRealm.addDefaultRole(roleString.trim());
+            }
+        }
+        // Setup client default roles
+        if (rep.getClients() != null) {
+            for (ClientRepresentation resourceRep : rep.getClients()) {
+                if (resourceRep.getDefaultRoles() != null) {
+                    ClientModel clientModel = newRealm.getClientByClientId(resourceRep.getClientId());
+                    clientModel.updateDefaultRoles(resourceRep.getDefaultRoles());
+                }
+            }
+        }
+
+        // Now that all possible roles and clients are created, create scope mappings
+
+        Map<String, ClientModel> appMap = newRealm.getClientNameMap();
+
+        if (rep.getClientScopeMappings() != null) {
+
+            for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getClientScopeMappings().entrySet()) {
+                ClientModel app = appMap.get(entry.getKey());
+                if (app == null) {
+                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
+                }
+                createClientScopeMappings(newRealm, app, entry.getValue());
+            }
+        }
+
+        if (rep.getScopeMappings() != null) {
+            for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
+                ClientModel client = newRealm.getClientByClientId(scope.getClient());
+                if (client == null) {
+                    throw new RuntimeException("Unknown client specification in realm scope mappings");
+                }
+                for (String roleString : scope.getRoles()) {
+                    RoleModel role = newRealm.getRole(roleString.trim());
+                    if (role == null) {
+                        role = newRealm.addRole(roleString.trim());
+                    }
+                    client.addScopeMapping(role);
+                }
+
+            }
+        }
+
+        if (rep.getSmtpServer() != null) {
+            newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
+        }
+
+        if (rep.getBrowserSecurityHeaders() != null) {
+            newRealm.setBrowserSecurityHeaders(rep.getBrowserSecurityHeaders());
+        } else {
+            newRealm.setBrowserSecurityHeaders(BrowserSecurityHeaders.defaultHeaders);
+        }
+
+        List<UserFederationProviderModel> providerModels = null;
+        if (rep.getUserFederationProviders() != null) {
+            providerModels = convertFederationProviders(rep.getUserFederationProviders());
+            newRealm.setUserFederationProviders(providerModels);
+        }
+        if (rep.getUserFederationMappers() != null) {
+
+            // Remove builtin mappers for federation providers, which have some mappers already provided in JSON (likely due to previous export)
+            if (rep.getUserFederationProviders() != null) {
+                Set<String> providerNames = new TreeSet<String>();
+                for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
+                    providerNames.add(representation.getFederationProviderDisplayName());
+                }
+                for (String providerName : providerNames) {
+                    for (UserFederationProviderModel providerModel : providerModels) {
+                        if (providerName.equals(providerModel.getDisplayName())) {
+                            Set<UserFederationMapperModel> toDelete = newRealm.getUserFederationMappersByFederationProvider(providerModel.getId());
+                            for (UserFederationMapperModel mapperModel : toDelete) {
+                                newRealm.removeUserFederationMapper(mapperModel);
+                            }
+                        }
+                    }
+                }
+            }
+
+            for (UserFederationMapperRepresentation representation : rep.getUserFederationMappers()) {
+                newRealm.addUserFederationMapper(toModel(newRealm, representation));
+            }
+        }
+
+        // create users and their role mappings and social mappings
+
+        if (rep.getUsers() != null) {
+            for (UserRepresentation userRep : rep.getUsers()) {
+                UserModel user = createUser(session, newRealm, userRep, appMap);
+            }
+        }
+
+        if(rep.isInternationalizationEnabled() != null){
+            newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
+        }
+        if(rep.getSupportedLocales() != null){
+            newRealm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
+        }
+        if(rep.getDefaultLocale() != null){
+            newRealm.setDefaultLocale(rep.getDefaultLocale());
+        }
+
+        importAuthenticationFlows(newRealm, rep);
+    }
+
+    public static void importAuthenticationFlows(RealmModel newRealm, RealmRepresentation rep) {
+        if (rep.getAuthenticationFlows() == null) {
+            // assume this is an old version being imported
+            DefaultAuthenticationFlows.addFlows(newRealm);
+        } else {
+            for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) {
+                AuthenticatorConfigModel model = toModel(configRep);
+                newRealm.addAuthenticatorConfig(model);
+            }
+            for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
+                AuthenticationFlowModel model = toModel(flowRep);
+                model = newRealm.addAuthenticationFlow(model);
+            }
+            for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
+                AuthenticationFlowModel model = newRealm.getFlowByAlias(flowRep.getAlias());
+                for (AuthenticationExecutionRepresentation exeRep : flowRep.getAuthenticationExecutions()) {
+                    AuthenticationExecutionModel execution = toModel(newRealm, exeRep);
+                    execution.setParentFlow(model.getId());
+                    newRealm.addAuthenticatorExecution(execution);
+                }
+            }
+         }
+
+    }
+
+    private static void convertDeprecatedSocialProviders(RealmRepresentation rep) {
+        if (rep.isSocial() != null && rep.isSocial() && rep.getSocialProviders() != null && !rep.getSocialProviders().isEmpty() && rep.getIdentityProviders() == null) {
+            Boolean updateProfileFirstLogin = rep.isUpdateProfileOnInitialSocialLogin() != null && rep.isUpdateProfileOnInitialSocialLogin();
+            if (rep.getSocialProviders() != null) {
+
+                logger.warn("Using deprecated 'social' configuration in JSON representation. It will be removed in future versions");
+                List<IdentityProviderRepresentation> identityProviders = new LinkedList<>();
+                for (String k : rep.getSocialProviders().keySet()) {
+                    if (k.endsWith(".key")) {
+                        String providerId = k.split("\\.")[0];
+                        String key = rep.getSocialProviders().get(k);
+                        String secret = rep.getSocialProviders().get(k.replace(".key", ".secret"));
+
+                        IdentityProviderRepresentation identityProvider = new IdentityProviderRepresentation();
+                        identityProvider.setAlias(providerId);
+                        identityProvider.setProviderId(providerId);
+                        identityProvider.setEnabled(true);
+                        identityProvider.setUpdateProfileFirstLogin(updateProfileFirstLogin);
+
+                        Map<String, String> config = new HashMap<>();
+                        config.put("clientId", key);
+                        config.put("clientSecret", secret);
+                        identityProvider.setConfig(config);
+
+                        identityProviders.add(identityProvider);
+                    }
+                }
+                rep.setIdentityProviders(identityProviders);
+            }
+        }
+    }
+
+    private static void convertDeprecatedSocialProviders(UserRepresentation user) {
+        if (user.getSocialLinks() != null && !user.getSocialLinks().isEmpty() && user.getFederatedIdentities() == null) {
+
+            logger.warnf("Using deprecated 'socialLinks' configuration in JSON representation for user '%s'. It will be removed in future versions", user.getUsername());
+            List<FederatedIdentityRepresentation> federatedIdentities = new LinkedList<>();
+            for (SocialLinkRepresentation social : user.getSocialLinks()) {
+                FederatedIdentityRepresentation federatedIdentity = new FederatedIdentityRepresentation();
+                federatedIdentity.setIdentityProvider(social.getSocialProvider());
+                federatedIdentity.setUserId(social.getSocialUserId());
+                federatedIdentity.setUserName(social.getSocialUsername());
+                federatedIdentities.add(federatedIdentity);
+            }
+            user.setFederatedIdentities(federatedIdentities);
+        }
+
+        user.setSocialLinks(null);
+    }
+
+    private static void convertDeprecatedApplications(KeycloakSession session, RealmRepresentation realm) {
+        if (realm.getApplications() != null || realm.getOauthClients() != null) {
+            if (realm.getClients() == null) {
+                realm.setClients(new LinkedList<ClientRepresentation>());
+            }
+
+            List<ApplicationRepresentation> clients = new LinkedList<>();
+            if (realm.getApplications() != null) {
+                clients.addAll(realm.getApplications());
+            }
+            if (realm.getOauthClients() != null) {
+                clients.addAll(realm.getOauthClients());
+            }
+
+            for (ApplicationRepresentation app : clients) {
+                app.setClientId(app.getName());
+                app.setName(null);
+
+                if (app instanceof OAuthClientRepresentation) {
+                    app.setConsentRequired(true);
+                    app.setFullScopeAllowed(false);
+                }
+
+                if (app.getProtocolMappers() == null && app.getClaims() != null) {
+                    long mask = getClaimsMask(app.getClaims());
+                    List<ProtocolMapperRepresentation> convertedProtocolMappers = session.getProvider(MigrationProvider.class).getMappersForClaimMask(mask);
+                    app.setProtocolMappers(convertedProtocolMappers);
+                    app.setClaims(null);
+                }
+
+                realm.getClients().add(app);
+            }
+        }
+
+        if (realm.getApplicationScopeMappings() != null && realm.getClientScopeMappings() == null) {
+            realm.setClientScopeMappings(realm.getApplicationScopeMappings());
+        }
+
+        if (realm.getRoles() != null && realm.getRoles().getApplication() != null && realm.getRoles().getClient() == null) {
+            realm.getRoles().setClient(realm.getRoles().getApplication());
+        }
+
+        if (realm.getUsers() != null) {
+            for (UserRepresentation user : realm.getUsers()) {
+                if (user.getApplicationRoles() != null && user.getClientRoles() == null) {
+                    user.setClientRoles(user.getApplicationRoles());
+                }
+            }
+        }
+
+        if (realm.getRoles() != null && realm.getRoles().getRealm() != null) {
+            for (RoleRepresentation role : realm.getRoles().getRealm()) {
+                if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
+                    role.getComposites().setClient(role.getComposites().getApplication());
+                }
+            }
+        }
+
+        if (realm.getRoles() != null && realm.getRoles().getClient() != null) {
+            for (Map.Entry<String, List<RoleRepresentation>> clientRoles : realm.getRoles().getClient().entrySet()) {
+                for (RoleRepresentation role : clientRoles.getValue()) {
+                    if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
+                        role.getComposites().setClient(role.getComposites().getApplication());
+                    }
+                }
+            }
+        }
+    }
+
+    public static void updateRealm(RealmRepresentation rep, RealmModel realm) {
+        if (rep.getRealm() != null) {
+            realm.setName(rep.getRealm());
+        }
+        if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
+        if (rep.isBruteForceProtected() != null) realm.setBruteForceProtected(rep.isBruteForceProtected());
+        if (rep.getMaxFailureWaitSeconds() != null) realm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
+        if (rep.getMinimumQuickLoginWaitSeconds() != null) realm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
+        if (rep.getWaitIncrementSeconds() != null) realm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
+        if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
+        if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
+        if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
+        if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
+        if (rep.isRegistrationEmailAsUsername() != null) realm.setRegistrationEmailAsUsername(rep.isRegistrationEmailAsUsername());
+        if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
+        if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
+        if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
+        if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
+        if (rep.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
+        if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
+        if (rep.getAccessCodeLifespanUserAction() != null) realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
+        if (rep.getAccessCodeLifespanLogin() != null) realm.setAccessCodeLifespanLogin(rep.getAccessCodeLifespanLogin());
+        if (rep.getNotBefore() != null) realm.setNotBefore(rep.getNotBefore());
+        if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
+        if (rep.getSsoSessionIdleTimeout() != null) realm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
+        if (rep.getSsoSessionMaxLifespan() != null) realm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
+        if (rep.getRequiredCredentials() != null) {
+            realm.updateRequiredCredentials(rep.getRequiredCredentials());
+        }
+        if (rep.getLoginTheme() != null) realm.setLoginTheme(rep.getLoginTheme());
+        if (rep.getAccountTheme() != null) realm.setAccountTheme(rep.getAccountTheme());
+        if (rep.getAdminTheme() != null) realm.setAdminTheme(rep.getAdminTheme());
+        if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
+        
+        if (rep.isEventsEnabled() != null) realm.setEventsEnabled(rep.isEventsEnabled());
+        if (rep.getEventsExpiration() != null) realm.setEventsExpiration(rep.getEventsExpiration());
+        if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
+        if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<>(rep.getEnabledEventTypes()));
+        
+        if (rep.isAdminEventsEnabled() != null) realm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
+        if (rep.isAdminEventsDetailsEnabled() != null) realm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
+        
+
+        if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
+
+        if (rep.getDefaultRoles() != null) {
+            realm.updateDefaultRoles(rep.getDefaultRoles().toArray(new String[rep.getDefaultRoles().size()]));
+        }
+
+        if (rep.getSmtpServer() != null) {
+            realm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
+        }
+
+        if (rep.getBrowserSecurityHeaders() != null) {
+            realm.setBrowserSecurityHeaders(rep.getBrowserSecurityHeaders());
+        }
+
+        if (rep.getUserFederationProviders() != null) {
+            List<UserFederationProviderModel> providerModels = convertFederationProviders(rep.getUserFederationProviders());
+            realm.setUserFederationProviders(providerModels);
+        }
+
+        if ("GENERATE".equals(rep.getPublicKey())) {
+            KeycloakModelUtils.generateRealmKeys(realm);
+        }
+
+        if(rep.isInternationalizationEnabled() != null){
+            realm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
+        }
+        if(rep.getSupportedLocales() != null){
+            realm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
+        }
+        if(rep.getDefaultLocale() != null){
+            realm.setDefaultLocale(rep.getDefaultLocale());
+        }
+    }
+
+    // Basic realm stuff
+
+    public static void addRequiredCredential(RealmModel newRealm, String requiredCred) {
+        newRealm.addRequiredCredential(requiredCred);
+    }
+
+
+    private static List<UserFederationProviderModel> convertFederationProviders(List<UserFederationProviderRepresentation> providers) {
+        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
+
+        for (UserFederationProviderRepresentation representation : providers) {
+            UserFederationProviderModel model = new UserFederationProviderModel(representation.getId(), representation.getProviderName(),
+                    representation.getConfig(), representation.getPriority(), representation.getDisplayName(),
+                    representation.getFullSyncPeriod(), representation.getChangedSyncPeriod(), representation.getLastSync());
+            result.add(model);
+        }
+        return result;
+    }
+
+    public static UserFederationMapperModel toModel(RealmModel realm, UserFederationMapperRepresentation rep) {
+        UserFederationMapperModel model = new UserFederationMapperModel();
+        model.setId(rep.getId());
+        model.setName(rep.getName());
+        model.setFederationMapperType(rep.getFederationMapperType());
+        model.setConfig(rep.getConfig());
+
+        UserFederationProviderModel fedProvider = KeycloakModelUtils.findUserFederationProviderByDisplayName(rep.getFederationProviderDisplayName(), realm);
+        if (fedProvider == null) {
+            throw new ModelException("Couldn't find federation provider with display name [" + rep.getFederationProviderDisplayName() + "] referenced from mapper ["
+                    + rep.getName());
+        }
+        model.setFederationProviderId(fedProvider.getId());
+
+        return model;
+    }
+
+    // Roles
+
+    public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
+        RoleModel role = roleRep.getId()!=null ? newRealm.addRole(roleRep.getId(), roleRep.getName()) : newRealm.addRole(roleRep.getName());
+        if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
+    }
+
+    private static void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
+        if (roleRep.getComposites() == null) return;
+        if (roleRep.getComposites().getRealm() != null) {
+            for (String roleStr : roleRep.getComposites().getRealm()) {
+                RoleModel realmRole = realm.getRole(roleStr);
+                if (realmRole == null) throw new RuntimeException("Unable to find composite realm role: " + roleStr);
+                role.addCompositeRole(realmRole);
+            }
+        }
+        if (roleRep.getComposites().getClient() != null) {
+            for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getClient().entrySet()) {
+                ClientModel client = realm.getClientByClientId(entry.getKey());
+                if (client == null) {
+                    throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName());
+                }
+                for (String roleStr : entry.getValue()) {
+                    RoleModel clientRole = client.getRole(roleStr);
+                    if (clientRole == null) throw new RuntimeException("Unable to find composite client role: " + roleStr);
+                    role.addCompositeRole(clientRole);
+                }
+            }
+
+        }
+
+    }
+
+    // CLIENTS
+
+    private static Map<String, ClientModel> createClients(KeycloakSession session, RealmRepresentation rep, RealmModel realm) {
+        Map<String, ClientModel> appMap = new HashMap<String, ClientModel>();
+        for (ClientRepresentation resourceRep : rep.getClients()) {
+            ClientModel app = createClient(session, realm, resourceRep, false);
+            appMap.put(app.getClientId(), app);
+        }
+        return appMap;
+    }
+
+    /**
+     * Does not create scope or role mappings!
+     *
+     * @param realm
+     * @param resourceRep
+     * @return
+     */
+    public static ClientModel createClient(KeycloakSession session, RealmModel realm, ClientRepresentation resourceRep, boolean addDefaultRoles) {
+        logger.debug("Create client: {0}" + resourceRep.getClientId());
+
+        ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId());
+        if (resourceRep.getName() != null) client.setName(resourceRep.getName());
+        if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled());
+        client.setManagementUrl(resourceRep.getAdminUrl());
+        if (resourceRep.isSurrogateAuthRequired() != null)
+            client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
+        if (resourceRep.getBaseUrl() != null) client.setBaseUrl(resourceRep.getBaseUrl());
+        if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
+        if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
+        if (resourceRep.isDirectGrantsOnly() != null) client.setDirectGrantsOnly(resourceRep.isDirectGrantsOnly());
+        if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
+        if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
+        if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol());
+        if (resourceRep.isFullScopeAllowed() != null) {
+            client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
+        } else {
+            client.setFullScopeAllowed(!client.isConsentRequired());
+        }
+        if (resourceRep.getNodeReRegistrationTimeout() != null) {
+            client.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout());
+        } else {
+            client.setNodeReRegistrationTimeout(-1);
+        }
+        client.updateClient();
+
+        if (resourceRep.getNotBefore() != null) {
+            client.setNotBefore(resourceRep.getNotBefore());
+        }
+
+        client.setSecret(resourceRep.getSecret());
+        if (client.getSecret() == null) {
+            KeycloakModelUtils.generateSecret(client);
+        }
+
+        if (resourceRep.getAttributes() != null) {
+            for (Map.Entry<String, String> entry : resourceRep.getAttributes().entrySet()) {
+                client.setAttribute(entry.getKey(), entry.getValue());
+            }
+        }
+
+
+        if (resourceRep.getRedirectUris() != null) {
+            for (String redirectUri : resourceRep.getRedirectUris()) {
+                client.addRedirectUri(redirectUri);
+            }
+        }
+        if (resourceRep.getWebOrigins() != null) {
+            for (String webOrigin : resourceRep.getWebOrigins()) {
+                logger.debugv("Client: {0} webOrigin: {1}", resourceRep.getClientId(), webOrigin);
+                client.addWebOrigin(webOrigin);
+            }
+        } else {
+            // add origins from redirect uris
+            if (resourceRep.getRedirectUris() != null) {
+                Set<String> origins = new HashSet<String>();
+                for (String redirectUri : resourceRep.getRedirectUris()) {
+                    logger.debugv("add redirect-uri to origin: {0}", redirectUri);
+                    if (redirectUri.startsWith("http")) {
+                        String origin = UriUtils.getOrigin(redirectUri);
+                        logger.debugv("adding default client origin: {0}" , origin);
+                        origins.add(origin);
+                    }
+                }
+                if (origins.size() > 0) {
+                    client.setWebOrigins(origins);
+                }
+            }
+        }
+
+        if (resourceRep.getRegisteredNodes() != null) {
+            for (Map.Entry<String, Integer> entry : resourceRep.getRegisteredNodes().entrySet()) {
+                client.registerNode(entry.getKey(), entry.getValue());
+            }
+        }
+
+        if (addDefaultRoles && resourceRep.getDefaultRoles() != null) {
+            client.updateDefaultRoles(resourceRep.getDefaultRoles());
+        }
+
+        if (resourceRep.getProtocolMappers() != null) {
+            // first, remove all default/built in mappers
+            Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
+            for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper);
+
+            for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) {
+                client.addProtocolMapper(toModel(mapper));
+            }
+        }
+
+        return client;
+    }
+
+    public static void updateClient(ClientRepresentation rep, ClientModel resource) {
+        if (rep.getClientId() != null) resource.setClientId(rep.getClientId());
+        if (rep.getName() != null) resource.setName(rep.getName());
+        if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
+        if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
+        if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
+        if (rep.isDirectGrantsOnly() != null) resource.setDirectGrantsOnly(rep.isDirectGrantsOnly());
+        if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
+        if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
+        if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
+        if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
+        if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
+        if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
+        if (rep.getNodeReRegistrationTimeout() != null) resource.setNodeReRegistrationTimeout(rep.getNodeReRegistrationTimeout());
+        resource.updateClient();
+
+        if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
+        if (rep.getAttributes() != null) {
+            for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
+                resource.setAttribute(entry.getKey(), entry.getValue());
+            }
+        }
+
+
+        if (rep.getNotBefore() != null) {
+            resource.setNotBefore(rep.getNotBefore());
+        }
+        if (rep.getDefaultRoles() != null) {
+            resource.updateDefaultRoles(rep.getDefaultRoles());
+        }
+
+        List<String> redirectUris = rep.getRedirectUris();
+        if (redirectUris != null) {
+            resource.setRedirectUris(new HashSet<String>(redirectUris));
+        }
+
+        List<String> webOrigins = rep.getWebOrigins();
+        if (webOrigins != null) {
+            resource.setWebOrigins(new HashSet<String>(webOrigins));
+        }
+
+        if (rep.getRegisteredNodes() != null) {
+            for (Map.Entry<String, Integer> entry : rep.getRegisteredNodes().entrySet()) {
+                resource.registerNode(entry.getKey(), entry.getValue());
+            }
+        }
+
+    }
+
+    public static long getClaimsMask(ClaimRepresentation rep) {
+        long mask = ClaimMask.ALL;
+
+        if (rep.getAddress()) {
+            mask |= ClaimMask.ADDRESS;
+        } else {
+            mask &= ~ClaimMask.ADDRESS;
+        }
+        if (rep.getEmail()) {
+            mask |= ClaimMask.EMAIL;
+        } else {
+            mask &= ~ClaimMask.EMAIL;
+        }
+        if (rep.getGender()) {
+            mask |= ClaimMask.GENDER;
+        } else {
+            mask &= ~ClaimMask.GENDER;
+        }
+        if (rep.getLocale()) {
+            mask |= ClaimMask.LOCALE;
+        } else {
+            mask &= ~ClaimMask.LOCALE;
+        }
+        if (rep.getName()) {
+            mask |= ClaimMask.NAME;
+        } else {
+            mask &= ~ClaimMask.NAME;
+        }
+        if (rep.getPhone()) {
+            mask |= ClaimMask.PHONE;
+        } else {
+            mask &= ~ClaimMask.PHONE;
+        }
+        if (rep.getPicture()) {
+            mask |= ClaimMask.PICTURE;
+        } else {
+            mask &= ~ClaimMask.PICTURE;
+        }
+        if (rep.getProfile()) {
+            mask |= ClaimMask.PROFILE;
+        } else {
+            mask &= ~ClaimMask.PROFILE;
+        }
+        if (rep.getUsername()) {
+            mask |= ClaimMask.USERNAME;
+        } else {
+            mask &= ~ClaimMask.USERNAME;
+        }
+        if (rep.getWebsite()) {
+            mask |= ClaimMask.WEBSITE;
+        } else {
+            mask &= ~ClaimMask.WEBSITE;
+        }
+        return mask;
+    }
+
+    // Scope mappings
+
+    public static void createClientScopeMappings(RealmModel realm, ClientModel clientModel, List<ScopeMappingRepresentation> mappings) {
+        for (ScopeMappingRepresentation mapping : mappings) {
+            ClientModel client = realm.getClientByClientId(mapping.getClient());
+            if (client == null) {
+                throw new RuntimeException("Unknown client specified in client scope mappings");
+            }
+            for (String roleString : mapping.getRoles()) {
+                RoleModel role = clientModel.getRole(roleString.trim());
+                if (role == null) {
+                    role = clientModel.addRole(roleString.trim());
+                }
+                client.addScopeMapping(role);
+            }
+        }
+    }
+
+    // Users
+
+    public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map<String, ClientModel> clientMap) {
+        convertDeprecatedSocialProviders(userRep);
+
+        // Import users just to user storage. Don't federate
+        UserModel user = session.userStorage().addUser(newRealm, userRep.getId(), userRep.getUsername(), false, false);
+        user.setEnabled(userRep.isEnabled());
+        user.setCreatedTimestamp(userRep.getCreatedTimestamp());
+        user.setEmail(userRep.getEmail());
+        user.setEmailVerified(userRep.isEmailVerified());
+        user.setFirstName(userRep.getFirstName());
+        user.setLastName(userRep.getLastName());
+        user.setFederationLink(userRep.getFederationLink());
+        user.setTotp(userRep.isTotp());
+        if (userRep.getAttributes() != null) {
+            for (Map.Entry<String, Object> entry : userRep.getAttributes().entrySet()) {
+                Object value = entry.getValue();
+
+                if (value instanceof Collection) {
+                    Collection<String> colVal = (Collection<String>) value;
+                    user.setAttribute(entry.getKey(), new ArrayList<>(colVal));
+                } else if (value instanceof String) {
+                    // TODO: This is here just for backwards compatibility with KC 1.3 and earlier
+                    String stringVal = (String) value;
+                    user.setSingleAttribute(entry.getKey(), stringVal);
+                }
+            }
+        }
+        if (userRep.getRequiredActions() != null) {
+            for (String requiredAction : userRep.getRequiredActions()) {
+                user.addRequiredAction(UserModel.RequiredAction.valueOf(requiredAction));
+            }
+        }
+        if (userRep.getCredentials() != null) {
+            for (CredentialRepresentation cred : userRep.getCredentials()) {
+                updateCredential(user, cred);
+            }
+        }
+        if (userRep.getFederatedIdentities() != null) {
+            for (FederatedIdentityRepresentation identity : userRep.getFederatedIdentities()) {
+                FederatedIdentityModel mappingModel = new FederatedIdentityModel(identity.getIdentityProvider(), identity.getUserId(), identity.getUserName());
+                session.users().addFederatedIdentity(newRealm, user, mappingModel);
+            }
+        }
+        if (userRep.getRealmRoles() != null) {
+            for (String roleString : userRep.getRealmRoles()) {
+                RoleModel role = newRealm.getRole(roleString.trim());
+                if (role == null) {
+                    role = newRealm.addRole(roleString.trim());
+                }
+                user.grantRole(role);
+            }
+        }
+        if (userRep.getClientRoles() != null) {
+            for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
+                ClientModel client = clientMap.get(entry.getKey());
+                if (client == null) {
+                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
+                }
+                createClientRoleMappings(client, user, entry.getValue());
+            }
+        }
+        if (userRep.getClientConsents() != null) {
+            for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
+                UserConsentModel consentModel = toModel(newRealm, consentRep);
+                user.addConsent(consentModel);
+            }
+        }
+        return user;
+    }
+
+    // Detect if it is "plain-text" or "hashed" representation and update model according to it
+    private static void updateCredential(UserModel user, CredentialRepresentation cred) {
+        if (cred.getValue() != null) {
+            UserCredentialModel plainTextCred = convertCredential(cred);
+            user.updateCredential(plainTextCred);
+        } else {
+            UserCredentialValueModel hashedCred = new UserCredentialValueModel();
+            hashedCred.setType(cred.getType());
+            hashedCred.setDevice(cred.getDevice());
+            hashedCred.setHashIterations(cred.getHashIterations());
+            try {
+                if (cred.getSalt() != null) hashedCred.setSalt(Base64.decode(cred.getSalt()));
+            } catch (IOException ioe) {
+                throw new RuntimeException(ioe);
+            }
+            hashedCred.setValue(cred.getHashedSaltedValue());
+            user.updateCredentialDirectly(hashedCred);
+        }
+    }
+
+    public static UserCredentialModel convertCredential(CredentialRepresentation cred) {
+        UserCredentialModel credential = new UserCredentialModel();
+        credential.setType(cred.getType());
+        credential.setValue(cred.getValue());
+        return credential;
+    }
+
+    // Role mappings
+
+    public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List<String> roleNames) {
+        if (user == null) {
+            throw new RuntimeException("User not found");
+        }
+
+        for (String roleName : roleNames) {
+            RoleModel role = clientModel.getRole(roleName.trim());
+            if (role == null) {
+                role = clientModel.addRole(roleName.trim());
+            }
+            user.grantRole(role);
+
+        }
+    }
+
+    private static void importIdentityProviders(RealmRepresentation rep, RealmModel newRealm) {
+        if (rep.getIdentityProviders() != null) {
+            for (IdentityProviderRepresentation representation : rep.getIdentityProviders()) {
+                newRealm.addIdentityProvider(toModel(representation));
+            }
+        }
+    }
+    private static void importIdentityProviderMappers(RealmRepresentation rep, RealmModel newRealm) {
+        if (rep.getIdentityProviderMappers() != null) {
+            for (IdentityProviderMapperRepresentation representation : rep.getIdentityProviderMappers()) {
+                newRealm.addIdentityProviderMapper(toModel(representation));
+            }
+        }
+    }
+   public static IdentityProviderModel toModel(IdentityProviderRepresentation representation) {
+        IdentityProviderModel identityProviderModel = new IdentityProviderModel();
+
+        identityProviderModel.setInternalId(representation.getInternalId());
+        identityProviderModel.setAlias(representation.getAlias());
+        identityProviderModel.setProviderId(representation.getProviderId());
+        identityProviderModel.setEnabled(representation.isEnabled());
+        identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
+        identityProviderModel.setTrustEmail(representation.isTrustEmail());
+        identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
+        identityProviderModel.setStoreToken(representation.isStoreToken());
+        identityProviderModel.setAddReadTokenRoleOnCreate(representation.isAddReadTokenRoleOnCreate());
+        identityProviderModel.setConfig(representation.getConfig());
+
+        return identityProviderModel;
+    }
+
+    public static ProtocolMapperModel toModel(ProtocolMapperRepresentation rep) {
+        ProtocolMapperModel model = new ProtocolMapperModel();
+        model.setId(rep.getId());
+        model.setName(rep.getName());
+        model.setConsentRequired(rep.isConsentRequired());
+        model.setConsentText(rep.getConsentText());
+        model.setProtocol(rep.getProtocol());
+        model.setProtocolMapper(rep.getProtocolMapper());
+        model.setConfig(rep.getConfig());
+        return model;
+    }
+
+    public static IdentityProviderMapperModel toModel(IdentityProviderMapperRepresentation rep) {
+        IdentityProviderMapperModel model = new IdentityProviderMapperModel();
+        model.setId(rep.getId());
+        model.setName(rep.getName());
+        model.setIdentityProviderAlias(rep.getIdentityProviderAlias());
+        model.setIdentityProviderMapper(rep.getIdentityProviderMapper());
+        model.setConfig(rep.getConfig());
+        return model;
+    }
+
+    public static UserConsentModel toModel(RealmModel newRealm, UserConsentRepresentation consentRep) {
+        ClientModel client = newRealm.getClientByClientId(consentRep.getClientId());
+        if (client == null) {
+            throw new RuntimeException("Unable to find client consent mappings for client: " + consentRep.getClientId());
+        }
+
+        UserConsentModel consentModel = new UserConsentModel(client);
+
+        if (consentRep.getGrantedRealmRoles() != null) {
+            for (String roleName : consentRep.getGrantedRealmRoles()) {
+                RoleModel role = newRealm.getRole(roleName);
+                if (role == null) {
+                    throw new RuntimeException("Unable to find realm role referenced in consent mappings of user. Role name: " + roleName);
+                }
+                consentModel.addGrantedRole(role);
+            }
+        }
+        if (consentRep.getGrantedClientRoles() != null) {
+            for (Map.Entry<String, List<String>> entry : consentRep.getGrantedClientRoles().entrySet()) {
+                String clientId2 = entry.getKey();
+                ClientModel client2 = newRealm.getClientByClientId(clientId2);
+                if (client2 == null) {
+                    throw new RuntimeException("Unable to find client referenced in consent mappings. Client ID: " + clientId2);
+                }
+                for (String clientRoleName : entry.getValue()) {
+                    RoleModel clientRole = client2.getRole(clientRoleName);
+                    if (clientRole == null) {
+                        throw new RuntimeException("Unable to find client role referenced in consent mappings of user. Role name: " + clientRole + ", Client: " + clientId2);
+                    }
+                    consentModel.addGrantedRole(clientRole);
+                }
+            }
+        }
+        if (consentRep.getGrantedProtocolMappers() != null) {
+            for (Map.Entry<String, List<String>> protocolEntry : consentRep.getGrantedProtocolMappers().entrySet()) {
+                String protocol = protocolEntry.getKey();
+                for (String protocolMapperName : protocolEntry.getValue()) {
+                    ProtocolMapperModel protocolMapper = client.getProtocolMapperByName(protocol, protocolMapperName);
+                    if (protocolMapper == null) {
+                        throw new RuntimeException("Unable to find protocol mapper for protocol " + protocol + ", mapper name " + protocolMapperName);
+                    }
+
+                    consentModel.addGrantedProtocolMapper(protocolMapper);
+                }
+            }
+        }
+        return consentModel;
+    }
+
+    public static AuthenticationFlowModel toModel(AuthenticationFlowRepresentation rep) {
+        AuthenticationFlowModel model = new AuthenticationFlowModel();
+        model.setBuiltIn(rep.isBuiltIn());
+        model.setTopLevel(rep.isTopLevel());
+        model.setProviderId(rep.getProviderId());
+        model.setAlias(rep.getAlias());
+        model.setDescription(rep.getDescription());
+        return model;
+
+    }
+
+    public static AuthenticationExecutionModel toModel(RealmModel realm, AuthenticationExecutionRepresentation rep) {
+        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
+        if (rep.getAuthenticatorConfig() != null) {
+            AuthenticatorConfigModel config = realm.getAuthenticatorConfigByAlias(rep.getAuthenticatorConfig());
+            model.setAuthenticatorConfig(config.getId());
+        }
+        model.setAuthenticator(rep.getAuthenticator());
+        model.setAutheticatorFlow(rep.isAutheticatorFlow());
+        if (rep.getFlowAlias() != null) {
+            AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
+            model.setFlowId(flow.getId());
+        }
+        model.setPriority(rep.getPriority());
+        model.setUserSetupAllowed(rep.isUserSetupAllowed());
+        model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
+        return model;
+    }
+
+    public static AuthenticatorConfigModel toModel(AuthenticatorConfigRepresentation rep) {
+        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
+        model.setAlias(rep.getAlias());
+        model.setConfig(rep.getConfig());
+        return model;
+    }
+
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java b/model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java
index 3a8ed8d..bc770ca 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java
@@ -1,60 +1,60 @@
-package org.keycloak.models.utils;
-
-import net.iharder.Base64;
-
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-
-/**
- * <p>
- * Password that uses SHA to encode passwords. You can always change the SHA strength by specifying a valid
- * integer when creating a new instance.
- * </p>
- * <p>Passwords are returned with a Base64 encoding.</p>
- *
- * @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
- *
- */
-public class SHAPasswordEncoder {
-
-    private int strength;
-
-    public SHAPasswordEncoder(int strength) {
-        this.strength = strength;
-    }
-
-    public String encode(String rawPassword) {
-        MessageDigest messageDigest = getMessageDigest();
-
-        String encodedPassword = null;
-
-        try {
-            byte[] digest = messageDigest.digest(rawPassword.getBytes("UTF-8"));
-            encodedPassword = Base64.encodeBytes(digest);
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException("Credential could not be encoded");
-        }
-
-        return encodedPassword;
-    }
-
-    public boolean verify(String rawPassword, String encodedPassword) {
-        return encode(rawPassword).equals(encodedPassword);
-    }
-
-    protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
-        String algorithm = "SHA-" + this.strength;
-
-        try {
-            return MessageDigest.getInstance(algorithm);
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("invalid credential encoding algorithm");
-        }
-    }
-
-    public int getStrength() {
-        return this.strength;
-    }
-}
+package org.keycloak.models.utils;
+
+import net.iharder.Base64;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+/**
+ * <p>
+ * Password that uses SHA to encode passwords. You can always change the SHA strength by specifying a valid
+ * integer when creating a new instance.
+ * </p>
+ * <p>Passwords are returned with a Base64 encoding.</p>
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
+ *
+ */
+public class SHAPasswordEncoder {
+
+    private int strength;
+
+    public SHAPasswordEncoder(int strength) {
+        this.strength = strength;
+    }
+
+    public String encode(String rawPassword) {
+        MessageDigest messageDigest = getMessageDigest();
+
+        String encodedPassword = null;
+
+        try {
+            byte[] digest = messageDigest.digest(rawPassword.getBytes("UTF-8"));
+            encodedPassword = Base64.encodeBytes(digest);
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException("Credential could not be encoded");
+        }
+
+        return encodedPassword;
+    }
+
+    public boolean verify(String rawPassword, String encodedPassword) {
+        return encode(rawPassword).equals(encodedPassword);
+    }
+
+    protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
+        String algorithm = "SHA-" + this.strength;
+
+        try {
+            return MessageDigest.getInstance(algorithm);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("invalid credential encoding algorithm");
+        }
+    }
+
+    public int getStrength() {
+        return this.strength;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java b/model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java
index d27718b..5f21d38 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java
@@ -1,216 +1,216 @@
-package org.keycloak.models.utils;
-
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import java.math.BigInteger;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
-/**
- * TOTP: Time-based One-time Password Algorithm Based on http://tools.ietf.org/html/draft-mraihi-totp-timebased-06
- *
- * @author anil saldhana
- * @since Sep 20, 2010
- */
-public class TimeBasedOTP {
-
-    public static final String HMAC_SHA1 = "HmacSHA1";
-    public static final String HMAC_SHA256 = "HmacSHA256";
-    public static final String HMAC_SHA512 = "HmacSHA512";
-
-    public static final String DEFAULT_ALGORITHM = HMAC_SHA1;
-    public static final int DEFAULT_NUMBER_DIGITS = 6;
-    public static final int DEFAULT_INTERVAL_SECONDS = 30;
-    public static final int DEFAULT_DELAY_WINDOW = 1;
-
-    // 0 1 2 3 4 5 6 7 8
-    private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
-
-    private Clock clock;
-    private final String algorithm;
-    private final int numberDigits;
-    private final int delayWindow;
-
-    public TimeBasedOTP() {
-        this(DEFAULT_ALGORITHM, DEFAULT_NUMBER_DIGITS, DEFAULT_INTERVAL_SECONDS, DEFAULT_DELAY_WINDOW);
-    }
-
-    /**
-     * @param algorithm the encryption algorithm
-     * @param numberDigits the number of digits for tokens
-     * @param timeIntervalInSeconds the number of seconds a token is valid
-     * @param delayWindow the number of previous intervals that should be used to validate tokens.
-     */
-    public TimeBasedOTP(String algorithm, int numberDigits, int timeIntervalInSeconds, int delayWindow) {
-        this.algorithm = algorithm;
-        this.numberDigits = numberDigits;
-        this.clock = new Clock(timeIntervalInSeconds);
-        this.delayWindow = delayWindow;
-    }
-
-    /**
-     * <p>Generates a token.</p>
-     *
-     * @param secretKey the secret key to derive the token from.
-     */
-    public String generate(String secretKey) {
-        long T = this.clock.getCurrentInterval();
-
-        String steps = Long.toHexString(T).toUpperCase();
-
-        // Just get a 16 digit string
-        while (steps.length() < 16)
-            steps = "0" + steps;
-
-        return generateTOTP(secretKey, steps, this.numberDigits, this.algorithm);
-    }
-
-    /**
-     * This method generates an TOTP value for the given set of parameters.
-     *
-     * @param key          the shared secret, HEX encoded
-     * @param time         a value that reflects a time
-     * @param returnDigits number of digits to return
-     * @param crypto       the crypto function to use
-     * @return A numeric String in base 10 that includes {@link truncationDigits} digits
-     * @throws java.security.GeneralSecurityException
-     *
-     */
-    public String generateTOTP(String key, String time, int returnDigits, String crypto) {
-        String result = null;
-        byte[] hash;
-
-        // Using the counter
-        // First 8 bytes are for the movingFactor
-        // Complaint with base RFC 4226 (HOTP)
-        while (time.length() < 16)
-            time = "0" + time;
-
-        // Get the HEX in a Byte[]
-        byte[] msg = hexStr2Bytes(time);
-
-        // Adding one byte to get the right conversion
-        // byte[] k = hexStr2Bytes(key);
-        byte[] k = key.getBytes();
-
-        hash = hmac_sha1(crypto, k, msg);
-
-        // put selected bytes into result int
-        int offset = hash[hash.length - 1] & 0xf;
-
-        int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8)
-                | (hash[offset + 3] & 0xff);
-
-        int otp = binary % DIGITS_POWER[returnDigits];
-
-        result = Integer.toString(otp);
-
-        while (result.length() < returnDigits) {
-            result = "0" + result;
-        }
-        return result;
-    }
-
-    /**
-     * <p>Validates a token using a secret key.</p>
-     *
-     * @param token  OTP string to validate
-     * @param secret Shared secret
-     * @return
-     */
-    public boolean validate(String token, byte[] secret) {
-        long currentInterval = this.clock.getCurrentInterval();
-
-        for (int i = this.delayWindow; i >= 0; --i) {
-            String steps = Long.toHexString(currentInterval - i).toUpperCase();
-
-            // Just get a 16 digit string
-            while (steps.length() < 16)
-                steps = "0" + steps;
-
-            String candidate = generateTOTP(new String(secret), steps, this.numberDigits, this.algorithm);
-
-            if (candidate.equals(token)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public void setCalendar(Calendar calendar) {
-        this.clock.setCalendar(calendar);
-    }
-
-    /**
-     * This method uses the JCE to provide the crypto algorithm. HMAC computes a Hashed Message Authentication Code with the
-     * crypto hash algorithm as a parameter.
-     *
-     * @param crypto   the crypto algorithm (HmacSHA1, HmacSHA256, HmacSHA512)
-     * @param keyBytes the bytes to use for the HMAC key
-     * @param text     the message or text to be authenticated.
-     * @throws java.security.NoSuchAlgorithmException
-     *
-     * @throws java.security.InvalidKeyException
-     *
-     */
-    private byte[] hmac_sha1(String crypto, byte[] keyBytes, byte[] text) {
-        byte[] value;
-
-        try {
-            Mac hmac = Mac.getInstance(crypto);
-            SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
-
-            hmac.init(macKey);
-
-            value = hmac.doFinal(text);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-
-        return value;
-    }
-
-    /**
-     * This method converts HEX string to Byte[]
-     *
-     * @param hex the HEX string
-     * @return A byte array
-     */
-    private byte[] hexStr2Bytes(String hex) {
-        // Adding one byte to get the right conversion
-        // values starting with "0" can be converted
-        byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
-
-        // Copy all the REAL bytes, not the "first"
-        byte[] ret = new byte[bArray.length - 1];
-        for (int i = 0; i < ret.length; i++)
-            ret[i] = bArray[i + 1];
-        return ret;
-    }
-
-    private class Clock {
-
-        private final int interval;
-        private Calendar calendar;
-
-        public Clock(int interval) {
-            this.interval = interval;
-        }
-
-        public long getCurrentInterval() {
-            Calendar currentCalendar = this.calendar;
-
-            if (currentCalendar == null) {
-                currentCalendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
-            }
-
-            return (currentCalendar.getTimeInMillis() / 1000) / this.interval;
-        }
-
-        public void setCalendar(Calendar calendar) {
-            this.calendar = calendar;
-        }
-    }
+package org.keycloak.models.utils;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * TOTP: Time-based One-time Password Algorithm Based on http://tools.ietf.org/html/draft-mraihi-totp-timebased-06
+ *
+ * @author anil saldhana
+ * @since Sep 20, 2010
+ */
+public class TimeBasedOTP {
+
+    public static final String HMAC_SHA1 = "HmacSHA1";
+    public static final String HMAC_SHA256 = "HmacSHA256";
+    public static final String HMAC_SHA512 = "HmacSHA512";
+
+    public static final String DEFAULT_ALGORITHM = HMAC_SHA1;
+    public static final int DEFAULT_NUMBER_DIGITS = 6;
+    public static final int DEFAULT_INTERVAL_SECONDS = 30;
+    public static final int DEFAULT_DELAY_WINDOW = 1;
+
+    // 0 1 2 3 4 5 6 7 8
+    private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
+
+    private Clock clock;
+    private final String algorithm;
+    private final int numberDigits;
+    private final int delayWindow;
+
+    public TimeBasedOTP() {
+        this(DEFAULT_ALGORITHM, DEFAULT_NUMBER_DIGITS, DEFAULT_INTERVAL_SECONDS, DEFAULT_DELAY_WINDOW);
+    }
+
+    /**
+     * @param algorithm the encryption algorithm
+     * @param numberDigits the number of digits for tokens
+     * @param timeIntervalInSeconds the number of seconds a token is valid
+     * @param delayWindow the number of previous intervals that should be used to validate tokens.
+     */
+    public TimeBasedOTP(String algorithm, int numberDigits, int timeIntervalInSeconds, int delayWindow) {
+        this.algorithm = algorithm;
+        this.numberDigits = numberDigits;
+        this.clock = new Clock(timeIntervalInSeconds);
+        this.delayWindow = delayWindow;
+    }
+
+    /**
+     * <p>Generates a token.</p>
+     *
+     * @param secretKey the secret key to derive the token from.
+     */
+    public String generate(String secretKey) {
+        long T = this.clock.getCurrentInterval();
+
+        String steps = Long.toHexString(T).toUpperCase();
+
+        // Just get a 16 digit string
+        while (steps.length() < 16)
+            steps = "0" + steps;
+
+        return generateTOTP(secretKey, steps, this.numberDigits, this.algorithm);
+    }
+
+    /**
+     * This method generates an TOTP value for the given set of parameters.
+     *
+     * @param key          the shared secret, HEX encoded
+     * @param time         a value that reflects a time
+     * @param returnDigits number of digits to return
+     * @param crypto       the crypto function to use
+     * @return A numeric String in base 10 that includes {@link truncationDigits} digits
+     * @throws java.security.GeneralSecurityException
+     *
+     */
+    public String generateTOTP(String key, String time, int returnDigits, String crypto) {
+        String result = null;
+        byte[] hash;
+
+        // Using the counter
+        // First 8 bytes are for the movingFactor
+        // Complaint with base RFC 4226 (HOTP)
+        while (time.length() < 16)
+            time = "0" + time;
+
+        // Get the HEX in a Byte[]
+        byte[] msg = hexStr2Bytes(time);
+
+        // Adding one byte to get the right conversion
+        // byte[] k = hexStr2Bytes(key);
+        byte[] k = key.getBytes();
+
+        hash = hmac_sha1(crypto, k, msg);
+
+        // put selected bytes into result int
+        int offset = hash[hash.length - 1] & 0xf;
+
+        int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8)
+                | (hash[offset + 3] & 0xff);
+
+        int otp = binary % DIGITS_POWER[returnDigits];
+
+        result = Integer.toString(otp);
+
+        while (result.length() < returnDigits) {
+            result = "0" + result;
+        }
+        return result;
+    }
+
+    /**
+     * <p>Validates a token using a secret key.</p>
+     *
+     * @param token  OTP string to validate
+     * @param secret Shared secret
+     * @return
+     */
+    public boolean validate(String token, byte[] secret) {
+        long currentInterval = this.clock.getCurrentInterval();
+
+        for (int i = this.delayWindow; i >= 0; --i) {
+            String steps = Long.toHexString(currentInterval - i).toUpperCase();
+
+            // Just get a 16 digit string
+            while (steps.length() < 16)
+                steps = "0" + steps;
+
+            String candidate = generateTOTP(new String(secret), steps, this.numberDigits, this.algorithm);
+
+            if (candidate.equals(token)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public void setCalendar(Calendar calendar) {
+        this.clock.setCalendar(calendar);
+    }
+
+    /**
+     * This method uses the JCE to provide the crypto algorithm. HMAC computes a Hashed Message Authentication Code with the
+     * crypto hash algorithm as a parameter.
+     *
+     * @param crypto   the crypto algorithm (HmacSHA1, HmacSHA256, HmacSHA512)
+     * @param keyBytes the bytes to use for the HMAC key
+     * @param text     the message or text to be authenticated.
+     * @throws java.security.NoSuchAlgorithmException
+     *
+     * @throws java.security.InvalidKeyException
+     *
+     */
+    private byte[] hmac_sha1(String crypto, byte[] keyBytes, byte[] text) {
+        byte[] value;
+
+        try {
+            Mac hmac = Mac.getInstance(crypto);
+            SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
+
+            hmac.init(macKey);
+
+            value = hmac.doFinal(text);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return value;
+    }
+
+    /**
+     * This method converts HEX string to Byte[]
+     *
+     * @param hex the HEX string
+     * @return A byte array
+     */
+    private byte[] hexStr2Bytes(String hex) {
+        // Adding one byte to get the right conversion
+        // values starting with "0" can be converted
+        byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
+
+        // Copy all the REAL bytes, not the "first"
+        byte[] ret = new byte[bArray.length - 1];
+        for (int i = 0; i < ret.length; i++)
+            ret[i] = bArray[i + 1];
+        return ret;
+    }
+
+    private class Clock {
+
+        private final int interval;
+        private Calendar calendar;
+
+        public Clock(int interval) {
+            this.interval = interval;
+        }
+
+        public long getCurrentInterval() {
+            Calendar currentCalendar = this.calendar;
+
+            if (currentCalendar == null) {
+                currentCalendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
+            }
+
+            return (currentCalendar.getTimeInMillis() / 1000) / this.interval;
+        }
+
+        public void setCalendar(Calendar calendar) {
+            this.calendar = calendar;
+        }
+    }
 }
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
index 5d9cf70..9599ab9 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
@@ -1,248 +1,248 @@
-package org.keycloak.models.utils;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserModelDelegate implements UserModel {
-    protected UserModel delegate;
-
-    public UserModelDelegate(UserModel delegate) {
-        this.delegate = delegate;
-    }
-
-    @Override
-    public String getId() {
-        return delegate.getId();
-    }
-
-    @Override
-    public String getUsername() {
-        return delegate.getUsername();
-    }
-
-    @Override
-    public void setUsername(String username) {
-        delegate.setUsername(username);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return delegate.isEnabled();
-    }
-
-    @Override
-    public boolean isTotp() {
-        return delegate.isTotp();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        delegate.setEnabled(enabled);
-    }
-
-    @Override
-    public void setSingleAttribute(String name, String value) {
-        delegate.setSingleAttribute(name, value);
-    }
-
-    @Override
-    public void setAttribute(String name, List<String> values) {
-        delegate.setAttribute(name, values);
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        delegate.removeAttribute(name);
-    }
-
-    @Override
-    public String getFirstAttribute(String name) {
-        return delegate.getFirstAttribute(name);
-    }
-
-    @Override
-    public List<String> getAttribute(String name) {
-        return delegate.getAttribute(name);
-    }
-
-    @Override
-    public Map<String, List<String>> getAttributes() {
-        return delegate.getAttributes();
-    }
-
-    @Override
-    public Set<String> getRequiredActions() {
-        return delegate.getRequiredActions();
-    }
-
-    @Override
-    public void addRequiredAction(String action) {
-        delegate.addRequiredAction(action);
-    }
-
-    @Override
-    public void removeRequiredAction(String action) {
-        delegate.removeRequiredAction(action);
-    }
-
-    @Override
-    public void addRequiredAction(RequiredAction action) {
-        delegate.addRequiredAction(action);
-    }
-
-    @Override
-    public void removeRequiredAction(RequiredAction action) {
-        delegate.removeRequiredAction(action);
-    }
-
-    @Override
-    public String getFirstName() {
-        return delegate.getFirstName();
-    }
-
-    @Override
-    public void setFirstName(String firstName) {
-        delegate.setFirstName(firstName);
-    }
-
-    @Override
-    public String getLastName() {
-        return delegate.getLastName();
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        delegate.setLastName(lastName);
-    }
-
-    @Override
-    public String getEmail() {
-        return delegate.getEmail();
-    }
-
-    @Override
-    public void setEmail(String email) {
-        delegate.setEmail(email);
-    }
-
-    @Override
-    public boolean isEmailVerified() {
-        return delegate.isEmailVerified();
-    }
-
-    @Override
-    public void setEmailVerified(boolean verified) {
-        delegate.setEmailVerified(verified);
-    }
-
-    @Override
-    public void setTotp(boolean totp) {
-        delegate.setTotp(totp);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        delegate.updateCredential(cred);
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly() {
-        return delegate.getCredentialsDirectly();
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel cred) {
-        delegate.updateCredentialDirectly(cred);
-    }
-
-    @Override
-    public Set<RoleModel> getRealmRoleMappings() {
-        return delegate.getRealmRoleMappings();
-    }
-
-    @Override
-    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        return delegate.getClientRoleMappings(app);
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        return delegate.hasRole(role);
-    }
-
-    @Override
-    public void grantRole(RoleModel role) {
-        delegate.grantRole(role);
-    }
-
-    @Override
-    public Set<RoleModel> getRoleMappings() {
-        return delegate.getRoleMappings();
-    }
-
-    @Override
-    public void deleteRoleMapping(RoleModel role) {
-        delegate.deleteRoleMapping(role);
-    }
-
-    @Override
-    public String getFederationLink() {
-        return delegate.getFederationLink();
-    }
-
-    @Override
-    public void setFederationLink(String link) {
-        delegate.setFederationLink(link);
-    }
-
-    @Override
-    public void addConsent(UserConsentModel consent) {
-        delegate.addConsent(consent);
-    }
-
-    @Override
-    public UserConsentModel getConsentByClient(String clientId) {
-        return delegate.getConsentByClient(clientId);
-    }
-
-    @Override
-    public List<UserConsentModel> getConsents() {
-        return delegate.getConsents();
-    }
-
-    @Override
-    public void updateConsent(UserConsentModel consent) {
-        delegate.updateConsent(consent);
-    }
-
-    @Override
-    public boolean revokeConsentForClient(String clientId) {
-        return delegate.revokeConsentForClient(clientId);
-    }
-
-    public UserModel getDelegate() {
-        return delegate;
-    }
-    
-    @Override
-    public Long getCreatedTimestamp(){
-        return delegate.getCreatedTimestamp();
-    }
-    
-    @Override
-    public void setCreatedTimestamp(Long timestamp){
-        delegate.setCreatedTimestamp(timestamp);
-    }
-}
+package org.keycloak.models.utils;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserModelDelegate implements UserModel {
+    protected UserModel delegate;
+
+    public UserModelDelegate(UserModel delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public String getId() {
+        return delegate.getId();
+    }
+
+    @Override
+    public String getUsername() {
+        return delegate.getUsername();
+    }
+
+    @Override
+    public void setUsername(String username) {
+        delegate.setUsername(username);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return delegate.isEnabled();
+    }
+
+    @Override
+    public boolean isTotp() {
+        return delegate.isTotp();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        delegate.setEnabled(enabled);
+    }
+
+    @Override
+    public void setSingleAttribute(String name, String value) {
+        delegate.setSingleAttribute(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, List<String> values) {
+        delegate.setAttribute(name, values);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        delegate.removeAttribute(name);
+    }
+
+    @Override
+    public String getFirstAttribute(String name) {
+        return delegate.getFirstAttribute(name);
+    }
+
+    @Override
+    public List<String> getAttribute(String name) {
+        return delegate.getAttribute(name);
+    }
+
+    @Override
+    public Map<String, List<String>> getAttributes() {
+        return delegate.getAttributes();
+    }
+
+    @Override
+    public Set<String> getRequiredActions() {
+        return delegate.getRequiredActions();
+    }
+
+    @Override
+    public void addRequiredAction(String action) {
+        delegate.addRequiredAction(action);
+    }
+
+    @Override
+    public void removeRequiredAction(String action) {
+        delegate.removeRequiredAction(action);
+    }
+
+    @Override
+    public void addRequiredAction(RequiredAction action) {
+        delegate.addRequiredAction(action);
+    }
+
+    @Override
+    public void removeRequiredAction(RequiredAction action) {
+        delegate.removeRequiredAction(action);
+    }
+
+    @Override
+    public String getFirstName() {
+        return delegate.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        delegate.setFirstName(firstName);
+    }
+
+    @Override
+    public String getLastName() {
+        return delegate.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        delegate.setLastName(lastName);
+    }
+
+    @Override
+    public String getEmail() {
+        return delegate.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        delegate.setEmail(email);
+    }
+
+    @Override
+    public boolean isEmailVerified() {
+        return delegate.isEmailVerified();
+    }
+
+    @Override
+    public void setEmailVerified(boolean verified) {
+        delegate.setEmailVerified(verified);
+    }
+
+    @Override
+    public void setTotp(boolean totp) {
+        delegate.setTotp(totp);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        delegate.updateCredential(cred);
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        return delegate.getCredentialsDirectly();
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel cred) {
+        delegate.updateCredentialDirectly(cred);
+    }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings() {
+        return delegate.getRealmRoleMappings();
+    }
+
+    @Override
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        return delegate.getClientRoleMappings(app);
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        return delegate.hasRole(role);
+    }
+
+    @Override
+    public void grantRole(RoleModel role) {
+        delegate.grantRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoleMappings() {
+        return delegate.getRoleMappings();
+    }
+
+    @Override
+    public void deleteRoleMapping(RoleModel role) {
+        delegate.deleteRoleMapping(role);
+    }
+
+    @Override
+    public String getFederationLink() {
+        return delegate.getFederationLink();
+    }
+
+    @Override
+    public void setFederationLink(String link) {
+        delegate.setFederationLink(link);
+    }
+
+    @Override
+    public void addConsent(UserConsentModel consent) {
+        delegate.addConsent(consent);
+    }
+
+    @Override
+    public UserConsentModel getConsentByClient(String clientId) {
+        return delegate.getConsentByClient(clientId);
+    }
+
+    @Override
+    public List<UserConsentModel> getConsents() {
+        return delegate.getConsents();
+    }
+
+    @Override
+    public void updateConsent(UserConsentModel consent) {
+        delegate.updateConsent(consent);
+    }
+
+    @Override
+    public boolean revokeConsentForClient(String clientId) {
+        return delegate.revokeConsentForClient(clientId);
+    }
+
+    public UserModel getDelegate() {
+        return delegate;
+    }
+    
+    @Override
+    public Long getCreatedTimestamp(){
+        return delegate.getCreatedTimestamp();
+    }
+    
+    @Override
+    public void setCreatedTimestamp(Long timestamp){
+        delegate.setCreatedTimestamp(timestamp);
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java b/model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java
index c737306..8817852 100755
--- a/model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java
+++ b/model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java
@@ -1,13 +1,13 @@
-package org.keycloak.provider;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ConfiguredProvider {
-    String getHelpText();
-
-    List<ProviderConfigProperty> getConfigProperties();
-}
+package org.keycloak.provider;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ConfiguredProvider {
+    String getHelpText();
+
+    List<ProviderConfigProperty> getConfigProperties();
+}
diff --git a/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java b/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
index 69e1d16..55524a0 100755
--- a/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
+++ b/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
@@ -1,59 +1,59 @@
-package org.keycloak.provider;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class ProviderConfigProperty {
-    public static final String BOOLEAN_TYPE="boolean";
-    public static final String STRING_TYPE="String";
-    public static final String ROLE_TYPE="Role";
-    public static final String LIST_TYPE="List";
-    public static final String CLIENT_LIST_TYPE="ClientList";
-
-    protected String name;
-    protected String label;
-    protected String helpText;
-    protected String type;
-    protected Object defaultValue;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    public void setDefaultValue(Object defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    public String getHelpText() {
-        return helpText;
-    }
-
-    public void setHelpText(String helpText) {
-        this.helpText = helpText;
-    }
-}
+package org.keycloak.provider;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class ProviderConfigProperty {
+    public static final String BOOLEAN_TYPE="boolean";
+    public static final String STRING_TYPE="String";
+    public static final String ROLE_TYPE="Role";
+    public static final String LIST_TYPE="List";
+    public static final String CLIENT_LIST_TYPE="ClientList";
+
+    protected String name;
+    protected String label;
+    protected String helpText;
+    protected String type;
+    protected Object defaultValue;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Object getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(Object defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    public String getHelpText() {
+        return helpText;
+    }
+
+    public void setHelpText(String helpText) {
+        this.helpText = helpText;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/provider/ProviderEvent.java b/model/api/src/main/java/org/keycloak/provider/ProviderEvent.java
index 403e112..2fba363 100755
--- a/model/api/src/main/java/org/keycloak/provider/ProviderEvent.java
+++ b/model/api/src/main/java/org/keycloak/provider/ProviderEvent.java
@@ -1,8 +1,8 @@
-package org.keycloak.provider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ProviderEvent {
-}
+package org.keycloak.provider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ProviderEvent {
+}
diff --git a/model/api/src/main/java/org/keycloak/provider/ProviderEventListener.java b/model/api/src/main/java/org/keycloak/provider/ProviderEventListener.java
index 8f99462..ea74873 100755
--- a/model/api/src/main/java/org/keycloak/provider/ProviderEventListener.java
+++ b/model/api/src/main/java/org/keycloak/provider/ProviderEventListener.java
@@ -1,9 +1,9 @@
-package org.keycloak.provider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ProviderEventListener {
-    void onEvent(ProviderEvent event);
-}
+package org.keycloak.provider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ProviderEventListener {
+    void onEvent(ProviderEvent event);
+}
diff --git a/model/api/src/main/java/org/keycloak/provider/ProviderEventManager.java b/model/api/src/main/java/org/keycloak/provider/ProviderEventManager.java
index dfe6782..ed63427 100755
--- a/model/api/src/main/java/org/keycloak/provider/ProviderEventManager.java
+++ b/model/api/src/main/java/org/keycloak/provider/ProviderEventManager.java
@@ -1,13 +1,13 @@
-package org.keycloak.provider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ProviderEventManager {
-    void register(ProviderEventListener listener);
-
-    void unregister(ProviderEventListener listener);
-
-    void publish(ProviderEvent event);
-}
+package org.keycloak.provider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ProviderEventManager {
+    void register(ProviderEventListener listener);
+
+    void unregister(ProviderEventListener listener);
+
+    void publish(ProviderEvent event);
+}
diff --git a/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 37844e0..ba45379 100755
--- a/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,6 +1,6 @@
-org.keycloak.models.UserFederationSpi
-org.keycloak.mappers.UserFederationMapperSpi
-org.keycloak.models.RealmSpi
-org.keycloak.models.UserSessionSpi
-org.keycloak.models.UserSpi
+org.keycloak.models.UserFederationSpi
+org.keycloak.mappers.UserFederationMapperSpi
+org.keycloak.models.RealmSpi
+org.keycloak.models.UserSessionSpi
+org.keycloak.models.UserSpi
 org.keycloak.migration.MigrationSpi
\ No newline at end of file
diff --git a/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java b/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
index 9bdd231..4ce6c4d 100755
--- a/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
+++ b/model/api/src/test/java/org/keycloak/models/MigrationVersionTest.java
@@ -1,45 +1,45 @@
-package org.keycloak.models;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.keycloak.migration.ModelVersion;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MigrationVersionTest {
-
-    @Test
-    public void testVersion() {
-        ModelVersion version_100Beta1 = new ModelVersion("1.0.0.Beta1");
-        Assert.assertEquals(version_100Beta1.getMajor(), 1);
-        Assert.assertEquals(version_100Beta1.getMinor(), 0);
-        Assert.assertEquals(version_100Beta1.getMicro(), 0);
-        ModelVersion version_100CR1 = new ModelVersion("1.0.0.CR1");
-        ModelVersion version_100 = new ModelVersion("1.0.0");
-        ModelVersion version_110Beta1 = new ModelVersion("1.1.0.Beta1");
-        ModelVersion version_110CR1 = new ModelVersion("1.1.0.CR1");
-        ModelVersion version_110 = new ModelVersion("1.1.0");
-        ModelVersion version_111Beta1 = new ModelVersion("1.1.1.Beta1");
-        ModelVersion version_111CR1 = new ModelVersion("1.1.1.CR1");
-        ModelVersion version_111 = new ModelVersion("1.1.1");
-        ModelVersion version_211Beta1 = new ModelVersion("2.1.1.Beta1");
-        ModelVersion version_211CR1 = new ModelVersion("2.1.1.CR1");
-        Assert.assertEquals(version_211CR1.getMajor(), 2);
-        Assert.assertEquals(version_211CR1.getMinor(), 1);
-        Assert.assertEquals(version_211CR1.getMicro(), 1);
-        Assert.assertEquals(version_211CR1.getQualifier(), "CR1");
-        ModelVersion version_211 = new ModelVersion("2.1.1");
-
-        Assert.assertFalse(version_100Beta1.lessThan(version_100Beta1));
-        Assert.assertTrue(version_100Beta1.lessThan(version_100CR1));
-        Assert.assertTrue(version_100Beta1.lessThan(version_100));
-        Assert.assertTrue(version_100Beta1.lessThan(version_110Beta1));
-        Assert.assertTrue(version_100Beta1.lessThan(version_110CR1));
-        Assert.assertTrue(version_100Beta1.lessThan(version_110));
-
-        Assert.assertFalse(version_211.lessThan(version_110CR1));
-
-    }
-}
+package org.keycloak.models;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.migration.ModelVersion;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrationVersionTest {
+
+    @Test
+    public void testVersion() {
+        ModelVersion version_100Beta1 = new ModelVersion("1.0.0.Beta1");
+        Assert.assertEquals(version_100Beta1.getMajor(), 1);
+        Assert.assertEquals(version_100Beta1.getMinor(), 0);
+        Assert.assertEquals(version_100Beta1.getMicro(), 0);
+        ModelVersion version_100CR1 = new ModelVersion("1.0.0.CR1");
+        ModelVersion version_100 = new ModelVersion("1.0.0");
+        ModelVersion version_110Beta1 = new ModelVersion("1.1.0.Beta1");
+        ModelVersion version_110CR1 = new ModelVersion("1.1.0.CR1");
+        ModelVersion version_110 = new ModelVersion("1.1.0");
+        ModelVersion version_111Beta1 = new ModelVersion("1.1.1.Beta1");
+        ModelVersion version_111CR1 = new ModelVersion("1.1.1.CR1");
+        ModelVersion version_111 = new ModelVersion("1.1.1");
+        ModelVersion version_211Beta1 = new ModelVersion("2.1.1.Beta1");
+        ModelVersion version_211CR1 = new ModelVersion("2.1.1.CR1");
+        Assert.assertEquals(version_211CR1.getMajor(), 2);
+        Assert.assertEquals(version_211CR1.getMinor(), 1);
+        Assert.assertEquals(version_211CR1.getMicro(), 1);
+        Assert.assertEquals(version_211CR1.getQualifier(), "CR1");
+        ModelVersion version_211 = new ModelVersion("2.1.1");
+
+        Assert.assertFalse(version_100Beta1.lessThan(version_100Beta1));
+        Assert.assertTrue(version_100Beta1.lessThan(version_100CR1));
+        Assert.assertTrue(version_100Beta1.lessThan(version_100));
+        Assert.assertTrue(version_100Beta1.lessThan(version_110Beta1));
+        Assert.assertTrue(version_100Beta1.lessThan(version_110CR1));
+        Assert.assertTrue(version_100Beta1.lessThan(version_110));
+
+        Assert.assertFalse(version_211.lessThan(version_110CR1));
+
+    }
+}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
index e7847e2..85ab05f 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
@@ -1,627 +1,627 @@
-/*
- * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.models.file.adapter;
-
-import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.entities.ClientEntity;
-import org.keycloak.models.entities.ProtocolMapperEntity;
-import org.keycloak.models.entities.RoleEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * ApplicationModel used for JSON persistence.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
- */
-public class ClientAdapter implements ClientModel {
-
-    private final RealmModel realm;
-    private  KeycloakSession session;
-    private final ClientEntity entity;
-    private final InMemoryModel inMemoryModel;
-
-    private final Map<String, RoleAdapter> allRoles = new HashMap<String, RoleAdapter>();
-    private final Map<String, RoleModel> allScopeMappings = new HashMap<String, RoleModel>();
-
-    public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity entity, InMemoryModel inMemoryModel) {
-        this.realm = realm;
-        this.session = session;
-        this.entity = entity;
-        this.inMemoryModel = inMemoryModel;
-    }
-
-    @Override
-    public void updateClient() {
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public String getName() {
-        return entity.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-       entity.setName(name);
-    }
-
-    @Override
-    public Set<String> getWebOrigins() {
-        Set<String> result = new HashSet<String>();
-        if (entity.getWebOrigins() != null) {
-            result.addAll(entity.getWebOrigins());
-        }
-        return result;
-    }
-
-    @Override
-    public void setWebOrigins(Set<String> webOrigins) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(webOrigins);
-        entity.setWebOrigins(result);
-    }
-
-    @Override
-    public void addWebOrigin(String webOrigin) {
-        Set<String> webOrigins = getWebOrigins();
-        webOrigins.add(webOrigin);
-        setWebOrigins(webOrigins);
-    }
-
-    @Override
-    public void removeWebOrigin(String webOrigin) {
-        Set<String> webOrigins = getWebOrigins();
-        webOrigins.remove(webOrigin);
-        setWebOrigins(webOrigins);
-    }
-
-    @Override
-    public Set<String> getRedirectUris() {
-        Set<String> result = new HashSet<String>();
-        if (entity.getRedirectUris() != null) {
-            result.addAll(entity.getRedirectUris());
-        }
-        return result;
-    }
-
-    @Override
-    public void setRedirectUris(Set<String> redirectUris) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(redirectUris);
-        entity.setRedirectUris(result);
-    }
-
-    @Override
-    public void addRedirectUri(String redirectUri) {
-        if (entity.getRedirectUris().contains(redirectUri)) return;
-        entity.getRedirectUris().add(redirectUri);
-    }
-
-    @Override
-    public void removeRedirectUri(String redirectUri) {
-        entity.getRedirectUris().remove(redirectUri);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return entity.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        entity.setEnabled(enabled);
-    }
-
-    @Override
-    public boolean validateSecret(String secret) {
-        return secret.equals(entity.getSecret());
-    }
-
-    @Override
-    public String getSecret() {
-        return entity.getSecret();
-    }
-
-    @Override
-    public void setSecret(String secret) {
-        entity.setSecret(secret);
-    }
-
-    @Override
-    public boolean isPublicClient() {
-        return entity.isPublicClient();
-    }
-
-    @Override
-    public void setPublicClient(boolean flag) {
-        entity.setPublicClient(flag);
-    }
-
-
-    @Override
-    public boolean isFrontchannelLogout() {
-        return entity.isFrontchannelLogout();
-    }
-
-    @Override
-    public void setFrontchannelLogout(boolean flag) {
-        entity.setFrontchannelLogout(flag);
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        return entity.isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        entity.setFullScopeAllowed(value);
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public int getNotBefore() {
-        return entity.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        entity.setNotBefore(notBefore);
-    }
-
-    @Override
-    public Set<RoleModel> getScopeMappings() {
-        return new HashSet<RoleModel>(allScopeMappings.values());
-    }
-
-    @Override
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> allScopes = getScopeMappings();
-
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allScopes) {
-            RoleAdapter roleAdapter = (RoleAdapter)role;
-            if (roleAdapter.isRealmRole()) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public void addScopeMapping(RoleModel role) {
-        allScopeMappings.put(role.getId(), role);
-    }
-
-    @Override
-    public void deleteScopeMapping(RoleModel role) {
-        allScopeMappings.remove(role.getId());
-    }
-
-    @Override
-    public String getProtocol() {
-        return entity.getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        entity.setProtocol(protocol);
-
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        entity.getAttributes().put(name, value);
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        entity.getAttributes().remove(name);
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        return entity.getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(entity.getAttributes());
-        return copy;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
-        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
-            ProtocolMapperModel model = getProtocolMapperById(entity.getId());
-            if (model != null) result.add(model);
-        }
-        return result;
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        ProtocolMapperEntity entity = new ProtocolMapperEntity();
-        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
-        entity.setId(id);
-        entity.setProtocol(model.getProtocol());
-        entity.setName(model.getName());
-        entity.setProtocolMapper(model.getProtocolMapper());
-        entity.setConfig(model.getConfig());
-        entity.setConsentRequired(model.isConsentRequired());
-        entity.setConsentText(model.getConsentText());
-        this.entity.getProtocolMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity toBeRemoved = null;
-        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
-            if (e.getId().equals(mapping.getId())) {
-                toBeRemoved = e;
-                break;
-            }
-        }
-
-        entity.getProtocolMappers().remove(toBeRemoved);
-    }
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId());
-        entity.setProtocolMapper(mapping.getProtocolMapper());
-        entity.setConsentRequired(mapping.isConsentRequired());
-        entity.setConsentText(mapping.getConsentText());
-        if (entity.getConfig() != null) {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        } else {
-            entity.setConfig(mapping.getConfig());
-        }
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntityById(String id) {
-        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
-            if (e.getId().equals(id)) {
-                return e;
-            }
-        }
-        return null;
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
-        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
-            if (e.getProtocol().equals(protocol) && e.getName().equals(name)) {
-                return e;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityById(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
-        ProtocolMapperModel mapping = new ProtocolMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setProtocol(entity.getProtocol());
-        mapping.setProtocolMapper(entity.getProtocolMapper());
-        mapping.setConsentRequired(entity.isConsentRequired());
-        mapping.setConsentText(entity.getConsentText());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-    @Override
-    public String getClientId() {
-        return entity.getClientId();
-    }
-
-    @Override
-    public void setClientId(String clientId) {
-        if (appNameExists(clientId)) throw new ModelDuplicateException("Application named " + clientId + " already exists.");
-        entity.setClientId(clientId);
-    }
-
-    private boolean appNameExists(String name) {
-        for (ClientModel app : realm.getClients()) {
-            if (app == this) continue;
-            if (app.getClientId().equals(name)) return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean isSurrogateAuthRequired() {
-        return entity.isSurrogateAuthRequired();
-    }
-
-    @Override
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        entity.setSurrogateAuthRequired(surrogateAuthRequired);
-    }
-
-    @Override
-    public String getManagementUrl() {
-        return entity.getManagementUrl();
-    }
-
-    @Override
-    public void setManagementUrl(String url) {
-        entity.setManagementUrl(url);
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-        entity.setBaseUrl(url);
-    }
-
-    @Override
-    public String getBaseUrl() {
-        return entity.getBaseUrl();
-    }
-
-    @Override
-    public boolean isBearerOnly() {
-        return entity.isBearerOnly();
-    }
-
-    @Override
-    public void setBearerOnly(boolean only) {
-        entity.setBearerOnly(only);
-    }
-
-    @Override
-    public boolean isConsentRequired() {
-        return entity.isConsentRequired();
-    }
-
-    @Override
-    public void setConsentRequired(boolean consentRequired) {
-        entity.setConsentRequired(consentRequired);
-    }
-
-    @Override
-    public boolean isDirectGrantsOnly() {
-        return entity.isDirectGrantsOnly();
-    }
-
-    @Override
-    public void setDirectGrantsOnly(boolean flag) {
-        entity.setDirectGrantsOnly(flag);
-    }
-
-    @Override
-    public RoleAdapter getRole(String name) {
-        for (RoleAdapter role : allRoles.values()) {
-            if (role.getName().equals(name)) return role;
-        }
-        return null;
-    }
-
-    @Override
-    public RoleAdapter addRole(String name) {
-        return this.addRole(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RoleAdapter addRole(String id, String name) {
-        if (roleNameExists(name)) throw new ModelDuplicateException("Role named " + name + " already exists.");
-        RoleEntity roleEntity = new RoleEntity();
-        roleEntity.setId(id);
-        roleEntity.setName(name);
-        roleEntity.setClientId(getId());
-
-        RoleAdapter role = new RoleAdapter(getRealm(), roleEntity, this);
-        allRoles.put(id, role);
-
-        return role;
-    }
-
-    private boolean roleNameExists(String name) {
-        for (RoleModel role : allRoles.values()) {
-            if (role.getName().equals(name)) return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        boolean removed = (allRoles.remove(role.getId()) != null);
-
-        // remove application roles from users
-        for (UserModel user : inMemoryModel.getUsers(realm.getId())) {
-            user.deleteRoleMapping(role);
-        }
-
-        // delete scope mappings from applications
-        for (ClientModel app : realm.getClients()) {
-            app.deleteScopeMapping(role);
-        }
-
-        // remove role from the realm
-        realm.removeRole(role);
-
-        this.deleteScopeMapping(role);
-
-        return removed;
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        return new HashSet(allRoles.values());
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        roles = getRoles();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
-        Set<RoleModel> allScopes = client.getScopeMappings();
-
-        Set<RoleModel> appRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allScopes) {
-            RoleAdapter roleAdapter = (RoleAdapter)role;
-            if (getId().equals(roleAdapter.getRoleEntity().getClientId())) {
-                appRoles.add(role);
-            }
-        }
-        return appRoles;
-    }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        return entity.getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            addRole(name);
-        }
-
-        List<String> defaultRoles = getDefaultRoles();
-        if (defaultRoles.contains(name)) return;
-
-        String[] defaultRoleNames = defaultRoles.toArray(new String[defaultRoles.size() + 1]);
-        defaultRoleNames[defaultRoleNames.length - 1] = name;
-        updateDefaultRoles(defaultRoleNames);
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        List<String> roleNames = new ArrayList<String>();
-        for (String roleName : defaultRoles) {
-            RoleModel role = getRole(roleName);
-            if (role == null) {
-                addRole(roleName);
-            }
-
-            roleNames.add(roleName);
-        }
-
-        entity.setDefaultRoles(roleNames);
-    }
-
-    @Override
-    public int getNodeReRegistrationTimeout() {
-        return entity.getNodeReRegistrationTimeout();
-    }
-
-    @Override
-    public void setNodeReRegistrationTimeout(int timeout) {
-        entity.setNodeReRegistrationTimeout(timeout);
-    }
-
-    @Override
-    public Map<String, Integer> getRegisteredNodes() {
-        return entity.getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(entity.getRegisteredNodes());
-    }
-
-    @Override
-    public void registerNode(String nodeHost, int registrationTime) {
-        if (entity.getRegisteredNodes() == null) {
-            entity.setRegisteredNodes(new HashMap<String, Integer>());
-        }
-
-        entity.getRegisteredNodes().put(nodeHost, registrationTime);
-    }
-
-    @Override
-    public void unregisterNode(String nodeHost) {
-        if (entity.getRegisteredNodes() == null) return;
-
-        entity.getRegisteredNodes().remove(nodeHost);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof ClientModel)) return false;
-
-        ClientModel that = (ClientModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-}
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.models.file.adapter;
+
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.ClientEntity;
+import org.keycloak.models.entities.ProtocolMapperEntity;
+import org.keycloak.models.entities.RoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * ApplicationModel used for JSON persistence.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class ClientAdapter implements ClientModel {
+
+    private final RealmModel realm;
+    private  KeycloakSession session;
+    private final ClientEntity entity;
+    private final InMemoryModel inMemoryModel;
+
+    private final Map<String, RoleAdapter> allRoles = new HashMap<String, RoleAdapter>();
+    private final Map<String, RoleModel> allScopeMappings = new HashMap<String, RoleModel>();
+
+    public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity entity, InMemoryModel inMemoryModel) {
+        this.realm = realm;
+        this.session = session;
+        this.entity = entity;
+        this.inMemoryModel = inMemoryModel;
+    }
+
+    @Override
+    public void updateClient() {
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public String getName() {
+        return entity.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+       entity.setName(name);
+    }
+
+    @Override
+    public Set<String> getWebOrigins() {
+        Set<String> result = new HashSet<String>();
+        if (entity.getWebOrigins() != null) {
+            result.addAll(entity.getWebOrigins());
+        }
+        return result;
+    }
+
+    @Override
+    public void setWebOrigins(Set<String> webOrigins) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(webOrigins);
+        entity.setWebOrigins(result);
+    }
+
+    @Override
+    public void addWebOrigin(String webOrigin) {
+        Set<String> webOrigins = getWebOrigins();
+        webOrigins.add(webOrigin);
+        setWebOrigins(webOrigins);
+    }
+
+    @Override
+    public void removeWebOrigin(String webOrigin) {
+        Set<String> webOrigins = getWebOrigins();
+        webOrigins.remove(webOrigin);
+        setWebOrigins(webOrigins);
+    }
+
+    @Override
+    public Set<String> getRedirectUris() {
+        Set<String> result = new HashSet<String>();
+        if (entity.getRedirectUris() != null) {
+            result.addAll(entity.getRedirectUris());
+        }
+        return result;
+    }
+
+    @Override
+    public void setRedirectUris(Set<String> redirectUris) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(redirectUris);
+        entity.setRedirectUris(result);
+    }
+
+    @Override
+    public void addRedirectUri(String redirectUri) {
+        if (entity.getRedirectUris().contains(redirectUri)) return;
+        entity.getRedirectUris().add(redirectUri);
+    }
+
+    @Override
+    public void removeRedirectUri(String redirectUri) {
+        entity.getRedirectUris().remove(redirectUri);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return entity.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        entity.setEnabled(enabled);
+    }
+
+    @Override
+    public boolean validateSecret(String secret) {
+        return secret.equals(entity.getSecret());
+    }
+
+    @Override
+    public String getSecret() {
+        return entity.getSecret();
+    }
+
+    @Override
+    public void setSecret(String secret) {
+        entity.setSecret(secret);
+    }
+
+    @Override
+    public boolean isPublicClient() {
+        return entity.isPublicClient();
+    }
+
+    @Override
+    public void setPublicClient(boolean flag) {
+        entity.setPublicClient(flag);
+    }
+
+
+    @Override
+    public boolean isFrontchannelLogout() {
+        return entity.isFrontchannelLogout();
+    }
+
+    @Override
+    public void setFrontchannelLogout(boolean flag) {
+        entity.setFrontchannelLogout(flag);
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        return entity.isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        entity.setFullScopeAllowed(value);
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public int getNotBefore() {
+        return entity.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        entity.setNotBefore(notBefore);
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings() {
+        return new HashSet<RoleModel>(allScopeMappings.values());
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> allScopes = getScopeMappings();
+
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            RoleAdapter roleAdapter = (RoleAdapter)role;
+            if (roleAdapter.isRealmRole()) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void addScopeMapping(RoleModel role) {
+        allScopeMappings.put(role.getId(), role);
+    }
+
+    @Override
+    public void deleteScopeMapping(RoleModel role) {
+        allScopeMappings.remove(role.getId());
+    }
+
+    @Override
+    public String getProtocol() {
+        return entity.getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        entity.setProtocol(protocol);
+
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        entity.getAttributes().put(name, value);
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        entity.getAttributes().remove(name);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return entity.getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> copy = new HashMap<String, String>();
+        copy.putAll(entity.getAttributes());
+        return copy;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            ProtocolMapperModel model = getProtocolMapperById(entity.getId());
+            if (model != null) result.add(model);
+        }
+        return result;
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
+        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
+        entity.setId(id);
+        entity.setProtocol(model.getProtocol());
+        entity.setName(model.getName());
+        entity.setProtocolMapper(model.getProtocolMapper());
+        entity.setConfig(model.getConfig());
+        entity.setConsentRequired(model.isConsentRequired());
+        entity.setConsentText(model.getConsentText());
+        this.entity.getProtocolMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity toBeRemoved = null;
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getId().equals(mapping.getId())) {
+                toBeRemoved = e;
+                break;
+            }
+        }
+
+        entity.getProtocolMappers().remove(toBeRemoved);
+    }
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
+        entity.setConsentRequired(mapping.isConsentRequired());
+        entity.setConsentText(mapping.getConsentText());
+        if (entity.getConfig() != null) {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        } else {
+            entity.setConfig(mapping.getConfig());
+        }
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntityById(String id) {
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getId().equals(id)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getProtocol().equals(protocol) && e.getName().equals(name)) {
+                return e;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityById(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
+        mapping.setConsentRequired(entity.isConsentRequired());
+        mapping.setConsentText(entity.getConsentText());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+    @Override
+    public String getClientId() {
+        return entity.getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        if (appNameExists(clientId)) throw new ModelDuplicateException("Application named " + clientId + " already exists.");
+        entity.setClientId(clientId);
+    }
+
+    private boolean appNameExists(String name) {
+        for (ClientModel app : realm.getClients()) {
+            if (app == this) continue;
+            if (app.getClientId().equals(name)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return entity.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        entity.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return entity.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        entity.setManagementUrl(url);
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        entity.setBaseUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return entity.getBaseUrl();
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return entity.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        entity.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return entity.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        entity.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return entity.isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        entity.setDirectGrantsOnly(flag);
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        for (RoleAdapter role : allRoles.values()) {
+            if (role.getName().equals(name)) return role;
+        }
+        return null;
+    }
+
+    @Override
+    public RoleAdapter addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleAdapter addRole(String id, String name) {
+        if (roleNameExists(name)) throw new ModelDuplicateException("Role named " + name + " already exists.");
+        RoleEntity roleEntity = new RoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setClientId(getId());
+
+        RoleAdapter role = new RoleAdapter(getRealm(), roleEntity, this);
+        allRoles.put(id, role);
+
+        return role;
+    }
+
+    private boolean roleNameExists(String name) {
+        for (RoleModel role : allRoles.values()) {
+            if (role.getName().equals(name)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        boolean removed = (allRoles.remove(role.getId()) != null);
+
+        // remove application roles from users
+        for (UserModel user : inMemoryModel.getUsers(realm.getId())) {
+            user.deleteRoleMapping(role);
+        }
+
+        // delete scope mappings from applications
+        for (ClientModel app : realm.getClients()) {
+            app.deleteScopeMapping(role);
+        }
+
+        // remove role from the realm
+        realm.removeRole(role);
+
+        this.deleteScopeMapping(role);
+
+        return removed;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        return new HashSet(allRoles.values());
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> allScopes = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            RoleAdapter roleAdapter = (RoleAdapter)role;
+            if (getId().equals(roleAdapter.getRoleEntity().getClientId())) {
+                appRoles.add(role);
+            }
+        }
+        return appRoles;
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return entity.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        List<String> defaultRoles = getDefaultRoles();
+        if (defaultRoles.contains(name)) return;
+
+        String[] defaultRoleNames = defaultRoles.toArray(new String[defaultRoles.size() + 1]);
+        defaultRoleNames[defaultRoleNames.length - 1] = name;
+        updateDefaultRoles(defaultRoleNames);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        entity.setDefaultRoles(roleNames);
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return entity.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        entity.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return entity.getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(entity.getRegisteredNodes());
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        if (entity.getRegisteredNodes() == null) {
+            entity.setRegisteredNodes(new HashMap<String, Integer>());
+        }
+
+        entity.getRegisteredNodes().put(nodeHost, registrationTime);
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        if (entity.getRegisteredNodes() == null) return;
+
+        entity.getRegisteredNodes().remove(nodeHost);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/MigrationModelAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/MigrationModelAdapter.java
index f92718c..13695db 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/MigrationModelAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/MigrationModelAdapter.java
@@ -1,26 +1,26 @@
-package org.keycloak.models.file.adapter;
-
-import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.migration.MigrationModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MigrationModelAdapter implements MigrationModel {
-    protected InMemoryModel em;
-
-    public MigrationModelAdapter(InMemoryModel em) {
-        this.em = em;
-    }
-
-    @Override
-    public String getStoredVersion() {
-        return em.getModelVersion();
-    }
-
-    @Override
-    public void setStoredVersion(String version) {
-       em.setModelVersion(version);
-    }
-}
+package org.keycloak.models.file.adapter;
+
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.migration.MigrationModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrationModelAdapter implements MigrationModel {
+    protected InMemoryModel em;
+
+    public MigrationModelAdapter(InMemoryModel em) {
+        this.em = em;
+    }
+
+    @Override
+    public String getStoredVersion() {
+        return em.getModelVersion();
+    }
+
+    @Override
+    public void setStoredVersion(String version) {
+       em.setModelVersion(version);
+    }
+}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
index ebafc24..f037f01 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
@@ -1,523 +1,523 @@
-/*
- * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.models.file.adapter;
-
-import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.models.ClientModel;
-
-import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
-
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.entities.CredentialEntity;
-import org.keycloak.models.entities.FederatedIdentityEntity;
-import org.keycloak.models.entities.RoleEntity;
-import org.keycloak.models.entities.UserEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
-import org.keycloak.util.Time;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
-
-/**
- * UserModel for JSON persistence.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
- */
-public class UserAdapter implements UserModel, Comparable {
-
-    private final InMemoryModel inMemoryModel;
-    private final UserEntity user;
-    private final RealmModel realm;
-
-    private final Set<RoleModel> allRoles = new HashSet<RoleModel>();
-
-    public UserAdapter(RealmModel realm, UserEntity userEntity, InMemoryModel inMemoryModel) {
-        this.user = userEntity;
-        this.realm = realm;
-        if (userEntity.getFederatedIdentities() == null) {
-            userEntity.setFederatedIdentities(new ArrayList<FederatedIdentityEntity>());
-        }
-        this.inMemoryModel = inMemoryModel;
-    }
-
-    public UserEntity getUserEntity() {
-        return this.user;
-    }
-
-    @Override
-    public String getId() {
-        return user.getId();
-    }
-
-    @Override
-    public String getUsername() {
-        return user.getUsername();
-    }
-
-    @Override
-    public void setUsername(String username) {
-        if (getUsername() == null) {
-            user.setUsername(username);
-            return;
-        }
-
-        if (getUsername().equals(username)) return; // allow setting to same name
-
-        if (inMemoryModel.hasUserWithUsername(realm.getId(), username))
-            throw new ModelDuplicateException("User with username " + username + " already exists in realm.");
-        user.setUsername(username);
-    }
-
-    @Override
-    public Long getCreatedTimestamp() {
-        return user.getCreatedTimestamp();
-    }
-
-    @Override
-    public void setCreatedTimestamp(Long timestamp) {
-        user.setCreatedTimestamp(timestamp);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return user.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        user.setEnabled(enabled);
-    }
-
-    @Override
-    public String getFirstName() {
-        return user.getFirstName();
-    }
-
-    @Override
-    public void setFirstName(String firstName) {
-        user.setFirstName(firstName);
-    }
-
-    @Override
-    public String getLastName() {
-        return user.getLastName();
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        user.setLastName(lastName);
-    }
-
-    @Override
-    public String getEmail() {
-        return user.getEmail();
-    }
-
-    @Override
-    public void setEmail(String email) {
-        if (email == null) {
-            user.setEmail(email);
-            return;
-        }
-
-        if (email.equals(getEmail())) return;
-
-        RealmAdapter realmAdapter = (RealmAdapter)realm;
-        if (realmAdapter.hasUserWithEmail(email)) throw new ModelDuplicateException("User with email address " + email + " already exists.");
-        user.setEmail(email);
-    }
-
-    @Override
-    public boolean isEmailVerified() {
-        return user.isEmailVerified();
-    }
-
-    @Override
-    public void setEmailVerified(boolean verified) {
-        user.setEmailVerified(verified);
-    }
-
-    @Override
-    public void setSingleAttribute(String name, String value) {
-        if (user.getAttributes() == null) {
-            user.setAttributes(new HashMap<String, List<String>>());
-        }
-
-        List<String> attrValues = new ArrayList<>();
-        attrValues.add(value);
-        user.getAttributes().put(name, attrValues);
-    }
-
-    @Override
-    public void setAttribute(String name, List<String> values) {
-        if (user.getAttributes() == null) {
-            user.setAttributes(new HashMap<String, List<String>>());
-        }
-
-        user.getAttributes().put(name, values);
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        if (user.getAttributes() == null) return;
-
-        user.getAttributes().remove(name);
-    }
-
-    @Override
-    public String getFirstAttribute(String name) {
-        if (user.getAttributes()==null) return null;
-
-        List<String> attrValues = user.getAttributes().get(name);
-        return (attrValues==null || attrValues.isEmpty()) ? null : attrValues.get(0);
-    }
-
-    @Override
-    public List<String> getAttribute(String name) {
-        if (user.getAttributes()==null) return Collections.<String>emptyList();
-        List<String> attrValues = user.getAttributes().get(name);
-        return (attrValues == null) ? Collections.<String>emptyList() : Collections.unmodifiableList(attrValues);
-    }
-
-    @Override
-    public Map<String, List<String>> getAttributes() {
-        return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map)user.getAttributes());
-    }
-
-    @Override
-    public Set<String> getRequiredActions() {
-        List<String> requiredActions = user.getRequiredActions();
-        if (requiredActions == null) requiredActions = new ArrayList<String>();
-        return new HashSet(requiredActions);
-    }
-
-    @Override
-    public void addRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        addRequiredAction(actionName);
-    }
-
-    @Override
-    public void addRequiredAction(String actionName) {
-        List<String> requiredActions = user.getRequiredActions();
-        if (requiredActions == null) requiredActions = new ArrayList<>();
-        if (!requiredActions.contains(actionName)) {
-            requiredActions.add(actionName);
-        }
-        user.setRequiredActions(requiredActions);
-    }
-
-    @Override
-    public void removeRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        removeRequiredAction(actionName);
-    }
-
-    @Override
-    public void removeRequiredAction(String actionName) {
-        List<String> requiredActions = user.getRequiredActions();
-        if (requiredActions == null) return;
-        requiredActions.remove(actionName);
-        user.setRequiredActions(requiredActions);
-    }
-
-    @Override
-    public boolean isTotp() {
-        return user.isTotp();
-    }
-
-    @Override
-    public void setTotp(boolean totp) {
-        user.setTotp(totp);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            updatePasswordCredential(cred);
-        } else {
-            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-            if (credentialEntity == null) {
-                credentialEntity = setCredentials(user, cred);
-                credentialEntity.setValue(cred.getValue());
-                user.getCredentials().add(credentialEntity);
-            } else {
-                credentialEntity.setValue(cred.getValue());
-            }
-        }
-    }
-
-    private void updatePasswordCredential(UserCredentialModel cred) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = setCredentials(user, cred);
-            setValue(credentialEntity, cred);
-            user.getCredentials().add(credentialEntity);
-        } else {
-
-            int expiredPasswordsPolicyValue = -1;
-            PasswordPolicy policy = realm.getPasswordPolicy();
-            if(policy != null) {
-                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
-            }
-            
-            if (expiredPasswordsPolicyValue != -1) {
-                user.getCredentials().remove(credentialEntity);
-                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
-                user.getCredentials().add(credentialEntity);
-
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
-                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
-                }
-
-                credentialEntity = setCredentials(user, cred);
-                setValue(credentialEntity, cred);
-                user.getCredentials().add(credentialEntity);
-            } else {
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities != null && credentialEntities.size() > 0) {
-                    user.getCredentials().removeAll(credentialEntities);
-                }
-                setValue(credentialEntity, cred);
-            }
-        }
-    }
-    
-    private CredentialEntity setCredentials(UserEntity user, UserCredentialModel cred) {
-        CredentialEntity credentialEntity = new CredentialEntity();
-        credentialEntity.setType(cred.getType());
-        credentialEntity.setDevice(cred.getDevice());
-        return credentialEntity;
-    }
-
-    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
-        byte[] salt = getSalt();
-        int hashIterations = 1;
-        PasswordPolicy policy = realm.getPasswordPolicy();
-        if (policy != null) {
-            hashIterations = policy.getHashIterations();
-            if (hashIterations == -1)
-                hashIterations = 1;
-        }
-        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
-        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
-        credentialEntity.setSalt(salt);
-        credentialEntity.setHashIterations(hashIterations);
-    }
-
-    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                return entity;
-            }
-        }
-
-        return null;
-    }
-
-    private List<CredentialEntity> getCredentialEntities(UserEntity userEntity, String credType) {
-        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                credentialEntities.add(entity);
-            }
-        }
-        
-        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
-        // Orders from most recent to least recent
-        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
-            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
-                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
-                    return -1;
-                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-        });
-        return credentialEntities;
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly() {
-        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
-        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
-
-        for (CredentialEntity credEntity : credentials) {
-            UserCredentialValueModel credModel = new UserCredentialValueModel();
-            credModel.setType(credEntity.getType());
-            credModel.setDevice(credEntity.getDevice());
-            credModel.setCreatedDate(credEntity.getCreatedDate());
-            credModel.setValue(credEntity.getValue());
-            credModel.setSalt(credEntity.getSalt());
-            credModel.setHashIterations(credEntity.getHashIterations());
-
-            result.add(credModel);
-        }
-
-        return result;
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-        //    credentialEntity.setId(KeycloakModelUtils.generateId());
-            credentialEntity.setType(credModel.getType());
-        //    credentialEntity.setUser(user);
-            credModel.setCreatedDate(credModel.getCreatedDate());
-            user.getCredentials().add(credentialEntity);
-        }
-
-        credentialEntity.setValue(credModel.getValue());
-        credentialEntity.setSalt(credModel.getSalt());
-        credentialEntity.setDevice(credModel.getDevice());
-        credentialEntity.setHashIterations(credModel.getHashIterations());
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
-    }
-
-    @Override
-    public void grantRole(RoleModel role) {
-        allRoles.add(role);
-    }
-
-    @Override
-    public Set<RoleModel> getRoleMappings() {
-        return Collections.unmodifiableSet(allRoles);
-    }
-
-    @Override
-    public Set<RoleModel> getRealmRoleMappings() {
-        Set<RoleModel> allRoleMappings = getRoleMappings();
-
-        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allRoleMappings) {
-            RoleEntity roleEntity = ((RoleAdapter) role).getRoleEntity();
-
-            if (realm.getId().equals(roleEntity.getRealmId())) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public void deleteRoleMapping(RoleModel role) {
-        if (user == null || role == null) return;
-        allRoles.remove(role);
-    }
-
-    @Override
-    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        Set<RoleModel> result = new HashSet<RoleModel>();
-
-        for (RoleModel role : allRoles) {
-            RoleEntity roleEntity = ((RoleAdapter)role).getRoleEntity();
-            if (app.getId().equals(roleEntity.getClientId())) {
-                result.add(new RoleAdapter(realm, roleEntity, app));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public String getFederationLink() {
-        return user.getFederationLink();
-    }
-
-    @Override
-    public void setFederationLink(String link) {
-        user.setFederationLink(link);
-    }
-
-    @Override
-    public void addConsent(UserConsentModel consent) {
-        // TODO
-    }
-
-    @Override
-    public UserConsentModel getConsentByClient(String clientId) {
-        // TODO
-        return null;
-    }
-
-    @Override
-    public List<UserConsentModel> getConsents() {
-        // TODO
-        return null;
-    }
-
-    @Override
-    public void updateConsent(UserConsentModel consent) {
-        // TODO
-    }
-
-    @Override
-    public boolean revokeConsentForClient(String clientId) {
-        // TODO
-        return false;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof UserModel)) return false;
-
-        UserModel that = (UserModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public int compareTo(Object user) {
-        if (this == user) return 0;
-        return (getUsername().compareTo(((UserModel)user).getUsername()));
-    }
-}
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.models.file.adapter;
+
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.models.ClientModel;
+
+import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.CredentialEntity;
+import org.keycloak.models.entities.FederatedIdentityEntity;
+import org.keycloak.models.entities.RoleEntity;
+import org.keycloak.models.entities.UserEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
+import org.keycloak.util.Time;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+
+/**
+ * UserModel for JSON persistence.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class UserAdapter implements UserModel, Comparable {
+
+    private final InMemoryModel inMemoryModel;
+    private final UserEntity user;
+    private final RealmModel realm;
+
+    private final Set<RoleModel> allRoles = new HashSet<RoleModel>();
+
+    public UserAdapter(RealmModel realm, UserEntity userEntity, InMemoryModel inMemoryModel) {
+        this.user = userEntity;
+        this.realm = realm;
+        if (userEntity.getFederatedIdentities() == null) {
+            userEntity.setFederatedIdentities(new ArrayList<FederatedIdentityEntity>());
+        }
+        this.inMemoryModel = inMemoryModel;
+    }
+
+    public UserEntity getUserEntity() {
+        return this.user;
+    }
+
+    @Override
+    public String getId() {
+        return user.getId();
+    }
+
+    @Override
+    public String getUsername() {
+        return user.getUsername();
+    }
+
+    @Override
+    public void setUsername(String username) {
+        if (getUsername() == null) {
+            user.setUsername(username);
+            return;
+        }
+
+        if (getUsername().equals(username)) return; // allow setting to same name
+
+        if (inMemoryModel.hasUserWithUsername(realm.getId(), username))
+            throw new ModelDuplicateException("User with username " + username + " already exists in realm.");
+        user.setUsername(username);
+    }
+
+    @Override
+    public Long getCreatedTimestamp() {
+        return user.getCreatedTimestamp();
+    }
+
+    @Override
+    public void setCreatedTimestamp(Long timestamp) {
+        user.setCreatedTimestamp(timestamp);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return user.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        user.setEnabled(enabled);
+    }
+
+    @Override
+    public String getFirstName() {
+        return user.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        user.setFirstName(firstName);
+    }
+
+    @Override
+    public String getLastName() {
+        return user.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        user.setLastName(lastName);
+    }
+
+    @Override
+    public String getEmail() {
+        return user.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        if (email == null) {
+            user.setEmail(email);
+            return;
+        }
+
+        if (email.equals(getEmail())) return;
+
+        RealmAdapter realmAdapter = (RealmAdapter)realm;
+        if (realmAdapter.hasUserWithEmail(email)) throw new ModelDuplicateException("User with email address " + email + " already exists.");
+        user.setEmail(email);
+    }
+
+    @Override
+    public boolean isEmailVerified() {
+        return user.isEmailVerified();
+    }
+
+    @Override
+    public void setEmailVerified(boolean verified) {
+        user.setEmailVerified(verified);
+    }
+
+    @Override
+    public void setSingleAttribute(String name, String value) {
+        if (user.getAttributes() == null) {
+            user.setAttributes(new HashMap<String, List<String>>());
+        }
+
+        List<String> attrValues = new ArrayList<>();
+        attrValues.add(value);
+        user.getAttributes().put(name, attrValues);
+    }
+
+    @Override
+    public void setAttribute(String name, List<String> values) {
+        if (user.getAttributes() == null) {
+            user.setAttributes(new HashMap<String, List<String>>());
+        }
+
+        user.getAttributes().put(name, values);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        if (user.getAttributes() == null) return;
+
+        user.getAttributes().remove(name);
+    }
+
+    @Override
+    public String getFirstAttribute(String name) {
+        if (user.getAttributes()==null) return null;
+
+        List<String> attrValues = user.getAttributes().get(name);
+        return (attrValues==null || attrValues.isEmpty()) ? null : attrValues.get(0);
+    }
+
+    @Override
+    public List<String> getAttribute(String name) {
+        if (user.getAttributes()==null) return Collections.<String>emptyList();
+        List<String> attrValues = user.getAttributes().get(name);
+        return (attrValues == null) ? Collections.<String>emptyList() : Collections.unmodifiableList(attrValues);
+    }
+
+    @Override
+    public Map<String, List<String>> getAttributes() {
+        return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map)user.getAttributes());
+    }
+
+    @Override
+    public Set<String> getRequiredActions() {
+        List<String> requiredActions = user.getRequiredActions();
+        if (requiredActions == null) requiredActions = new ArrayList<String>();
+        return new HashSet(requiredActions);
+    }
+
+    @Override
+    public void addRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        addRequiredAction(actionName);
+    }
+
+    @Override
+    public void addRequiredAction(String actionName) {
+        List<String> requiredActions = user.getRequiredActions();
+        if (requiredActions == null) requiredActions = new ArrayList<>();
+        if (!requiredActions.contains(actionName)) {
+            requiredActions.add(actionName);
+        }
+        user.setRequiredActions(requiredActions);
+    }
+
+    @Override
+    public void removeRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        removeRequiredAction(actionName);
+    }
+
+    @Override
+    public void removeRequiredAction(String actionName) {
+        List<String> requiredActions = user.getRequiredActions();
+        if (requiredActions == null) return;
+        requiredActions.remove(actionName);
+        user.setRequiredActions(requiredActions);
+    }
+
+    @Override
+    public boolean isTotp() {
+        return user.isTotp();
+    }
+
+    @Override
+    public void setTotp(boolean totp) {
+        user.setTotp(totp);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            updatePasswordCredential(cred);
+        } else {
+            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+            if (credentialEntity == null) {
+                credentialEntity = setCredentials(user, cred);
+                credentialEntity.setValue(cred.getValue());
+                user.getCredentials().add(credentialEntity);
+            } else {
+                credentialEntity.setValue(cred.getValue());
+            }
+        }
+    }
+
+    private void updatePasswordCredential(UserCredentialModel cred) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = setCredentials(user, cred);
+            setValue(credentialEntity, cred);
+            user.getCredentials().add(credentialEntity);
+        } else {
+
+            int expiredPasswordsPolicyValue = -1;
+            PasswordPolicy policy = realm.getPasswordPolicy();
+            if(policy != null) {
+                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
+            }
+            
+            if (expiredPasswordsPolicyValue != -1) {
+                user.getCredentials().remove(credentialEntity);
+                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
+                user.getCredentials().add(credentialEntity);
+
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
+                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
+                }
+
+                credentialEntity = setCredentials(user, cred);
+                setValue(credentialEntity, cred);
+                user.getCredentials().add(credentialEntity);
+            } else {
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities != null && credentialEntities.size() > 0) {
+                    user.getCredentials().removeAll(credentialEntities);
+                }
+                setValue(credentialEntity, cred);
+            }
+        }
+    }
+    
+    private CredentialEntity setCredentials(UserEntity user, UserCredentialModel cred) {
+        CredentialEntity credentialEntity = new CredentialEntity();
+        credentialEntity.setType(cred.getType());
+        credentialEntity.setDevice(cred.getDevice());
+        return credentialEntity;
+    }
+
+    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
+        byte[] salt = getSalt();
+        int hashIterations = 1;
+        PasswordPolicy policy = realm.getPasswordPolicy();
+        if (policy != null) {
+            hashIterations = policy.getHashIterations();
+            if (hashIterations == -1)
+                hashIterations = 1;
+        }
+        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
+        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
+        credentialEntity.setSalt(salt);
+        credentialEntity.setHashIterations(hashIterations);
+    }
+
+    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                return entity;
+            }
+        }
+
+        return null;
+    }
+
+    private List<CredentialEntity> getCredentialEntities(UserEntity userEntity, String credType) {
+        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                credentialEntities.add(entity);
+            }
+        }
+        
+        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
+        // Orders from most recent to least recent
+        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
+            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
+                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
+                    return -1;
+                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+        return credentialEntities;
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
+        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
+
+        for (CredentialEntity credEntity : credentials) {
+            UserCredentialValueModel credModel = new UserCredentialValueModel();
+            credModel.setType(credEntity.getType());
+            credModel.setDevice(credEntity.getDevice());
+            credModel.setCreatedDate(credEntity.getCreatedDate());
+            credModel.setValue(credEntity.getValue());
+            credModel.setSalt(credEntity.getSalt());
+            credModel.setHashIterations(credEntity.getHashIterations());
+
+            result.add(credModel);
+        }
+
+        return result;
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+        //    credentialEntity.setId(KeycloakModelUtils.generateId());
+            credentialEntity.setType(credModel.getType());
+        //    credentialEntity.setUser(user);
+            credModel.setCreatedDate(credModel.getCreatedDate());
+            user.getCredentials().add(credentialEntity);
+        }
+
+        credentialEntity.setValue(credModel.getValue());
+        credentialEntity.setSalt(credModel.getSalt());
+        credentialEntity.setDevice(credModel.getDevice());
+        credentialEntity.setHashIterations(credModel.getHashIterations());
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        Set<RoleModel> roles = getRoleMappings();
+        return KeycloakModelUtils.hasRole(roles, role);
+    }
+
+    @Override
+    public void grantRole(RoleModel role) {
+        allRoles.add(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoleMappings() {
+        return Collections.unmodifiableSet(allRoles);
+    }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings() {
+        Set<RoleModel> allRoleMappings = getRoleMappings();
+
+        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allRoleMappings) {
+            RoleEntity roleEntity = ((RoleAdapter) role).getRoleEntity();
+
+            if (realm.getId().equals(roleEntity.getRealmId())) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void deleteRoleMapping(RoleModel role) {
+        if (user == null || role == null) return;
+        allRoles.remove(role);
+    }
+
+    @Override
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+
+        for (RoleModel role : allRoles) {
+            RoleEntity roleEntity = ((RoleAdapter)role).getRoleEntity();
+            if (app.getId().equals(roleEntity.getClientId())) {
+                result.add(new RoleAdapter(realm, roleEntity, app));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String getFederationLink() {
+        return user.getFederationLink();
+    }
+
+    @Override
+    public void setFederationLink(String link) {
+        user.setFederationLink(link);
+    }
+
+    @Override
+    public void addConsent(UserConsentModel consent) {
+        // TODO
+    }
+
+    @Override
+    public UserConsentModel getConsentByClient(String clientId) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public List<UserConsentModel> getConsents() {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public void updateConsent(UserConsentModel consent) {
+        // TODO
+    }
+
+    @Override
+    public boolean revokeConsentForClient(String clientId) {
+        // TODO
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserModel)) return false;
+
+        UserModel that = (UserModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public int compareTo(Object user) {
+        if (this == user) return 0;
+        return (getUsername().compareTo(((UserModel)user).getUsername()));
+    }
+}
diff --git a/model/invalidation-cache/infinispan/pom.xml b/model/invalidation-cache/infinispan/pom.xml
index 2b9501b..f9068a9 100755
--- a/model/invalidation-cache/infinispan/pom.xml
+++ b/model/invalidation-cache/infinispan/pom.xml
@@ -1,35 +1,35 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
-    <name>Keycloak Model Invalidation Cache Infinispan</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-invalidation-cache-model</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-infinispan</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
+    <name>Keycloak Model Invalidation Cache Infinispan</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-infinispan</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
index 5791f3e..dc571e7 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java
@@ -1,48 +1,48 @@
-package org.keycloak.models.cache.infinispan;
-
-import org.infinispan.Cache;
-import org.keycloak.Config;
-import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.cache.CacheRealmProvider;
-import org.keycloak.models.cache.CacheRealmProviderFactory;
-import org.keycloak.models.cache.DefaultCacheRealmProvider;
-import org.keycloak.models.cache.RealmCache;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFactory {
-
-    protected final ConcurrentHashMap<String, String> realmLookup = new ConcurrentHashMap<String, String>();
-
-    @Override
-    public CacheRealmProvider create(KeycloakSession session) {
-        Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
-        RealmCache realmCache = new InfinispanRealmCache(cache, realmLookup);
-        return new DefaultCacheRealmProvider(realmCache, session);
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public String getId() {
-        return "infinispan";
-    }
-
-}
+package org.keycloak.models.cache.infinispan;
+
+import org.infinispan.Cache;
+import org.keycloak.Config;
+import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.cache.CacheRealmProvider;
+import org.keycloak.models.cache.CacheRealmProviderFactory;
+import org.keycloak.models.cache.DefaultCacheRealmProvider;
+import org.keycloak.models.cache.RealmCache;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFactory {
+
+    protected final ConcurrentHashMap<String, String> realmLookup = new ConcurrentHashMap<String, String>();
+
+    @Override
+    public CacheRealmProvider create(KeycloakSession session) {
+        Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
+        RealmCache realmCache = new InfinispanRealmCache(cache, realmLookup);
+        return new DefaultCacheRealmProvider(realmCache, session);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public String getId() {
+        return "infinispan";
+    }
+
+}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
index bbe8981..30f4f43 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
@@ -1,154 +1,154 @@
-package org.keycloak.models.cache.infinispan;
-
-import org.infinispan.Cache;
-import org.infinispan.notifications.Listener;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
-import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
-import org.keycloak.Config;
-import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.cache.CacheUserProvider;
-import org.keycloak.models.cache.CacheUserProviderFactory;
-import org.keycloak.models.cache.DefaultCacheUserProvider;
-import org.keycloak.models.cache.entities.CachedUser;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class InfinispanCacheUserProviderFactory implements CacheUserProviderFactory {
-
-    protected InfinispanUserCache userCache;
-
-    protected final RealmLookup usernameLookup = new RealmLookup();
-
-    protected final RealmLookup emailLookup = new RealmLookup();
-
-    // Method CacheEntryCreatedEvent.getValue is available from ispn 6 (EAP6 and AS7 are on ispn 5)
-    private boolean isNewInfinispan;
-
-    @Override
-    public CacheUserProvider create(KeycloakSession session) {
-        lazyInit(session);
-        return new DefaultCacheUserProvider(userCache, session);
-    }
-
-    private void lazyInit(KeycloakSession session) {
-        if (userCache == null) {
-            synchronized (this) {
-                if (userCache == null) {
-                    checkIspnVersion();
-                    Cache<String, CachedUser> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.USER_CACHE_NAME);
-                    cache.addListener(new CacheListener());
-                    userCache = new InfinispanUserCache(cache, usernameLookup, emailLookup);
-                }
-            }
-        }
-    }
-
-    protected void checkIspnVersion() {
-        try {
-            CacheEntryCreatedEvent.class.getMethod("getValue");
-            isNewInfinispan = true;
-        } catch (NoSuchMethodException nsme) {
-            isNewInfinispan = false;
-        }
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public String getId() {
-        return "infinispan";
-    }
-
-    @Listener
-    public class CacheListener {
-
-        @CacheEntryCreated
-        public void userCreated(CacheEntryCreatedEvent<String, CachedUser> event) {
-            if (!event.isPre()) {
-
-                CachedUser cachedUser;
-
-                // Try optimized version if available
-                if (isNewInfinispan) {
-                    cachedUser = event.getValue();
-                } else {
-                    String userId = event.getKey();
-                    cachedUser = event.getCache().get(userId);
-                }
-
-                if (cachedUser != null) {
-                    String realm = cachedUser.getRealm();
-                    usernameLookup.put(realm, cachedUser.getUsername(), cachedUser.getId());
-                    if (cachedUser.getEmail() != null) {
-                        emailLookup.put(realm, cachedUser.getEmail(), cachedUser.getId());
-                    }
-                }
-            }
-        }
-
-        @CacheEntryRemoved
-        public void userRemoved(CacheEntryRemovedEvent<String, CachedUser> event) {
-            if (event.isPre() && event.getValue() != null) {
-                CachedUser cachedUser = event.getValue();
-                String realm = cachedUser.getRealm();
-                usernameLookup.remove(realm, cachedUser.getUsername());
-                if (cachedUser.getEmail() != null) {
-                    emailLookup.remove(realm, cachedUser.getEmail());
-                }
-            }
-        }
-
-    }
-
-    static class RealmLookup {
-
-        protected final ConcurrentHashMap<String, ConcurrentHashMap<String, String>> lookup = new ConcurrentHashMap<String, ConcurrentHashMap<String, String>>();
-
-        public void put(String realm, String key, String value) {
-            ConcurrentHashMap<String, String> map = lookup.get(realm);
-            if(map == null) {
-                map = new ConcurrentHashMap<String, String>();
-                ConcurrentHashMap<String, String> p = lookup.putIfAbsent(realm, map);
-                if (p != null) {
-                    map = p;
-                }
-            }
-            map.put(key, value);
-        }
-
-        public String get(String realm, String key) {
-            ConcurrentHashMap<String, String> map = lookup.get(realm);
-            return map != null ? map.get(key) : null;
-        }
-
-        public void remove(String realm, String key) {
-            ConcurrentHashMap<String, String> map = lookup.get(realm);
-            if (map != null) {
-                map.remove(key);
-                if (map.isEmpty()) {
-                    lookup.remove(realm);
-                }
-            }
-        }
-
-    }
-
-}
+package org.keycloak.models.cache.infinispan;
+
+import org.infinispan.Cache;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+import org.keycloak.Config;
+import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.cache.CacheUserProvider;
+import org.keycloak.models.cache.CacheUserProviderFactory;
+import org.keycloak.models.cache.DefaultCacheUserProvider;
+import org.keycloak.models.cache.entities.CachedUser;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class InfinispanCacheUserProviderFactory implements CacheUserProviderFactory {
+
+    protected InfinispanUserCache userCache;
+
+    protected final RealmLookup usernameLookup = new RealmLookup();
+
+    protected final RealmLookup emailLookup = new RealmLookup();
+
+    // Method CacheEntryCreatedEvent.getValue is available from ispn 6 (EAP6 and AS7 are on ispn 5)
+    private boolean isNewInfinispan;
+
+    @Override
+    public CacheUserProvider create(KeycloakSession session) {
+        lazyInit(session);
+        return new DefaultCacheUserProvider(userCache, session);
+    }
+
+    private void lazyInit(KeycloakSession session) {
+        if (userCache == null) {
+            synchronized (this) {
+                if (userCache == null) {
+                    checkIspnVersion();
+                    Cache<String, CachedUser> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.USER_CACHE_NAME);
+                    cache.addListener(new CacheListener());
+                    userCache = new InfinispanUserCache(cache, usernameLookup, emailLookup);
+                }
+            }
+        }
+    }
+
+    protected void checkIspnVersion() {
+        try {
+            CacheEntryCreatedEvent.class.getMethod("getValue");
+            isNewInfinispan = true;
+        } catch (NoSuchMethodException nsme) {
+            isNewInfinispan = false;
+        }
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public String getId() {
+        return "infinispan";
+    }
+
+    @Listener
+    public class CacheListener {
+
+        @CacheEntryCreated
+        public void userCreated(CacheEntryCreatedEvent<String, CachedUser> event) {
+            if (!event.isPre()) {
+
+                CachedUser cachedUser;
+
+                // Try optimized version if available
+                if (isNewInfinispan) {
+                    cachedUser = event.getValue();
+                } else {
+                    String userId = event.getKey();
+                    cachedUser = event.getCache().get(userId);
+                }
+
+                if (cachedUser != null) {
+                    String realm = cachedUser.getRealm();
+                    usernameLookup.put(realm, cachedUser.getUsername(), cachedUser.getId());
+                    if (cachedUser.getEmail() != null) {
+                        emailLookup.put(realm, cachedUser.getEmail(), cachedUser.getId());
+                    }
+                }
+            }
+        }
+
+        @CacheEntryRemoved
+        public void userRemoved(CacheEntryRemovedEvent<String, CachedUser> event) {
+            if (event.isPre() && event.getValue() != null) {
+                CachedUser cachedUser = event.getValue();
+                String realm = cachedUser.getRealm();
+                usernameLookup.remove(realm, cachedUser.getUsername());
+                if (cachedUser.getEmail() != null) {
+                    emailLookup.remove(realm, cachedUser.getEmail());
+                }
+            }
+        }
+
+    }
+
+    static class RealmLookup {
+
+        protected final ConcurrentHashMap<String, ConcurrentHashMap<String, String>> lookup = new ConcurrentHashMap<String, ConcurrentHashMap<String, String>>();
+
+        public void put(String realm, String key, String value) {
+            ConcurrentHashMap<String, String> map = lookup.get(realm);
+            if(map == null) {
+                map = new ConcurrentHashMap<String, String>();
+                ConcurrentHashMap<String, String> p = lookup.putIfAbsent(realm, map);
+                if (p != null) {
+                    map = p;
+                }
+            }
+            map.put(key, value);
+        }
+
+        public String get(String realm, String key) {
+            ConcurrentHashMap<String, String> map = lookup.get(realm);
+            return map != null ? map.get(key) : null;
+        }
+
+        public void remove(String realm, String key) {
+            ConcurrentHashMap<String, String> map = lookup.get(realm);
+            if (map != null) {
+                map.remove(key);
+                if (map.isEmpty()) {
+                    lookup.remove(realm);
+                }
+            }
+        }
+
+    }
+
+}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
index 735e721..07554a8 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
@@ -1,140 +1,140 @@
-package org.keycloak.models.cache.infinispan;
-
-import org.infinispan.Cache;
-import org.jboss.logging.Logger;
-import org.keycloak.models.cache.RealmCache;
-import org.keycloak.models.cache.entities.CachedClient;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.entities.CachedRole;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class InfinispanRealmCache implements RealmCache {
-
-    protected static final Logger logger = Logger.getLogger(InfinispanRealmCache.class);
-
-    protected final Cache<String, Object> cache;
-    protected final ConcurrentHashMap<String, String> realmLookup;
-    protected volatile boolean enabled = true;
-
-    public InfinispanRealmCache(Cache<String, Object> cache, ConcurrentHashMap<String, String> realmLookup) {
-        this.cache = cache;
-        this.realmLookup = realmLookup;
-    }
-
-    @Override
-    public void clear() {
-        cache.clear();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        clear();
-        this.enabled = enabled;
-        clear();
-    }
-
-    @Override
-    public CachedRealm getCachedRealm(String id) {
-        if (!enabled) return null;
-        return get(id, CachedRealm.class);
-    }
-
-    @Override
-    public void invalidateCachedRealm(CachedRealm realm) {
-        logger.tracev("Invalidating realm {0}", realm.getId());
-        cache.remove(realm.getId());
-        realmLookup.remove(realm.getName());
-    }
-
-    @Override
-    public void invalidateCachedRealmById(String id) {
-        CachedRealm cached = (CachedRealm) cache.remove(id);
-        if (cached != null) realmLookup.remove(cached.getName());
-    }
-
-    @Override
-    public void addCachedRealm(CachedRealm realm) {
-        if (!enabled) return;
-        logger.tracev("Adding realm {0}", realm.getId());
-        cache.put(realm.getId(), realm);
-        realmLookup.put(realm.getName(), realm.getId());
-    }
-
-    @Override
-    public CachedRealm getCachedRealmByName(String name) {
-        if (!enabled) return null;
-        String id = realmLookup.get(name);
-        return id != null ? getCachedRealm(id) : null;
-    }
-
-    @Override
-    public CachedClient getApplication(String id) {
-        if (!enabled) return null;
-        return get(id, CachedClient.class);
-    }
-
-    @Override
-    public void invalidateApplication(CachedClient app) {
-        logger.tracev("Removing application {0}", app.getId());
-        cache.remove(app.getId());
-    }
-
-    @Override
-    public void addCachedClient(CachedClient app) {
-        if (!enabled) return;
-        logger.tracev("Adding application {0}", app.getId());
-        cache.put(app.getId(), app);
-    }
-
-    @Override
-    public void invalidateCachedApplicationById(String id) {
-        logger.tracev("Removing application {0}", id);
-        cache.remove(id);
-    }
-
-    @Override
-    public CachedRole getRole(String id) {
-        if (!enabled) return null;
-        return get(id, CachedRole.class);
-    }
-
-    @Override
-    public void invalidateRole(CachedRole role) {
-        logger.tracev("Removing role {0}", role.getId());
-        cache.remove(role.getId());
-    }
-
-    @Override
-    public void invalidateRoleById(String id) {
-        logger.tracev("Removing role {0}", id);
-        cache.remove(id);
-    }
-
-    @Override
-    public void addCachedRole(CachedRole role) {
-        if (!enabled) return;
-        logger.tracev("Adding role {0}", role.getId());
-        cache.put(role.getId(), role);
-    }
-
-    @Override
-    public void invalidateCachedRoleById(String id) {
-        logger.tracev("Removing role {0}", id);
-        cache.remove(id);
-    }
-
-    private <T> T get(String id, Class<T> type) {
-        Object o = cache.get(id);
-        return o != null && type.isInstance(o) ? type.cast(o) : null;
-    }
-
-}
+package org.keycloak.models.cache.infinispan;
+
+import org.infinispan.Cache;
+import org.jboss.logging.Logger;
+import org.keycloak.models.cache.RealmCache;
+import org.keycloak.models.cache.entities.CachedClient;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedRole;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class InfinispanRealmCache implements RealmCache {
+
+    protected static final Logger logger = Logger.getLogger(InfinispanRealmCache.class);
+
+    protected final Cache<String, Object> cache;
+    protected final ConcurrentHashMap<String, String> realmLookup;
+    protected volatile boolean enabled = true;
+
+    public InfinispanRealmCache(Cache<String, Object> cache, ConcurrentHashMap<String, String> realmLookup) {
+        this.cache = cache;
+        this.realmLookup = realmLookup;
+    }
+
+    @Override
+    public void clear() {
+        cache.clear();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        clear();
+        this.enabled = enabled;
+        clear();
+    }
+
+    @Override
+    public CachedRealm getCachedRealm(String id) {
+        if (!enabled) return null;
+        return get(id, CachedRealm.class);
+    }
+
+    @Override
+    public void invalidateCachedRealm(CachedRealm realm) {
+        logger.tracev("Invalidating realm {0}", realm.getId());
+        cache.remove(realm.getId());
+        realmLookup.remove(realm.getName());
+    }
+
+    @Override
+    public void invalidateCachedRealmById(String id) {
+        CachedRealm cached = (CachedRealm) cache.remove(id);
+        if (cached != null) realmLookup.remove(cached.getName());
+    }
+
+    @Override
+    public void addCachedRealm(CachedRealm realm) {
+        if (!enabled) return;
+        logger.tracev("Adding realm {0}", realm.getId());
+        cache.put(realm.getId(), realm);
+        realmLookup.put(realm.getName(), realm.getId());
+    }
+
+    @Override
+    public CachedRealm getCachedRealmByName(String name) {
+        if (!enabled) return null;
+        String id = realmLookup.get(name);
+        return id != null ? getCachedRealm(id) : null;
+    }
+
+    @Override
+    public CachedClient getApplication(String id) {
+        if (!enabled) return null;
+        return get(id, CachedClient.class);
+    }
+
+    @Override
+    public void invalidateApplication(CachedClient app) {
+        logger.tracev("Removing application {0}", app.getId());
+        cache.remove(app.getId());
+    }
+
+    @Override
+    public void addCachedClient(CachedClient app) {
+        if (!enabled) return;
+        logger.tracev("Adding application {0}", app.getId());
+        cache.put(app.getId(), app);
+    }
+
+    @Override
+    public void invalidateCachedApplicationById(String id) {
+        logger.tracev("Removing application {0}", id);
+        cache.remove(id);
+    }
+
+    @Override
+    public CachedRole getRole(String id) {
+        if (!enabled) return null;
+        return get(id, CachedRole.class);
+    }
+
+    @Override
+    public void invalidateRole(CachedRole role) {
+        logger.tracev("Removing role {0}", role.getId());
+        cache.remove(role.getId());
+    }
+
+    @Override
+    public void invalidateRoleById(String id) {
+        logger.tracev("Removing role {0}", id);
+        cache.remove(id);
+    }
+
+    @Override
+    public void addCachedRole(CachedRole role) {
+        if (!enabled) return;
+        logger.tracev("Adding role {0}", role.getId());
+        cache.put(role.getId(), role);
+    }
+
+    @Override
+    public void invalidateCachedRoleById(String id) {
+        logger.tracev("Removing role {0}", id);
+        cache.remove(id);
+    }
+
+    private <T> T get(String id, Class<T> type) {
+        Object o = cache.get(id);
+        return o != null && type.isInstance(o) ? type.cast(o) : null;
+    }
+
+}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
index 7efa174..fbb36c5 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
@@ -1,95 +1,95 @@
-package org.keycloak.models.cache.infinispan;
-
-import org.infinispan.Cache;
-import org.jboss.logging.Logger;
-import org.keycloak.models.cache.UserCache;
-import org.keycloak.models.cache.entities.CachedUser;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class InfinispanUserCache implements UserCache {
-
-    protected static final Logger logger = Logger.getLogger(InfinispanRealmCache.class);
-
-    protected volatile boolean enabled = true;
-
-    protected final Cache<String, CachedUser> cache;
-
-    protected final InfinispanCacheUserProviderFactory.RealmLookup usernameLookup;
-
-    protected final InfinispanCacheUserProviderFactory.RealmLookup emailLookup;
-
-    public InfinispanUserCache(Cache<String, CachedUser> cache, InfinispanCacheUserProviderFactory.RealmLookup usernameLookup, InfinispanCacheUserProviderFactory.RealmLookup emailLookup) {
-        this.cache = cache;
-        this.usernameLookup = usernameLookup;
-        this.emailLookup = emailLookup;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        clear();
-        this.enabled = enabled;
-        clear();
-    }
-
-    @Override
-    public CachedUser getCachedUser(String realmId, String id) {
-        if (realmId == null || id == null) return null;
-        CachedUser user = cache.get(id);
-        return user != null && realmId.equals(user.getRealm()) ? user : null;
-    }
-
-    @Override
-    public void invalidateCachedUser(String realmId, CachedUser user) {
-        logger.tracev("Invalidating user {0}", user.getId());
-        cache.remove(user.getId());
-    }
-
-    @Override
-    public void invalidateCachedUserById(String realmId, String id) {
-        logger.tracev("Invalidating user {0}", id);
-        cache.remove(id);
-    }
-
-    @Override
-    public void addCachedUser(String realmId, CachedUser user) {
-        logger.tracev("Adding user {0}", user.getId());
-        cache.put(user.getId(), user);
-    }
-
-    @Override
-    public CachedUser getCachedUserByUsername(String realmId, String name) {
-        String id = usernameLookup.get(realmId, name);
-        return id != null ? getCachedUser(realmId, id) : null;
-    }
-
-    @Override
-    public CachedUser getCachedUserByEmail(String realmId, String email) {
-        String id = emailLookup.get(realmId, email);
-        return id != null ? getCachedUser(realmId, id) : null;
-    }
-
-    @Override
-    public void invalidateRealmUsers(String realmId) {
-        logger.tracev("Invalidating users for realm {0}", realmId);
-        for (Map.Entry<String, CachedUser> u : cache.entrySet()) {
-            if (u.getValue().getRealm().equals(realmId)) {
-                cache.remove(u.getKey());
-            }
-        }
-    }
-
-    @Override
-    public void clear() {
-        cache.clear();
-    }
-
-}
+package org.keycloak.models.cache.infinispan;
+
+import org.infinispan.Cache;
+import org.jboss.logging.Logger;
+import org.keycloak.models.cache.UserCache;
+import org.keycloak.models.cache.entities.CachedUser;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class InfinispanUserCache implements UserCache {
+
+    protected static final Logger logger = Logger.getLogger(InfinispanRealmCache.class);
+
+    protected volatile boolean enabled = true;
+
+    protected final Cache<String, CachedUser> cache;
+
+    protected final InfinispanCacheUserProviderFactory.RealmLookup usernameLookup;
+
+    protected final InfinispanCacheUserProviderFactory.RealmLookup emailLookup;
+
+    public InfinispanUserCache(Cache<String, CachedUser> cache, InfinispanCacheUserProviderFactory.RealmLookup usernameLookup, InfinispanCacheUserProviderFactory.RealmLookup emailLookup) {
+        this.cache = cache;
+        this.usernameLookup = usernameLookup;
+        this.emailLookup = emailLookup;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        clear();
+        this.enabled = enabled;
+        clear();
+    }
+
+    @Override
+    public CachedUser getCachedUser(String realmId, String id) {
+        if (realmId == null || id == null) return null;
+        CachedUser user = cache.get(id);
+        return user != null && realmId.equals(user.getRealm()) ? user : null;
+    }
+
+    @Override
+    public void invalidateCachedUser(String realmId, CachedUser user) {
+        logger.tracev("Invalidating user {0}", user.getId());
+        cache.remove(user.getId());
+    }
+
+    @Override
+    public void invalidateCachedUserById(String realmId, String id) {
+        logger.tracev("Invalidating user {0}", id);
+        cache.remove(id);
+    }
+
+    @Override
+    public void addCachedUser(String realmId, CachedUser user) {
+        logger.tracev("Adding user {0}", user.getId());
+        cache.put(user.getId(), user);
+    }
+
+    @Override
+    public CachedUser getCachedUserByUsername(String realmId, String name) {
+        String id = usernameLookup.get(realmId, name);
+        return id != null ? getCachedUser(realmId, id) : null;
+    }
+
+    @Override
+    public CachedUser getCachedUserByEmail(String realmId, String email) {
+        String id = emailLookup.get(realmId, email);
+        return id != null ? getCachedUser(realmId, id) : null;
+    }
+
+    @Override
+    public void invalidateRealmUsers(String realmId) {
+        logger.tracev("Invalidating users for realm {0}", realmId);
+        for (Map.Entry<String, CachedUser> u : cache.entrySet()) {
+            if (u.getValue().getRealm().equals(realmId)) {
+                cache.remove(u.getKey());
+            }
+        }
+    }
+
+    @Override
+    public void clear() {
+        cache.clear();
+    }
+
+}
diff --git a/model/invalidation-cache/model-adapters/pom.xml b/model/invalidation-cache/model-adapters/pom.xml
index ee61f1f..fb6056a 100755
--- a/model/invalidation-cache/model-adapters/pom.xml
+++ b/model/invalidation-cache/model-adapters/pom.xml
@@ -1,76 +1,76 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-invalidation-cache-model</artifactId>
-    <name>Keycloak Model Invalidation Cache</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-invalidation-cache-model</artifactId>
+    <name>Keycloak Model Invalidation Cache</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
index 9810d50..4aab371 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
@@ -1,20 +1,20 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.RealmProvider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface CacheRealmProvider extends RealmProvider {
-    RealmProvider getDelegate();
-
-    boolean isEnabled();
-    void setEnabled(boolean enabled);
-
-    void registerRealmInvalidation(String id);
-
-    void registerApplicationInvalidation(String id);
-
-    void registerRoleInvalidation(String id);
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.RealmProvider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CacheRealmProvider extends RealmProvider {
+    RealmProvider getDelegate();
+
+    boolean isEnabled();
+    void setEnabled(boolean enabled);
+
+    void registerRealmInvalidation(String id);
+
+    void registerApplicationInvalidation(String id);
+
+    void registerRoleInvalidation(String id);
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderFactory.java
index af84c7b..ed6e774 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderFactory.java
@@ -1,11 +1,11 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface CacheRealmProviderFactory extends ProviderFactory<CacheRealmProvider> {
-
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CacheRealmProviderFactory extends ProviderFactory<CacheRealmProvider> {
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
index bff04a9..07f0faf 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProviderSpi.java
@@ -1,32 +1,32 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.Spi;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CacheRealmProviderSpi implements Spi {
-
-    @Override
-    public boolean isInternal() {
-        return true;
-    }
-
-    @Override
-    public String getName() {
-        return "realmCache";
-    }
-
-    @Override
-    public Class<? extends Provider> getProviderClass() {
-        return CacheRealmProvider.class;
-    }
-
-    @Override
-    public Class<? extends ProviderFactory> getProviderFactoryClass() {
-        return CacheRealmProviderFactory.class;
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CacheRealmProviderSpi implements Spi {
+
+    @Override
+    public boolean isInternal() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return "realmCache";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return CacheRealmProvider.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return CacheRealmProviderFactory.class;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
index 8a5f68f..ec0d021 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
@@ -1,15 +1,15 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserProvider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface CacheUserProvider extends UserProvider {
-    UserProvider getDelegate();
-    boolean isEnabled();
-    void setEnabled(boolean enabled);
-    void registerUserInvalidation(RealmModel realm, String id);
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserProvider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CacheUserProvider extends UserProvider {
+    UserProvider getDelegate();
+    boolean isEnabled();
+    void setEnabled(boolean enabled);
+    void registerUserInvalidation(RealmModel realm, String id);
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java
index 4341ad5..1b7e2e7 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java
@@ -1,11 +1,11 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface CacheUserProviderFactory extends ProviderFactory<CacheUserProvider> {
-
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CacheUserProviderFactory extends ProviderFactory<CacheUserProvider> {
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
index 989f062..f70c633 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
@@ -1,32 +1,32 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.Spi;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CacheUserProviderSpi implements Spi {
-
-    @Override
-    public boolean isInternal() {
-        return true;
-    }
-
-    @Override
-    public String getName() {
-        return "userCache";
-    }
-
-    @Override
-    public Class<? extends Provider> getProviderClass() {
-        return CacheUserProvider.class;
-    }
-
-    @Override
-    public Class<? extends ProviderFactory> getProviderFactoryClass() {
-        return CacheUserProviderFactory.class;
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CacheUserProviderSpi implements Spi {
+
+    @Override
+    public boolean isInternal() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return "userCache";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return CacheUserProvider.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return CacheUserProviderFactory.class;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
index 48089bd..bc31941 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
@@ -1,523 +1,523 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.cache.entities.CachedClient;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientAdapter implements ClientModel {
-    protected CacheRealmProvider cacheSession;
-    protected RealmModel cachedRealm;
-    protected RealmCache cache;
-
-    protected ClientModel updated;
-    protected CachedClient cached;
-
-    public ClientAdapter(RealmModel cachedRealm, CachedClient cached, CacheRealmProvider cacheSession, RealmCache cache) {
-        this.cachedRealm = cachedRealm;
-        this.cache = cache;
-        this.cacheSession = cacheSession;
-        this.cached = cached;
-    }
-
-    private void getDelegateForUpdate() {
-        if (updated == null) {
-            cacheSession.registerApplicationInvalidation(getId());
-            updated = updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
-            if (updated == null) throw new IllegalStateException("Not found in database");
-        }
-    }
-
-    @Override
-    public void updateClient() {
-        if (updated != null) updated.updateClient();
-    }
-
-    @Override
-    public String getId() {
-        if (updated != null) return updated.getId();
-        return cached.getId();
-    }
-
-    public Set<String> getWebOrigins() {
-        if (updated != null) return updated.getWebOrigins();
-        return cached.getWebOrigins();
-    }
-
-    public void setWebOrigins(Set<String> webOrigins) {
-        getDelegateForUpdate();
-        updated.setWebOrigins(webOrigins);
-    }
-
-    public void addWebOrigin(String webOrigin) {
-        getDelegateForUpdate();
-        updated.addWebOrigin(webOrigin);
-    }
-
-    public void removeWebOrigin(String webOrigin) {
-        getDelegateForUpdate();
-        updated.removeWebOrigin(webOrigin);
-    }
-
-    public Set<String> getRedirectUris() {
-        if (updated != null) return updated.getRedirectUris();
-        return cached.getRedirectUris();
-    }
-
-    public void setRedirectUris(Set<String> redirectUris) {
-        getDelegateForUpdate();
-        updated.setRedirectUris(redirectUris);
-    }
-
-    public void addRedirectUri(String redirectUri) {
-        getDelegateForUpdate();
-        updated.addRedirectUri(redirectUri);
-    }
-
-    public void removeRedirectUri(String redirectUri) {
-        getDelegateForUpdate();
-        updated.removeRedirectUri(redirectUri);
-    }
-
-    public boolean isEnabled() {
-        if (updated != null) return updated.isEnabled();
-        return cached.isEnabled();
-    }
-
-    public void setEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setEnabled(enabled);
-    }
-
-    public boolean validateSecret(String secret) {
-        return secret.equals(getSecret());
-    }
-
-    public String getSecret() {
-        if (updated != null) return updated.getSecret();
-        return cached.getSecret();
-    }
-
-    public void setSecret(String secret) {
-        getDelegateForUpdate();
-        updated.setSecret(secret);
-    }
-
-    public boolean isPublicClient() {
-        if (updated != null) return updated.isPublicClient();
-        return cached.isPublicClient();
-    }
-
-    public void setPublicClient(boolean flag) {
-        getDelegateForUpdate();
-        updated.setPublicClient(flag);
-    }
-
-    public boolean isFrontchannelLogout() {
-        if (updated != null) return updated.isPublicClient();
-        return cached.isFrontchannelLogout();
-    }
-
-    public void setFrontchannelLogout(boolean flag) {
-        getDelegateForUpdate();
-        updated.setFrontchannelLogout(flag);
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        if (updated != null) return updated.isFullScopeAllowed();
-        return cached.isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        getDelegateForUpdate();
-        updated.setFullScopeAllowed(value);
-
-    }
-
-    public boolean isDirectGrantsOnly() {
-        if (updated != null) return updated.isDirectGrantsOnly();
-        return cached.isDirectGrantsOnly();
-    }
-
-    public void setDirectGrantsOnly(boolean flag) {
-        getDelegateForUpdate();
-        updated.setDirectGrantsOnly(flag);
-    }
-
-    public Set<RoleModel> getScopeMappings() {
-        if (updated != null) return updated.getScopeMappings();
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String id : cached.getScope()) {
-            roles.add(cacheSession.getRoleById(id, getRealm()));
-
-        }
-        return roles;
-    }
-
-    public void addScopeMapping(RoleModel role) {
-        getDelegateForUpdate();
-        updated.addScopeMapping(role);
-    }
-
-    public void deleteScopeMapping(RoleModel role) {
-        getDelegateForUpdate();
-        updated.deleteScopeMapping(role);
-    }
-
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> roleMappings = getScopeMappings();
-
-        Set<RoleModel> appRoles = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-                if (((RealmModel) container).getId().equals(cachedRealm.getId())) {
-                    appRoles.add(role);
-                }
-            }
-        }
-
-        return appRoles;
-    }
-
-    public RealmModel getRealm() {
-        return cachedRealm;
-    }
-
-    public int getNotBefore() {
-        if (updated != null) return updated.getNotBefore();
-        return cached.getNotBefore();
-    }
-
-    public void setNotBefore(int notBefore) {
-        getDelegateForUpdate();
-        updated.setNotBefore(notBefore);
-    }
-
-    @Override
-    public String getProtocol() {
-        if (updated != null) return updated.getProtocol();
-        return cached.getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        getDelegateForUpdate();
-        updated.setProtocol(protocol);
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        getDelegateForUpdate();
-        updated.setAttribute(name, value);
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        getDelegateForUpdate();
-        updated.removeAttribute(name);
-
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        if (updated != null) return updated.getAttribute(name);
-        return cached.getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        if (updated != null) return updated.getAttributes();
-        Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(cached.getAttributes());
-        return copy;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        if (updated != null) return updated.getProtocolMappers();
-        return cached.getProtocolMappers();
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        getDelegateForUpdate();
-        return updated.addProtocolMapper(model);
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        getDelegateForUpdate();
-        updated.removeProtocolMapper(mapping);
-
-    }
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        getDelegateForUpdate();
-        updated.updateProtocolMapper(mapping);
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
-            if (mapping.getId().equals(id)) return mapping;
-        }
-        return null;
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
-            if (mapping.getProtocol().equals(protocol) && mapping.getName().equals(name)) return mapping;
-        }
-        return null;
-    }
-
-    @Override
-    public String getClientId() {
-        if (updated != null) return updated.getClientId();
-        return cached.getClientId();
-    }
-
-    @Override
-    public void setClientId(String clientId) {
-        getDelegateForUpdate();
-        updated.setClientId(clientId);
-        cacheSession.registerRealmInvalidation(cachedRealm.getId());
-    }
-
-    @Override
-    public String getName() {
-        if (updated != null) return updated.getName();
-        return cached.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        getDelegateForUpdate();
-        updated.setName(name);
-    }
-
-    @Override
-    public boolean isSurrogateAuthRequired() {
-        if (updated != null) return updated.isSurrogateAuthRequired();
-        return cached.isSurrogateAuthRequired();
-    }
-
-    @Override
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        getDelegateForUpdate();
-        updated.setSurrogateAuthRequired(surrogateAuthRequired);
-    }
-
-    @Override
-    public String getManagementUrl() {
-        if (updated != null) return updated.getManagementUrl();
-        return cached.getManagementUrl();
-    }
-
-    @Override
-    public void setManagementUrl(String url) {
-        getDelegateForUpdate();
-        updated.setManagementUrl(url);
-    }
-
-    @Override
-    public String getBaseUrl() {
-        if (updated != null) return updated.getBaseUrl();
-        return cached.getBaseUrl();
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-        getDelegateForUpdate();
-        updated.setBaseUrl(url);
-    }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        if (updated != null) return updated.getDefaultRoles();
-        return cached.getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        getDelegateForUpdate();
-        updated.addDefaultRole(name);
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        getDelegateForUpdate();
-        updated.updateDefaultRoles(defaultRoles);
-    }
-
-    @Override
-    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
-        Set<RoleModel> roleMappings = client.getScopeMappings();
-
-        Set<RoleModel> appRoles = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-            } else {
-                ClientModel app = (ClientModel)container;
-                if (app.getId().equals(getId())) {
-                    appRoles.add(role);
-                }
-            }
-        }
-
-        return appRoles;
-    }
-
-    @Override
-    public boolean isBearerOnly() {
-        if (updated != null) return updated.isBearerOnly();
-        return cached.isBearerOnly();
-    }
-
-    @Override
-    public void setBearerOnly(boolean only) {
-        getDelegateForUpdate();
-        updated.setBearerOnly(only);
-    }
-
-    @Override
-    public boolean isConsentRequired() {
-        if (updated != null) return updated.isConsentRequired();
-        return cached.isConsentRequired();
-    }
-
-    @Override
-    public void setConsentRequired(boolean consentRequired) {
-        getDelegateForUpdate();
-        updated.setConsentRequired(consentRequired);
-    }
-
-    @Override
-    public RoleModel getRole(String name) {
-        if (updated != null) return updated.getRole(name);
-        String id = cached.getRoles().get(name);
-        if (id == null) return null;
-        return cacheSession.getRoleById(id, cachedRealm);
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        getDelegateForUpdate();
-        RoleModel role = updated.addRole(name);
-        cacheSession.registerRoleInvalidation(role.getId());
-        return role;
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        getDelegateForUpdate();
-        RoleModel role =  updated.addRole(id, name);
-        cacheSession.registerRoleInvalidation(role.getId());
-        return role;
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        cacheSession.registerRoleInvalidation(role.getId());
-        getDelegateForUpdate();
-        return updated.removeRole(role);
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        if (updated != null) return updated.getRoles();
-
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String id : cached.getRoles().values()) {
-            RoleModel roleById = cacheSession.getRoleById(id, cachedRealm);
-            if (roleById == null) continue;
-            roles.add(roleById);
-        }
-        return roles;
-    }
-
-    @Override
-    public int getNodeReRegistrationTimeout() {
-        if (updated != null) return updated.getNodeReRegistrationTimeout();
-        return cached.getNodeReRegistrationTimeout();
-    }
-
-    @Override
-    public void setNodeReRegistrationTimeout(int timeout) {
-        getDelegateForUpdate();
-        updated.setNodeReRegistrationTimeout(timeout);
-    }
-
-    @Override
-    public Map<String, Integer> getRegisteredNodes() {
-        if (updated != null) return updated.getRegisteredNodes();
-        return cached.getRegisteredNodes();
-    }
-
-    @Override
-    public void registerNode(String nodeHost, int registrationTime) {
-        getDelegateForUpdate();
-        updated.registerNode(nodeHost, registrationTime);
-    }
-
-    @Override
-    public void unregisterNode(String nodeHost) {
-        getDelegateForUpdate();
-        updated.unregisterNode(nodeHost);
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (updated != null) return updated.hasScope(role);
-        if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
-
-        Set<RoleModel> roles = getScopeMappings();
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-
-        roles = getRoles();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof ClientModel)) return false;
-
-        ClientModel that = (ClientModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.cache.entities.CachedClient;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientAdapter implements ClientModel {
+    protected CacheRealmProvider cacheSession;
+    protected RealmModel cachedRealm;
+    protected RealmCache cache;
+
+    protected ClientModel updated;
+    protected CachedClient cached;
+
+    public ClientAdapter(RealmModel cachedRealm, CachedClient cached, CacheRealmProvider cacheSession, RealmCache cache) {
+        this.cachedRealm = cachedRealm;
+        this.cache = cache;
+        this.cacheSession = cacheSession;
+        this.cached = cached;
+    }
+
+    private void getDelegateForUpdate() {
+        if (updated == null) {
+            cacheSession.registerApplicationInvalidation(getId());
+            updated = updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
+
+    @Override
+    public void updateClient() {
+        if (updated != null) updated.updateClient();
+    }
+
+    @Override
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
+
+    public Set<String> getWebOrigins() {
+        if (updated != null) return updated.getWebOrigins();
+        return cached.getWebOrigins();
+    }
+
+    public void setWebOrigins(Set<String> webOrigins) {
+        getDelegateForUpdate();
+        updated.setWebOrigins(webOrigins);
+    }
+
+    public void addWebOrigin(String webOrigin) {
+        getDelegateForUpdate();
+        updated.addWebOrigin(webOrigin);
+    }
+
+    public void removeWebOrigin(String webOrigin) {
+        getDelegateForUpdate();
+        updated.removeWebOrigin(webOrigin);
+    }
+
+    public Set<String> getRedirectUris() {
+        if (updated != null) return updated.getRedirectUris();
+        return cached.getRedirectUris();
+    }
+
+    public void setRedirectUris(Set<String> redirectUris) {
+        getDelegateForUpdate();
+        updated.setRedirectUris(redirectUris);
+    }
+
+    public void addRedirectUri(String redirectUri) {
+        getDelegateForUpdate();
+        updated.addRedirectUri(redirectUri);
+    }
+
+    public void removeRedirectUri(String redirectUri) {
+        getDelegateForUpdate();
+        updated.removeRedirectUri(redirectUri);
+    }
+
+    public boolean isEnabled() {
+        if (updated != null) return updated.isEnabled();
+        return cached.isEnabled();
+    }
+
+    public void setEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setEnabled(enabled);
+    }
+
+    public boolean validateSecret(String secret) {
+        return secret.equals(getSecret());
+    }
+
+    public String getSecret() {
+        if (updated != null) return updated.getSecret();
+        return cached.getSecret();
+    }
+
+    public void setSecret(String secret) {
+        getDelegateForUpdate();
+        updated.setSecret(secret);
+    }
+
+    public boolean isPublicClient() {
+        if (updated != null) return updated.isPublicClient();
+        return cached.isPublicClient();
+    }
+
+    public void setPublicClient(boolean flag) {
+        getDelegateForUpdate();
+        updated.setPublicClient(flag);
+    }
+
+    public boolean isFrontchannelLogout() {
+        if (updated != null) return updated.isPublicClient();
+        return cached.isFrontchannelLogout();
+    }
+
+    public void setFrontchannelLogout(boolean flag) {
+        getDelegateForUpdate();
+        updated.setFrontchannelLogout(flag);
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        if (updated != null) return updated.isFullScopeAllowed();
+        return cached.isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        getDelegateForUpdate();
+        updated.setFullScopeAllowed(value);
+
+    }
+
+    public boolean isDirectGrantsOnly() {
+        if (updated != null) return updated.isDirectGrantsOnly();
+        return cached.isDirectGrantsOnly();
+    }
+
+    public void setDirectGrantsOnly(boolean flag) {
+        getDelegateForUpdate();
+        updated.setDirectGrantsOnly(flag);
+    }
+
+    public Set<RoleModel> getScopeMappings() {
+        if (updated != null) return updated.getScopeMappings();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String id : cached.getScope()) {
+            roles.add(cacheSession.getRoleById(id, getRealm()));
+
+        }
+        return roles;
+    }
+
+    public void addScopeMapping(RoleModel role) {
+        getDelegateForUpdate();
+        updated.addScopeMapping(role);
+    }
+
+    public void deleteScopeMapping(RoleModel role) {
+        getDelegateForUpdate();
+        updated.deleteScopeMapping(role);
+    }
+
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> roleMappings = getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+                if (((RealmModel) container).getId().equals(cachedRealm.getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+    public RealmModel getRealm() {
+        return cachedRealm;
+    }
+
+    public int getNotBefore() {
+        if (updated != null) return updated.getNotBefore();
+        return cached.getNotBefore();
+    }
+
+    public void setNotBefore(int notBefore) {
+        getDelegateForUpdate();
+        updated.setNotBefore(notBefore);
+    }
+
+    @Override
+    public String getProtocol() {
+        if (updated != null) return updated.getProtocol();
+        return cached.getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        getDelegateForUpdate();
+        updated.setProtocol(protocol);
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, value);
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        getDelegateForUpdate();
+        updated.removeAttribute(name);
+
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        if (updated != null) return updated.getAttribute(name);
+        return cached.getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        if (updated != null) return updated.getAttributes();
+        Map<String, String> copy = new HashMap<String, String>();
+        copy.putAll(cached.getAttributes());
+        return copy;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        if (updated != null) return updated.getProtocolMappers();
+        return cached.getProtocolMappers();
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        getDelegateForUpdate();
+        return updated.addProtocolMapper(model);
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        getDelegateForUpdate();
+        updated.removeProtocolMapper(mapping);
+
+    }
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        getDelegateForUpdate();
+        updated.updateProtocolMapper(mapping);
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
+            if (mapping.getId().equals(id)) return mapping;
+        }
+        return null;
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
+            if (mapping.getProtocol().equals(protocol) && mapping.getName().equals(name)) return mapping;
+        }
+        return null;
+    }
+
+    @Override
+    public String getClientId() {
+        if (updated != null) return updated.getClientId();
+        return cached.getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        getDelegateForUpdate();
+        updated.setClientId(clientId);
+        cacheSession.registerRealmInvalidation(cachedRealm.getId());
+    }
+
+    @Override
+    public String getName() {
+        if (updated != null) return updated.getName();
+        return cached.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getDelegateForUpdate();
+        updated.setName(name);
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        if (updated != null) return updated.isSurrogateAuthRequired();
+        return cached.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        getDelegateForUpdate();
+        updated.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        if (updated != null) return updated.getManagementUrl();
+        return cached.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        getDelegateForUpdate();
+        updated.setManagementUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        if (updated != null) return updated.getBaseUrl();
+        return cached.getBaseUrl();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        getDelegateForUpdate();
+        updated.setBaseUrl(url);
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        if (updated != null) return updated.getDefaultRoles();
+        return cached.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        getDelegateForUpdate();
+        updated.addDefaultRole(name);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        getDelegateForUpdate();
+        updated.updateDefaultRoles(defaultRoles);
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> roleMappings = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ClientModel app = (ClientModel)container;
+                if (app.getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        if (updated != null) return updated.isBearerOnly();
+        return cached.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        getDelegateForUpdate();
+        updated.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        if (updated != null) return updated.isConsentRequired();
+        return cached.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        getDelegateForUpdate();
+        updated.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        if (updated != null) return updated.getRole(name);
+        String id = cached.getRoles().get(name);
+        if (id == null) return null;
+        return cacheSession.getRoleById(id, cachedRealm);
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        getDelegateForUpdate();
+        RoleModel role = updated.addRole(name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        getDelegateForUpdate();
+        RoleModel role =  updated.addRole(id, name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        cacheSession.registerRoleInvalidation(role.getId());
+        getDelegateForUpdate();
+        return updated.removeRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        if (updated != null) return updated.getRoles();
+
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String id : cached.getRoles().values()) {
+            RoleModel roleById = cacheSession.getRoleById(id, cachedRealm);
+            if (roleById == null) continue;
+            roles.add(roleById);
+        }
+        return roles;
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        if (updated != null) return updated.getNodeReRegistrationTimeout();
+        return cached.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        getDelegateForUpdate();
+        updated.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        if (updated != null) return updated.getRegisteredNodes();
+        return cached.getRegisteredNodes();
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        getDelegateForUpdate();
+        updated.registerNode(nodeHost, registrationTime);
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        getDelegateForUpdate();
+        updated.unregisterNode(nodeHost);
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (updated != null) return updated.hasScope(role);
+        if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
+
+        Set<RoleModel> roles = getScopeMappings();
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
index 436e189..eca2572 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
@@ -1,294 +1,294 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakTransaction;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.cache.entities.CachedClient;
-import org.keycloak.models.cache.entities.CachedClientRole;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.entities.CachedRealmRole;
-import org.keycloak.models.cache.entities.CachedRole;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DefaultCacheRealmProvider implements CacheRealmProvider {
-    protected RealmCache cache;
-    protected KeycloakSession session;
-    protected RealmProvider delegate;
-    protected boolean transactionActive;
-    protected boolean setRollbackOnly;
-
-    protected Set<String> realmInvalidations = new HashSet<String>();
-    protected Set<String> appInvalidations = new HashSet<String>();
-    protected Set<String> roleInvalidations = new HashSet<String>();
-    protected Map<String, RealmModel> managedRealms = new HashMap<String, RealmModel>();
-    protected Map<String, ClientModel> managedApplications = new HashMap<String, ClientModel>();
-    protected Map<String, RoleModel> managedRoles = new HashMap<String, RoleModel>();
-
-    protected boolean clearAll;
-
-    public DefaultCacheRealmProvider(RealmCache cache, KeycloakSession session) {
-        this.cache = cache;
-        this.session = session;
-
-        session.getTransaction().enlistAfterCompletion(getTransaction());
-    }
-
-    @Override
-    public MigrationModel getMigrationModel() {
-        return getDelegate().getMigrationModel();
-    }
-
-
-    @Override
-    public boolean isEnabled() {
-        return cache.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        cache.setEnabled(enabled);
-    }
-
-    @Override
-    public RealmProvider getDelegate() {
-        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
-        if (delegate != null) return delegate;
-        delegate = session.getProvider(RealmProvider.class);
-        return delegate;
-    }
-
-    @Override
-    public void registerRealmInvalidation(String id) {
-        realmInvalidations.add(id);
-    }
-
-    @Override
-    public void registerApplicationInvalidation(String id) {
-        appInvalidations.add(id);
-    }
-
-    @Override
-    public void registerRoleInvalidation(String id) {
-        roleInvalidations.add(id);
-    }
-
-    protected void runInvalidations() {
-        for (String id : realmInvalidations) {
-            cache.invalidateCachedRealmById(id);
-        }
-        for (String id : roleInvalidations) {
-            cache.invalidateRoleById(id);
-        }
-        for (String id : appInvalidations) {
-            cache.invalidateCachedApplicationById(id);
-        }
-    }
-
-    private KeycloakTransaction getTransaction() {
-        return new KeycloakTransaction() {
-            @Override
-            public void begin() {
-                transactionActive = true;
-            }
-
-            @Override
-            public void commit() {
-                if (delegate == null) return;
-                if (clearAll) {
-                    cache.clear();
-                }
-                runInvalidations();
-                transactionActive = false;
-            }
-
-            @Override
-            public void rollback() {
-                setRollbackOnly = true;
-                runInvalidations();
-                transactionActive = false;
-            }
-
-            @Override
-            public void setRollbackOnly() {
-                setRollbackOnly = true;
-            }
-
-            @Override
-            public boolean getRollbackOnly() {
-                return setRollbackOnly;
-            }
-
-            @Override
-            public boolean isActive() {
-                return transactionActive;
-            }
-        };
-    }
-
-    @Override
-    public RealmModel createRealm(String name) {
-        RealmModel realm = getDelegate().createRealm(name);
-        if (!cache.isEnabled()) return realm;
-        registerRealmInvalidation(realm.getId());
-        return realm;
-    }
-
-    @Override
-    public RealmModel createRealm(String id, String name) {
-        RealmModel realm =  getDelegate().createRealm(id, name);
-        if (!cache.isEnabled()) return realm;
-        registerRealmInvalidation(realm.getId());
-        return realm;
-    }
-
-    @Override
-    public RealmModel getRealm(String id) {
-        if (!cache.isEnabled()) return getDelegate().getRealm(id);
-        CachedRealm cached = cache.getCachedRealm(id);
-        if (cached == null) {
-            RealmModel model = getDelegate().getRealm(id);
-            if (model == null) return null;
-            if (realmInvalidations.contains(id)) return model;
-            cached = new CachedRealm(cache, this, model);
-            cache.addCachedRealm(cached);
-        } else if (realmInvalidations.contains(id)) {
-            return getDelegate().getRealm(id);
-        } else if (managedRealms.containsKey(id)) {
-            return managedRealms.get(id);
-        }
-        RealmAdapter adapter = new RealmAdapter(cached, this);
-        managedRealms.put(id, adapter);
-        return adapter;
-    }
-
-    @Override
-    public RealmModel getRealmByName(String name) {
-        if (!cache.isEnabled()) return getDelegate().getRealmByName(name);
-        CachedRealm cached = cache.getCachedRealmByName(name);
-        if (cached == null) {
-            RealmModel model = getDelegate().getRealmByName(name);
-            if (model == null) return null;
-            if (realmInvalidations.contains(model.getId())) return model;
-            cached = new CachedRealm(cache, this, model);
-            cache.addCachedRealm(cached);
-        } else if (realmInvalidations.contains(cached.getId())) {
-            return getDelegate().getRealmByName(name);
-        } else if (managedRealms.containsKey(cached.getId())) {
-            return managedRealms.get(cached.getId());
-        }
-        RealmAdapter adapter = new RealmAdapter(cached, this);
-        managedRealms.put(cached.getId(), adapter);
-        return adapter;
-    }
-
-    @Override
-    public List<RealmModel> getRealms() {
-        // Retrieve realms from backend
-        List<RealmModel> backendRealms = getDelegate().getRealms();
-
-        // Return cache delegates to ensure cache invalidated during write operations
-        List<RealmModel> cachedRealms = new LinkedList<RealmModel>();
-        for (RealmModel realm : backendRealms) {
-            RealmModel cached = getRealm(realm.getId());
-            cachedRealms.add(cached);
-        }
-        return cachedRealms;
-    }
-
-    @Override
-    public boolean removeRealm(String id) {
-        if (!cache.isEnabled()) return getDelegate().removeRealm(id);
-        cache.invalidateCachedRealmById(id);
-
-        RealmModel realm = getDelegate().getRealm(id);
-        Set<RoleModel> realmRoles = null;
-        if (realm != null) {
-            realmRoles = realm.getRoles();
-        }
-
-        boolean didIt = getDelegate().removeRealm(id);
-        realmInvalidations.add(id);
-
-        // TODO: Temporary workaround to invalidate cached realm roles
-        if (didIt && realmRoles != null) {
-            for (RoleModel role : realmRoles) {
-                roleInvalidations.add(role.getId());
-            }
-        }
-
-        return didIt;
-    }
-
-    @Override
-    public void close() {
-        if (delegate != null) delegate.close();
-    }
-
-    @Override
-    public RoleModel getRoleById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getRoleById(id, realm);
-        CachedRole cached = cache.getRole(id);
-        if (cached != null && !cached.getRealm().equals(realm.getId())) {
-            cached = null;
-        }
-
-        if (cached == null) {
-            RoleModel model = getDelegate().getRoleById(id, realm);
-            if (model == null) return null;
-            if (roleInvalidations.contains(id)) return model;
-            if (model.getContainer() instanceof ClientModel) {
-                cached = new CachedClientRole(((ClientModel) model.getContainer()).getId(), model, realm);
-            } else {
-                cached = new CachedRealmRole(model, realm);
-            }
-            cache.addCachedRole(cached);
-
-        } else if (roleInvalidations.contains(id)) {
-            return getDelegate().getRoleById(id, realm);
-        } else if (managedRoles.containsKey(id)) {
-            return managedRoles.get(id);
-        }
-        RoleAdapter adapter = new RoleAdapter(cached, cache, this, realm);
-        managedRoles.put(id, adapter);
-        return adapter;
-    }
-
-    @Override
-    public ClientModel getClientById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getClientById(id, realm);
-        CachedClient cached = cache.getApplication(id);
-        if (cached != null && !cached.getRealm().equals(realm.getId())) {
-            cached = null;
-        }
-
-        if (cached == null) {
-            ClientModel model = getDelegate().getClientById(id, realm);
-            if (model == null) return null;
-            if (appInvalidations.contains(id)) return model;
-            cached = new CachedClient(cache, getDelegate(), realm, model);
-            cache.addCachedClient(cached);
-        } else if (appInvalidations.contains(id)) {
-            return getDelegate().getClientById(id, realm);
-        } else if (managedApplications.containsKey(id)) {
-            return managedApplications.get(id);
-        }
-        ClientAdapter adapter = new ClientAdapter(realm, cached, this, cache);
-        managedApplications.put(id, adapter);
-        return adapter;
-    }
-
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.cache.entities.CachedClient;
+import org.keycloak.models.cache.entities.CachedClientRole;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedRealmRole;
+import org.keycloak.models.cache.entities.CachedRole;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DefaultCacheRealmProvider implements CacheRealmProvider {
+    protected RealmCache cache;
+    protected KeycloakSession session;
+    protected RealmProvider delegate;
+    protected boolean transactionActive;
+    protected boolean setRollbackOnly;
+
+    protected Set<String> realmInvalidations = new HashSet<String>();
+    protected Set<String> appInvalidations = new HashSet<String>();
+    protected Set<String> roleInvalidations = new HashSet<String>();
+    protected Map<String, RealmModel> managedRealms = new HashMap<String, RealmModel>();
+    protected Map<String, ClientModel> managedApplications = new HashMap<String, ClientModel>();
+    protected Map<String, RoleModel> managedRoles = new HashMap<String, RoleModel>();
+
+    protected boolean clearAll;
+
+    public DefaultCacheRealmProvider(RealmCache cache, KeycloakSession session) {
+        this.cache = cache;
+        this.session = session;
+
+        session.getTransaction().enlistAfterCompletion(getTransaction());
+    }
+
+    @Override
+    public MigrationModel getMigrationModel() {
+        return getDelegate().getMigrationModel();
+    }
+
+
+    @Override
+    public boolean isEnabled() {
+        return cache.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        cache.setEnabled(enabled);
+    }
+
+    @Override
+    public RealmProvider getDelegate() {
+        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
+        if (delegate != null) return delegate;
+        delegate = session.getProvider(RealmProvider.class);
+        return delegate;
+    }
+
+    @Override
+    public void registerRealmInvalidation(String id) {
+        realmInvalidations.add(id);
+    }
+
+    @Override
+    public void registerApplicationInvalidation(String id) {
+        appInvalidations.add(id);
+    }
+
+    @Override
+    public void registerRoleInvalidation(String id) {
+        roleInvalidations.add(id);
+    }
+
+    protected void runInvalidations() {
+        for (String id : realmInvalidations) {
+            cache.invalidateCachedRealmById(id);
+        }
+        for (String id : roleInvalidations) {
+            cache.invalidateRoleById(id);
+        }
+        for (String id : appInvalidations) {
+            cache.invalidateCachedApplicationById(id);
+        }
+    }
+
+    private KeycloakTransaction getTransaction() {
+        return new KeycloakTransaction() {
+            @Override
+            public void begin() {
+                transactionActive = true;
+            }
+
+            @Override
+            public void commit() {
+                if (delegate == null) return;
+                if (clearAll) {
+                    cache.clear();
+                }
+                runInvalidations();
+                transactionActive = false;
+            }
+
+            @Override
+            public void rollback() {
+                setRollbackOnly = true;
+                runInvalidations();
+                transactionActive = false;
+            }
+
+            @Override
+            public void setRollbackOnly() {
+                setRollbackOnly = true;
+            }
+
+            @Override
+            public boolean getRollbackOnly() {
+                return setRollbackOnly;
+            }
+
+            @Override
+            public boolean isActive() {
+                return transactionActive;
+            }
+        };
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        RealmModel realm = getDelegate().createRealm(name);
+        if (!cache.isEnabled()) return realm;
+        registerRealmInvalidation(realm.getId());
+        return realm;
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        RealmModel realm =  getDelegate().createRealm(id, name);
+        if (!cache.isEnabled()) return realm;
+        registerRealmInvalidation(realm.getId());
+        return realm;
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        if (!cache.isEnabled()) return getDelegate().getRealm(id);
+        CachedRealm cached = cache.getCachedRealm(id);
+        if (cached == null) {
+            RealmModel model = getDelegate().getRealm(id);
+            if (model == null) return null;
+            if (realmInvalidations.contains(id)) return model;
+            cached = new CachedRealm(cache, this, model);
+            cache.addCachedRealm(cached);
+        } else if (realmInvalidations.contains(id)) {
+            return getDelegate().getRealm(id);
+        } else if (managedRealms.containsKey(id)) {
+            return managedRealms.get(id);
+        }
+        RealmAdapter adapter = new RealmAdapter(cached, this);
+        managedRealms.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public RealmModel getRealmByName(String name) {
+        if (!cache.isEnabled()) return getDelegate().getRealmByName(name);
+        CachedRealm cached = cache.getCachedRealmByName(name);
+        if (cached == null) {
+            RealmModel model = getDelegate().getRealmByName(name);
+            if (model == null) return null;
+            if (realmInvalidations.contains(model.getId())) return model;
+            cached = new CachedRealm(cache, this, model);
+            cache.addCachedRealm(cached);
+        } else if (realmInvalidations.contains(cached.getId())) {
+            return getDelegate().getRealmByName(name);
+        } else if (managedRealms.containsKey(cached.getId())) {
+            return managedRealms.get(cached.getId());
+        }
+        RealmAdapter adapter = new RealmAdapter(cached, this);
+        managedRealms.put(cached.getId(), adapter);
+        return adapter;
+    }
+
+    @Override
+    public List<RealmModel> getRealms() {
+        // Retrieve realms from backend
+        List<RealmModel> backendRealms = getDelegate().getRealms();
+
+        // Return cache delegates to ensure cache invalidated during write operations
+        List<RealmModel> cachedRealms = new LinkedList<RealmModel>();
+        for (RealmModel realm : backendRealms) {
+            RealmModel cached = getRealm(realm.getId());
+            cachedRealms.add(cached);
+        }
+        return cachedRealms;
+    }
+
+    @Override
+    public boolean removeRealm(String id) {
+        if (!cache.isEnabled()) return getDelegate().removeRealm(id);
+        cache.invalidateCachedRealmById(id);
+
+        RealmModel realm = getDelegate().getRealm(id);
+        Set<RoleModel> realmRoles = null;
+        if (realm != null) {
+            realmRoles = realm.getRoles();
+        }
+
+        boolean didIt = getDelegate().removeRealm(id);
+        realmInvalidations.add(id);
+
+        // TODO: Temporary workaround to invalidate cached realm roles
+        if (didIt && realmRoles != null) {
+            for (RoleModel role : realmRoles) {
+                roleInvalidations.add(role.getId());
+            }
+        }
+
+        return didIt;
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) delegate.close();
+    }
+
+    @Override
+    public RoleModel getRoleById(String id, RealmModel realm) {
+        if (!cache.isEnabled()) return getDelegate().getRoleById(id, realm);
+        CachedRole cached = cache.getRole(id);
+        if (cached != null && !cached.getRealm().equals(realm.getId())) {
+            cached = null;
+        }
+
+        if (cached == null) {
+            RoleModel model = getDelegate().getRoleById(id, realm);
+            if (model == null) return null;
+            if (roleInvalidations.contains(id)) return model;
+            if (model.getContainer() instanceof ClientModel) {
+                cached = new CachedClientRole(((ClientModel) model.getContainer()).getId(), model, realm);
+            } else {
+                cached = new CachedRealmRole(model, realm);
+            }
+            cache.addCachedRole(cached);
+
+        } else if (roleInvalidations.contains(id)) {
+            return getDelegate().getRoleById(id, realm);
+        } else if (managedRoles.containsKey(id)) {
+            return managedRoles.get(id);
+        }
+        RoleAdapter adapter = new RoleAdapter(cached, cache, this, realm);
+        managedRoles.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public ClientModel getClientById(String id, RealmModel realm) {
+        if (!cache.isEnabled()) return getDelegate().getClientById(id, realm);
+        CachedClient cached = cache.getApplication(id);
+        if (cached != null && !cached.getRealm().equals(realm.getId())) {
+            cached = null;
+        }
+
+        if (cached == null) {
+            ClientModel model = getDelegate().getClientById(id, realm);
+            if (model == null) return null;
+            if (appInvalidations.contains(id)) return model;
+            cached = new CachedClient(cache, getDelegate(), realm, model);
+            cache.addCachedClient(cached);
+        } else if (appInvalidations.contains(id)) {
+            return getDelegate().getClientById(id, realm);
+        } else if (managedApplications.containsKey(id)) {
+            return managedApplications.get(id);
+        }
+        ClientAdapter adapter = new ClientAdapter(realm, cached, this, cache);
+        managedApplications.put(id, adapter);
+        return adapter;
+    }
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java
index d7fdbda..2f12c9f 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java
@@ -1,331 +1,331 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakTransaction;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.cache.entities.CachedUser;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DefaultCacheUserProvider implements CacheUserProvider {
-    protected UserCache cache;
-    protected KeycloakSession session;
-    protected UserProvider delegate;
-    protected boolean transactionActive;
-    protected boolean setRollbackOnly;
-
-    protected Map<String, String> userInvalidations = new HashMap<>();
-    protected Set<String> realmInvalidations = new HashSet<>();
-    protected Map<String, UserModel> managedUsers = new HashMap<>();
-
-    protected boolean clearAll;
-
-    public DefaultCacheUserProvider(UserCache cache, KeycloakSession session) {
-        this.cache = cache;
-        this.session = session;
-
-        session.getTransaction().enlistAfterCompletion(getTransaction());
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return cache.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        cache.setEnabled(enabled);
-    }
-
-    @Override
-    public UserProvider getDelegate() {
-        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
-        if (delegate != null) return delegate;
-        delegate = session.getProvider(UserProvider.class);
-        return delegate;
-    }
-
-    @Override
-    public void registerUserInvalidation(RealmModel realm, String id) {
-        userInvalidations.put(id, realm.getId());
-    }
-
-    protected void runInvalidations() {
-        for (Map.Entry<String, String> invalidation : userInvalidations.entrySet()) {
-            cache.invalidateCachedUserById(invalidation.getValue(), invalidation.getKey());
-        }
-        for (String realmId : realmInvalidations) {
-            cache.invalidateRealmUsers(realmId);
-        }
-    }
-
-    private KeycloakTransaction getTransaction() {
-        return new KeycloakTransaction() {
-            @Override
-            public void begin() {
-                transactionActive = true;
-            }
-
-            @Override
-            public void commit() {
-                if (delegate == null) return;
-                if (clearAll) {
-                    cache.clear();
-                }
-                runInvalidations();
-                transactionActive = false;
-            }
-
-            @Override
-            public void rollback() {
-                setRollbackOnly = true;
-                runInvalidations();
-                transactionActive = false;
-            }
-
-            @Override
-            public void setRollbackOnly() {
-                setRollbackOnly = true;
-            }
-
-            @Override
-            public boolean getRollbackOnly() {
-                return setRollbackOnly;
-            }
-
-            @Override
-            public boolean isActive() {
-                return transactionActive;
-            }
-        };
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getUserById(id, realm);
-        if (realmInvalidations.contains(realm.getId())) {
-            return getDelegate().getUserById(id, realm);
-        }
-        if (userInvalidations.containsKey(id)) {
-            return getDelegate().getUserById(id, realm);
-        }
-
-        CachedUser cached = cache.getCachedUser(realm.getId(), id);
-        if (cached == null) {
-            UserModel model = getDelegate().getUserById(id, realm);
-            if (model == null) return null;
-            if (managedUsers.containsKey(id)) return managedUsers.get(id);
-            if (userInvalidations.containsKey(id)) return model;
-            cached = new CachedUser(realm, model);
-            cache.addCachedUser(realm.getId(), cached);
-        } else if (managedUsers.containsKey(id)) {
-            return managedUsers.get(id);
-        }
-        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
-        managedUsers.put(id, adapter);
-        return adapter;
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        
-        username = username.toLowerCase();
-        
-        if (!cache.isEnabled()) return getDelegate().getUserByUsername(username, realm);
-        if (realmInvalidations.contains(realm.getId())) {
-            return getDelegate().getUserByUsername(username, realm);
-        }
-        CachedUser cached = cache.getCachedUserByUsername(realm.getId(), username);
-        if (cached == null) {
-            UserModel model = getDelegate().getUserByUsername(username, realm);
-            if (model == null) return null;
-            if (managedUsers.containsKey(model.getId())) return managedUsers.get(model.getId());
-            if (userInvalidations.containsKey(model.getId())) return model;
-            cached = new CachedUser(realm, model);
-            cache.addCachedUser(realm.getId(), cached);
-        } else if (userInvalidations.containsKey(cached.getId())) {
-            return getDelegate().getUserById(cached.getId(), realm);
-        } else if (managedUsers.containsKey(cached.getId())) {
-            return managedUsers.get(cached.getId());
-        }
-        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
-        managedUsers.put(cached.getId(), adapter);
-        return adapter;
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        
-        email = email.toLowerCase();
-        
-        if (!cache.isEnabled()) return getDelegate().getUserByEmail(email, realm);
-        if (realmInvalidations.contains(realm.getId())) {
-            return getDelegate().getUserByEmail(email, realm);
-        }
-        CachedUser cached = cache.getCachedUserByEmail(realm.getId(), email);
-        if (cached == null) {
-            UserModel model = getDelegate().getUserByEmail(email, realm);
-            if (model == null) return null;
-            if (userInvalidations.containsKey(model.getId())) return model;
-            cached = new CachedUser(realm, model);
-            cache.addCachedUser(realm.getId(), cached);
-        } else if (userInvalidations.containsKey(cached.getId())) {
-            return getDelegate().getUserByEmail(email, realm);
-        } else if (managedUsers.containsKey(cached.getId())) {
-            return managedUsers.get(cached.getId());
-        }
-        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
-        managedUsers.put(cached.getId(), adapter);
-        return adapter;
-    }
-
-    @Override
-    public void close() {
-        if (delegate != null) delegate.close();
-    }
-
-    @Override
-    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
-        return getDelegate().getUserByFederatedIdentity(socialLink, realm);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return getDelegate().getUsers(realm);
-    }
-
-    @Override
-    public int getUsersCount(RealmModel realm) {
-        return getDelegate().getUsersCount(realm);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().getUsers(realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return getDelegate().searchForUser(search, realm);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().searchForUser(search, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return getDelegate().searchForUserByAttributes(attributes, realm);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
-        return getDelegate().getFederatedIdentities(user, realm);
-    }
-
-    @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        return getDelegate().getFederatedIdentity(user, socialProvider, realm);
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
-        UserModel user = getDelegate().addUser(realm, id, username, addDefaultRoles, addDefaultRoles);
-        managedUsers.put(user.getId(), user);
-        return user;
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String username) {
-        UserModel user = getDelegate().addUser(realm, username);
-        managedUsers.put(user.getId(), user);
-        return user;
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        if (!cache.isEnabled()) return getDelegate().removeUser(realm, user);
-        registerUserInvalidation(realm, user.getId());
-        return getDelegate().removeUser(realm, user);
-    }
-
-    @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
-        getDelegate().addFederatedIdentity(realm, user, socialLink);
-    }
-
-    @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        getDelegate().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
-    }
-
-    @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
-        return getDelegate().removeFederatedIdentity(realm, user, socialProvider);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        return getDelegate().validCredentials(realm, user, input);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return getDelegate().validCredentials(realm, user, input);
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
-        return getDelegate().validCredentials(realm, input);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        realmInvalidations.add(realm.getId());
-        getDelegate().preRemove(realm);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        getDelegate().preRemove(realm, role);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
-        realmInvalidations.add(realm.getId()); // easier to just invalidate whole realm
-        getDelegate().preRemove(realm, link);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, ClientModel client) {
-        getDelegate().preRemove(realm, client);
-    }
-
-    @Override
-    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
-        getDelegate().preRemove(client, protocolMapper);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.cache.entities.CachedUser;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DefaultCacheUserProvider implements CacheUserProvider {
+    protected UserCache cache;
+    protected KeycloakSession session;
+    protected UserProvider delegate;
+    protected boolean transactionActive;
+    protected boolean setRollbackOnly;
+
+    protected Map<String, String> userInvalidations = new HashMap<>();
+    protected Set<String> realmInvalidations = new HashSet<>();
+    protected Map<String, UserModel> managedUsers = new HashMap<>();
+
+    protected boolean clearAll;
+
+    public DefaultCacheUserProvider(UserCache cache, KeycloakSession session) {
+        this.cache = cache;
+        this.session = session;
+
+        session.getTransaction().enlistAfterCompletion(getTransaction());
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return cache.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        cache.setEnabled(enabled);
+    }
+
+    @Override
+    public UserProvider getDelegate() {
+        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
+        if (delegate != null) return delegate;
+        delegate = session.getProvider(UserProvider.class);
+        return delegate;
+    }
+
+    @Override
+    public void registerUserInvalidation(RealmModel realm, String id) {
+        userInvalidations.put(id, realm.getId());
+    }
+
+    protected void runInvalidations() {
+        for (Map.Entry<String, String> invalidation : userInvalidations.entrySet()) {
+            cache.invalidateCachedUserById(invalidation.getValue(), invalidation.getKey());
+        }
+        for (String realmId : realmInvalidations) {
+            cache.invalidateRealmUsers(realmId);
+        }
+    }
+
+    private KeycloakTransaction getTransaction() {
+        return new KeycloakTransaction() {
+            @Override
+            public void begin() {
+                transactionActive = true;
+            }
+
+            @Override
+            public void commit() {
+                if (delegate == null) return;
+                if (clearAll) {
+                    cache.clear();
+                }
+                runInvalidations();
+                transactionActive = false;
+            }
+
+            @Override
+            public void rollback() {
+                setRollbackOnly = true;
+                runInvalidations();
+                transactionActive = false;
+            }
+
+            @Override
+            public void setRollbackOnly() {
+                setRollbackOnly = true;
+            }
+
+            @Override
+            public boolean getRollbackOnly() {
+                return setRollbackOnly;
+            }
+
+            @Override
+            public boolean isActive() {
+                return transactionActive;
+            }
+        };
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        if (!cache.isEnabled()) return getDelegate().getUserById(id, realm);
+        if (realmInvalidations.contains(realm.getId())) {
+            return getDelegate().getUserById(id, realm);
+        }
+        if (userInvalidations.containsKey(id)) {
+            return getDelegate().getUserById(id, realm);
+        }
+
+        CachedUser cached = cache.getCachedUser(realm.getId(), id);
+        if (cached == null) {
+            UserModel model = getDelegate().getUserById(id, realm);
+            if (model == null) return null;
+            if (managedUsers.containsKey(id)) return managedUsers.get(id);
+            if (userInvalidations.containsKey(id)) return model;
+            cached = new CachedUser(realm, model);
+            cache.addCachedUser(realm.getId(), cached);
+        } else if (managedUsers.containsKey(id)) {
+            return managedUsers.get(id);
+        }
+        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
+        managedUsers.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        
+        username = username.toLowerCase();
+        
+        if (!cache.isEnabled()) return getDelegate().getUserByUsername(username, realm);
+        if (realmInvalidations.contains(realm.getId())) {
+            return getDelegate().getUserByUsername(username, realm);
+        }
+        CachedUser cached = cache.getCachedUserByUsername(realm.getId(), username);
+        if (cached == null) {
+            UserModel model = getDelegate().getUserByUsername(username, realm);
+            if (model == null) return null;
+            if (managedUsers.containsKey(model.getId())) return managedUsers.get(model.getId());
+            if (userInvalidations.containsKey(model.getId())) return model;
+            cached = new CachedUser(realm, model);
+            cache.addCachedUser(realm.getId(), cached);
+        } else if (userInvalidations.containsKey(cached.getId())) {
+            return getDelegate().getUserById(cached.getId(), realm);
+        } else if (managedUsers.containsKey(cached.getId())) {
+            return managedUsers.get(cached.getId());
+        }
+        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
+        managedUsers.put(cached.getId(), adapter);
+        return adapter;
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        
+        email = email.toLowerCase();
+        
+        if (!cache.isEnabled()) return getDelegate().getUserByEmail(email, realm);
+        if (realmInvalidations.contains(realm.getId())) {
+            return getDelegate().getUserByEmail(email, realm);
+        }
+        CachedUser cached = cache.getCachedUserByEmail(realm.getId(), email);
+        if (cached == null) {
+            UserModel model = getDelegate().getUserByEmail(email, realm);
+            if (model == null) return null;
+            if (userInvalidations.containsKey(model.getId())) return model;
+            cached = new CachedUser(realm, model);
+            cache.addCachedUser(realm.getId(), cached);
+        } else if (userInvalidations.containsKey(cached.getId())) {
+            return getDelegate().getUserByEmail(email, realm);
+        } else if (managedUsers.containsKey(cached.getId())) {
+            return managedUsers.get(cached.getId());
+        }
+        UserAdapter adapter = new UserAdapter(cached, this, session, realm);
+        managedUsers.put(cached.getId(), adapter);
+        return adapter;
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) delegate.close();
+    }
+
+    @Override
+    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
+        return getDelegate().getUserByFederatedIdentity(socialLink, realm);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getDelegate().getUsers(realm);
+    }
+
+    @Override
+    public int getUsersCount(RealmModel realm) {
+        return getDelegate().getUsersCount(realm);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().getUsers(realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return getDelegate().searchForUser(search, realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().searchForUser(search, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return getDelegate().searchForUserByAttributes(attributes, realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
+        return getDelegate().getFederatedIdentities(user, realm);
+    }
+
+    @Override
+    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
+        return getDelegate().getFederatedIdentity(user, socialProvider, realm);
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+        UserModel user = getDelegate().addUser(realm, id, username, addDefaultRoles, addDefaultRoles);
+        managedUsers.put(user.getId(), user);
+        return user;
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String username) {
+        UserModel user = getDelegate().addUser(realm, username);
+        managedUsers.put(user.getId(), user);
+        return user;
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        if (!cache.isEnabled()) return getDelegate().removeUser(realm, user);
+        registerUserInvalidation(realm, user.getId());
+        return getDelegate().removeUser(realm, user);
+    }
+
+    @Override
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
+        getDelegate().addFederatedIdentity(realm, user, socialLink);
+    }
+
+    @Override
+    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+        getDelegate().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
+    }
+
+    @Override
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
+        return getDelegate().removeFederatedIdentity(realm, user, socialProvider);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        return getDelegate().validCredentials(realm, user, input);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return getDelegate().validCredentials(realm, user, input);
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
+        return getDelegate().validCredentials(realm, input);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        realmInvalidations.add(realm.getId());
+        getDelegate().preRemove(realm);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        getDelegate().preRemove(realm, role);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
+        realmInvalidations.add(realm.getId()); // easier to just invalidate whole realm
+        getDelegate().preRemove(realm, link);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, ClientModel client) {
+        getDelegate().preRemove(realm, client);
+    }
+
+    @Override
+    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
+        getDelegate().preRemove(client, protocolMapper);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
index 15bc151..1133bdb 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
@@ -1,192 +1,192 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.cache.RealmCache;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedClient implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String id;
-    private String clientId;
-    private String name;
-    private String realm;
-    private Set<String> redirectUris = new HashSet<String>();
-    private boolean enabled;
-    private String secret;
-    private String protocol;
-    private Map<String, String> attributes = new HashMap<String, String>();
-    private boolean publicClient;
-    private boolean fullScopeAllowed;
-    private boolean directGrantsOnly;
-    private boolean frontchannelLogout;
-    private int notBefore;
-    private Set<String> scope = new HashSet<String>();
-    private Set<String> webOrigins = new HashSet<String>();
-    private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
-    private boolean surrogateAuthRequired;
-    private String managementUrl;
-    private String baseUrl;
-    private List<String> defaultRoles = new LinkedList<String>();
-    private boolean bearerOnly;
-    private boolean consentRequired;
-    private Map<String, String> roles = new HashMap<String, String>();
-    private int nodeReRegistrationTimeout;
-    private Map<String, Integer> registeredNodes;
-
-    public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
-        id = model.getId();
-        secret = model.getSecret();
-        clientId = model.getClientId();
-        name = model.getName();
-        this.realm = realm.getId();
-        enabled = model.isEnabled();
-        protocol = model.getProtocol();
-        attributes.putAll(model.getAttributes());
-        notBefore = model.getNotBefore();
-        directGrantsOnly = model.isDirectGrantsOnly();
-        frontchannelLogout = model.isFrontchannelLogout();
-        publicClient = model.isPublicClient();
-        fullScopeAllowed = model.isFullScopeAllowed();
-        redirectUris.addAll(model.getRedirectUris());
-        webOrigins.addAll(model.getWebOrigins());
-        for (RoleModel role : model.getScopeMappings())  {
-            scope.add(role.getId());
-        }
-        for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
-            this.protocolMappers.add(mapper);
-        }
-        surrogateAuthRequired = model.isSurrogateAuthRequired();
-        managementUrl = model.getManagementUrl();
-        baseUrl = model.getBaseUrl();
-        defaultRoles.addAll(model.getDefaultRoles());
-        bearerOnly = model.isBearerOnly();
-        consentRequired = model.isConsentRequired();
-        for (RoleModel role : model.getRoles()) {
-            roles.put(role.getName(), role.getId());
-            cache.addCachedRole(new CachedClientRole(id, role, realm));
-        }
-
-        nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout();
-        registeredNodes = new TreeMap<String, Integer>(model.getRegisteredNodes());
-    }
-    public String getId() {
-        return id;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public Set<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public boolean isDirectGrantsOnly() {
-        return directGrantsOnly;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public Set<String> getScope() {
-        return scope;
-    }
-
-    public Set<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public boolean isSurrogateAuthRequired() {
-        return surrogateAuthRequired;
-    }
-
-    public String getManagementUrl() {
-        return managementUrl;
-    }
-
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public List<String> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public Map<String, String> getRoles() {
-        return roles;
-    }
-
-    public int getNodeReRegistrationTimeout() {
-        return nodeReRegistrationTimeout;
-    }
-
-    public Map<String, Integer> getRegisteredNodes() {
-        return registeredNodes;
-    }
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.cache.RealmCache;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedClient implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+    private String clientId;
+    private String name;
+    private String realm;
+    private Set<String> redirectUris = new HashSet<String>();
+    private boolean enabled;
+    private String secret;
+    private String protocol;
+    private Map<String, String> attributes = new HashMap<String, String>();
+    private boolean publicClient;
+    private boolean fullScopeAllowed;
+    private boolean directGrantsOnly;
+    private boolean frontchannelLogout;
+    private int notBefore;
+    private Set<String> scope = new HashSet<String>();
+    private Set<String> webOrigins = new HashSet<String>();
+    private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
+    private boolean surrogateAuthRequired;
+    private String managementUrl;
+    private String baseUrl;
+    private List<String> defaultRoles = new LinkedList<String>();
+    private boolean bearerOnly;
+    private boolean consentRequired;
+    private Map<String, String> roles = new HashMap<String, String>();
+    private int nodeReRegistrationTimeout;
+    private Map<String, Integer> registeredNodes;
+
+    public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
+        id = model.getId();
+        secret = model.getSecret();
+        clientId = model.getClientId();
+        name = model.getName();
+        this.realm = realm.getId();
+        enabled = model.isEnabled();
+        protocol = model.getProtocol();
+        attributes.putAll(model.getAttributes());
+        notBefore = model.getNotBefore();
+        directGrantsOnly = model.isDirectGrantsOnly();
+        frontchannelLogout = model.isFrontchannelLogout();
+        publicClient = model.isPublicClient();
+        fullScopeAllowed = model.isFullScopeAllowed();
+        redirectUris.addAll(model.getRedirectUris());
+        webOrigins.addAll(model.getWebOrigins());
+        for (RoleModel role : model.getScopeMappings())  {
+            scope.add(role.getId());
+        }
+        for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
+            this.protocolMappers.add(mapper);
+        }
+        surrogateAuthRequired = model.isSurrogateAuthRequired();
+        managementUrl = model.getManagementUrl();
+        baseUrl = model.getBaseUrl();
+        defaultRoles.addAll(model.getDefaultRoles());
+        bearerOnly = model.isBearerOnly();
+        consentRequired = model.isConsentRequired();
+        for (RoleModel role : model.getRoles()) {
+            roles.put(role.getName(), role.getId());
+            cache.addCachedRole(new CachedClientRole(id, role, realm));
+        }
+
+        nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout();
+        registeredNodes = new TreeMap<String, Integer>(model.getRegisteredNodes());
+    }
+    public String getId() {
+        return id;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public Set<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public Set<String> getScope() {
+        return scope;
+    }
+
+    public Set<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public String getManagementUrl() {
+        return managementUrl;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public List<String> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public Map<String, String> getRoles() {
+        return roles;
+    }
+
+    public int getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClientRole.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClientRole.java
index 1d2ad72..da97671 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClientRole.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClientRole.java
@@ -1,25 +1,25 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedClientRole extends CachedRole {
-
-    private static final long serialVersionUID = 1L;
-
-    private final String idClient;
-
-    public CachedClientRole(String idClient, RoleModel model, RealmModel realm) {
-        super(model, realm);
-        this.idClient = idClient;
-
-    }
-
-    public String getIdClient() {
-        return idClient;
-    }
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedClientRole extends CachedRole {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String idClient;
+
+    public CachedClientRole(String idClient, RoleModel model, RealmModel realm) {
+        super(model, realm);
+        this.idClient = idClient;
+
+    }
+
+    public String getIdClient() {
+        return idClient;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealmRole.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealmRole.java
index e34478e..3435a8f 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealmRole.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealmRole.java
@@ -1,18 +1,18 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedRealmRole extends CachedRole {
-
-
-    public CachedRealmRole(RoleModel model, RealmModel realm) {
-        super(model, realm);
-
-    }
-
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedRealmRole extends CachedRole {
+
+
+    public CachedRealmRole(RoleModel model, RealmModel realm) {
+        super(model, realm);
+
+    }
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRole.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRole.java
index 407b9fe..3fb7332 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRole.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRole.java
@@ -1,62 +1,62 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedRole implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    final protected String id;
-    final protected String name;
-    final protected String realm;
-    final protected String description;
-    final protected boolean composite;
-    final protected Set<String> composites = new HashSet<String>();
-
-    public CachedRole(RoleModel model, RealmModel realm) {
-        composite = model.isComposite();
-        description = model.getDescription();
-        id = model.getId();
-        name = model.getName();
-        this.realm = realm.getId();
-        if (composite) {
-            for (RoleModel child : model.getComposites()) {
-                composites.add(child.getId());
-            }
-        }
-
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public boolean isComposite() {
-        return composite;
-    }
-
-    public Set<String> getComposites() {
-        return composites;
-    }
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedRole implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    final protected String id;
+    final protected String name;
+    final protected String realm;
+    final protected String description;
+    final protected boolean composite;
+    final protected Set<String> composites = new HashSet<String>();
+
+    public CachedRole(RoleModel model, RealmModel realm) {
+        composite = model.isComposite();
+        description = model.getDescription();
+        id = model.getId();
+        name = model.getName();
+        this.realm = realm.getId();
+        if (composite) {
+            for (RoleModel child : model.getComposites()) {
+                composites.add(child.getId());
+            }
+        }
+
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public boolean isComposite() {
+        return composite;
+    }
+
+    public Set<String> getComposites() {
+        return composites;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
index e8f54db..3d1395b 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
@@ -1,117 +1,117 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.util.MultivaluedHashMap;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedUser implements Serializable {
-    private String id;
-    private String realm;
-    private String username;
-    private Long createdTimestamp;
-    private String firstName;
-    private String lastName;
-    private String email;
-    private boolean emailVerified;
-    private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
-    private boolean enabled;
-    private boolean totp;
-    private String federationLink;
-    private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
-    private Set<String> requiredActions = new HashSet<>();
-    private Set<String> roleMappings = new HashSet<String>();
-
-    public CachedUser(RealmModel realm, UserModel user) {
-        this.id = user.getId();
-        this.realm = realm.getId();
-        this.username = user.getUsername();
-        this.createdTimestamp = user.getCreatedTimestamp();
-        this.firstName = user.getFirstName();
-        this.lastName = user.getLastName();
-        this.attributes.putAll(user.getAttributes());
-        this.email = user.getEmail();
-        this.emailVerified = user.isEmailVerified();
-        this.credentials.addAll(user.getCredentialsDirectly());
-        this.enabled = user.isEnabled();
-        this.totp = user.isTotp();
-        this.federationLink = user.getFederationLink();
-        this.requiredActions.addAll(user.getRequiredActions());
-        for (RoleModel role : user.getRoleMappings()) {
-            roleMappings.add(role.getId());
-        }
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public String getRealm() {
-        return realm;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public Long getCreatedTimestamp() {
-        return createdTimestamp;
-    }
-
-    public String getFirstName() {
-        return firstName;
-    }
-
-    public String getLastName() {
-        return lastName;
-    }
-
-    public String getEmail() {
-        return email;
-    }
-
-    public boolean isEmailVerified() {
-        return emailVerified;
-    }
-
-    public List<UserCredentialValueModel> getCredentials() {
-        return credentials;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public boolean isTotp() {
-        return totp;
-    }
-
-    public MultivaluedHashMap<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public Set<String> getRequiredActions() {
-        return requiredActions;
-    }
-
-    public Set<String> getRoleMappings() {
-        return roleMappings;
-    }
-
-    public String getFederationLink() {
-        return federationLink;
-    }
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.util.MultivaluedHashMap;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedUser implements Serializable {
+    private String id;
+    private String realm;
+    private String username;
+    private Long createdTimestamp;
+    private String firstName;
+    private String lastName;
+    private String email;
+    private boolean emailVerified;
+    private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
+    private boolean enabled;
+    private boolean totp;
+    private String federationLink;
+    private MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
+    private Set<String> requiredActions = new HashSet<>();
+    private Set<String> roleMappings = new HashSet<String>();
+
+    public CachedUser(RealmModel realm, UserModel user) {
+        this.id = user.getId();
+        this.realm = realm.getId();
+        this.username = user.getUsername();
+        this.createdTimestamp = user.getCreatedTimestamp();
+        this.firstName = user.getFirstName();
+        this.lastName = user.getLastName();
+        this.attributes.putAll(user.getAttributes());
+        this.email = user.getEmail();
+        this.emailVerified = user.isEmailVerified();
+        this.credentials.addAll(user.getCredentialsDirectly());
+        this.enabled = user.isEnabled();
+        this.totp = user.isTotp();
+        this.federationLink = user.getFederationLink();
+        this.requiredActions.addAll(user.getRequiredActions());
+        for (RoleModel role : user.getRoleMappings()) {
+            roleMappings.add(role.getId());
+        }
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public Long getCreatedTimestamp() {
+        return createdTimestamp;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public boolean isEmailVerified() {
+        return emailVerified;
+    }
+
+    public List<UserCredentialValueModel> getCredentials() {
+        return credentials;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isTotp() {
+        return totp;
+    }
+
+    public MultivaluedHashMap<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public Set<String> getRequiredActions() {
+        return requiredActions;
+    }
+
+    public Set<String> getRoleMappings() {
+        return roleMappings;
+    }
+
+    public String getFederationLink() {
+        return federationLink;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheRealmProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheRealmProviderFactory.java
index a8ceada..db1faae 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheRealmProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheRealmProviderFactory.java
@@ -1,39 +1,39 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MemoryCacheRealmProviderFactory implements CacheRealmProviderFactory {
-    protected RealmCache cache = new MemoryRealmCache();
-
-    @Override
-    public CacheRealmProvider create(KeycloakSession session) {
-        return new DefaultCacheRealmProvider(cache, session);
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        config.get("");
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public String getId() {
-        return "mem";
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MemoryCacheRealmProviderFactory implements CacheRealmProviderFactory {
+    protected RealmCache cache = new MemoryRealmCache();
+
+    @Override
+    public CacheRealmProvider create(KeycloakSession session) {
+        return new DefaultCacheRealmProvider(cache, session);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        config.get("");
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getId() {
+        return "mem";
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheUserProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheUserProviderFactory.java
index bf1b4d2..ff58e66 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheUserProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryCacheUserProviderFactory.java
@@ -1,41 +1,41 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MemoryCacheUserProviderFactory implements CacheUserProviderFactory {
-    protected MemoryUserCache cache;
-
-    @Override
-    public CacheUserProvider create(KeycloakSession session) {
-        return new DefaultCacheUserProvider(cache, session);
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        config.get("");
-        cache = new MemoryUserCache();
-        int size = config.getInt("maxSize", 10000);
-        cache.setMaxUserCacheSize(size);
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public String getId() {
-        return "mem";
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MemoryCacheUserProviderFactory implements CacheUserProviderFactory {
+    protected MemoryUserCache cache;
+
+    @Override
+    public CacheUserProvider create(KeycloakSession session) {
+        return new DefaultCacheUserProvider(cache, session);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        config.get("");
+        cache = new MemoryUserCache();
+        int size = config.getInt("maxSize", 10000);
+        cache.setMaxUserCacheSize(size);
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getId() {
+        return "mem";
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
index 3b04670..4e6f483 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
@@ -1,122 +1,122 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.cache.entities.CachedClient;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.entities.CachedRole;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MemoryRealmCache implements RealmCache {
-
-    protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
-    protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
-    protected ConcurrentHashMap<String, CachedClient> applicationCache = new ConcurrentHashMap<String, CachedClient>();
-    protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
-    protected volatile boolean enabled = true;
-
-    @Override
-    public void clear() {
-        realmCache.clear();
-        realmCacheByName.clear();
-        applicationCache.clear();
-        roleCache.clear();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        clear();
-        this.enabled = enabled;
-        clear();
-    }
-
-    @Override
-    public CachedRealm getCachedRealm(String id) {
-        if (!enabled) return null;
-        return realmCache.get(id);
-    }
-
-    @Override
-    public void invalidateCachedRealm(CachedRealm realm) {
-        realmCache.remove(realm.getId());
-        realmCacheByName.remove(realm.getName());
-    }
-
-    @Override
-    public void invalidateCachedRealmById(String id) {
-        CachedRealm cached = realmCache.remove(id);
-        if (cached != null) realmCacheByName.remove(cached.getName());
-    }
-
-
-    @Override
-    public void addCachedRealm(CachedRealm realm) {
-        if (!enabled) return;
-        realmCache.put(realm.getId(), realm);
-        realmCacheByName.put(realm.getName(), realm);
-
-    }
-
-    @Override
-    public CachedRealm getCachedRealmByName(String name) {
-        if (!enabled) return null;
-        return realmCacheByName.get(name);
-    }
-
-    @Override
-    public CachedClient getApplication(String id) {
-        if (!enabled) return null;
-        return applicationCache.get(id);
-    }
-
-    @Override
-    public void invalidateApplication(CachedClient app) {
-        applicationCache.remove(app.getId());
-    }
-
-    @Override
-    public void addCachedClient(CachedClient app) {
-        if (!enabled) return;
-        applicationCache.put(app.getId(), app);
-    }
-
-    @Override
-    public void invalidateCachedApplicationById(String id) {
-        applicationCache.remove(id);
-    }
-
-    @Override
-    public CachedRole getRole(String id) {
-        if (!enabled) return null;
-        return roleCache.get(id);
-    }
-
-    @Override
-    public void invalidateRole(CachedRole role) {
-        roleCache.remove(role);
-    }
-
-    @Override
-    public void invalidateRoleById(String id) {
-        roleCache.remove(id);
-    }
-
-    @Override
-    public void addCachedRole(CachedRole role) {
-        if (!enabled) return;
-        roleCache.put(role.getId(), role);
-    }
-
-    @Override
-    public void invalidateCachedRoleById(String id) {
-        roleCache.remove(id);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.cache.entities.CachedClient;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedRole;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MemoryRealmCache implements RealmCache {
+
+    protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
+    protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
+    protected ConcurrentHashMap<String, CachedClient> applicationCache = new ConcurrentHashMap<String, CachedClient>();
+    protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
+    protected volatile boolean enabled = true;
+
+    @Override
+    public void clear() {
+        realmCache.clear();
+        realmCacheByName.clear();
+        applicationCache.clear();
+        roleCache.clear();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        clear();
+        this.enabled = enabled;
+        clear();
+    }
+
+    @Override
+    public CachedRealm getCachedRealm(String id) {
+        if (!enabled) return null;
+        return realmCache.get(id);
+    }
+
+    @Override
+    public void invalidateCachedRealm(CachedRealm realm) {
+        realmCache.remove(realm.getId());
+        realmCacheByName.remove(realm.getName());
+    }
+
+    @Override
+    public void invalidateCachedRealmById(String id) {
+        CachedRealm cached = realmCache.remove(id);
+        if (cached != null) realmCacheByName.remove(cached.getName());
+    }
+
+
+    @Override
+    public void addCachedRealm(CachedRealm realm) {
+        if (!enabled) return;
+        realmCache.put(realm.getId(), realm);
+        realmCacheByName.put(realm.getName(), realm);
+
+    }
+
+    @Override
+    public CachedRealm getCachedRealmByName(String name) {
+        if (!enabled) return null;
+        return realmCacheByName.get(name);
+    }
+
+    @Override
+    public CachedClient getApplication(String id) {
+        if (!enabled) return null;
+        return applicationCache.get(id);
+    }
+
+    @Override
+    public void invalidateApplication(CachedClient app) {
+        applicationCache.remove(app.getId());
+    }
+
+    @Override
+    public void addCachedClient(CachedClient app) {
+        if (!enabled) return;
+        applicationCache.put(app.getId(), app);
+    }
+
+    @Override
+    public void invalidateCachedApplicationById(String id) {
+        applicationCache.remove(id);
+    }
+
+    @Override
+    public CachedRole getRole(String id) {
+        if (!enabled) return null;
+        return roleCache.get(id);
+    }
+
+    @Override
+    public void invalidateRole(CachedRole role) {
+        roleCache.remove(role);
+    }
+
+    @Override
+    public void invalidateRoleById(String id) {
+        roleCache.remove(id);
+    }
+
+    @Override
+    public void addCachedRole(CachedRole role) {
+        if (!enabled) return;
+        roleCache.put(role.getId(), role);
+    }
+
+    @Override
+    public void invalidateCachedRoleById(String id) {
+        roleCache.remove(id);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java
index dcbf2c9..da71342 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java
@@ -1,158 +1,158 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.cache.entities.CachedUser;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MemoryUserCache implements UserCache {
-
-    protected int maxUserCacheSize = 10000;
-    protected volatile boolean enabled = true;
-
-
-    protected class RealmUsers {
-        protected class LRUCache extends LinkedHashMap<String, CachedUser> {
-            public LRUCache() {
-                super(1000, 1.1F, true);
-            }
-
-            @Override
-            public CachedUser put(String key, CachedUser value) {
-                if (value.getUsername() != null) {
-                    usersByUsername.put(value.getUsername(), value);
-                }
-                if (value.getEmail() != null) {
-                    usersByEmail.put(value.getEmail(), value);
-                }
-                return super.put(key, value);
-            }
-
-            @Override
-            public CachedUser remove(Object key) {
-                CachedUser user = super.remove(key);
-                if (user == null) return null;
-                removeUser(user);
-                return user;
-            }
-
-            @Override
-            public void clear() {
-                super.clear();
-                usersByUsername.clear();
-                usersByEmail.clear();
-            }
-
-            @Override
-            protected boolean removeEldestEntry(Map.Entry<String, CachedUser> eldest) {
-                boolean evict = size() > maxUserCacheSize;
-                if (evict) {
-                    removeUser(eldest.getValue());
-                }
-                return evict;
-            }
-
-            private void removeUser(CachedUser value) {
-                if (value.getUsername() != null) usersByUsername.remove(value.getUsername());
-                if (value.getEmail() != null) usersByEmail.remove(value.getEmail());
-            }
-        }
-
-        protected Map<String, CachedUser> usersById = Collections.synchronizedMap(new LRUCache());
-        protected Map<String, CachedUser> usersByUsername = new ConcurrentHashMap<String, CachedUser>();
-        protected Map<String, CachedUser> usersByEmail = new ConcurrentHashMap<String, CachedUser>();
-
-    }
-
-    protected ConcurrentHashMap<String, RealmUsers> realmUsers = new ConcurrentHashMap<String, RealmUsers>();
-
-    public int getMaxUserCacheSize() {
-        return maxUserCacheSize;
-    }
-
-    public void setMaxUserCacheSize(int maxUserCacheSize) {
-        this.maxUserCacheSize = maxUserCacheSize;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        clear();
-        this.enabled = enabled;
-        clear();
-    }
-
-    @Override
-    public CachedUser getCachedUser(String realmId, String id) {
-        if (realmId == null || id == null) return null;
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) return null;
-        return users.usersById.get(id);
-    }
-
-    @Override
-    public void invalidateCachedUser(String realmId, CachedUser user) {
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) return;
-        users.usersById.remove(user.getId());
-    }
-
-    @Override
-    public void invalidateCachedUserById(String realmId, String id) {
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) return;
-        users.usersById.remove(id);
-    }
-
-    @Override
-    public void addCachedUser(String realmId, CachedUser user) {
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) {
-            users = new RealmUsers();
-            realmUsers.put(realmId, users);
-        }
-        users.usersById.put(user.getId(), user);
-    }
-
-    @Override
-    public CachedUser getCachedUserByUsername(String realmId, String name) {
-        if (realmId == null || name == null) return null;
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) return null;
-        CachedUser user = users.usersByUsername.get(name);
-        if (user == null) return null;
-        users.usersById.get(user.getId()); // refresh cache entry age
-        return user;
-    }
-
-    @Override
-    public CachedUser getCachedUserByEmail(String realmId, String email) {
-        if (realmId == null || email == null) return null;
-        RealmUsers users = realmUsers.get(realmId);
-        if (users == null) return null;
-        CachedUser user = users.usersByEmail.get(email);
-        if (user == null) return null;
-        users.usersById.get(user.getId()); // refresh cache entry age
-        return user;
-    }
-
-    @Override
-    public void invalidateRealmUsers(String realmId) {
-        realmUsers.remove(realmId);
-    }
-
-    @Override
-    public void clear() {
-        realmUsers.clear();
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.cache.entities.CachedUser;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MemoryUserCache implements UserCache {
+
+    protected int maxUserCacheSize = 10000;
+    protected volatile boolean enabled = true;
+
+
+    protected class RealmUsers {
+        protected class LRUCache extends LinkedHashMap<String, CachedUser> {
+            public LRUCache() {
+                super(1000, 1.1F, true);
+            }
+
+            @Override
+            public CachedUser put(String key, CachedUser value) {
+                if (value.getUsername() != null) {
+                    usersByUsername.put(value.getUsername(), value);
+                }
+                if (value.getEmail() != null) {
+                    usersByEmail.put(value.getEmail(), value);
+                }
+                return super.put(key, value);
+            }
+
+            @Override
+            public CachedUser remove(Object key) {
+                CachedUser user = super.remove(key);
+                if (user == null) return null;
+                removeUser(user);
+                return user;
+            }
+
+            @Override
+            public void clear() {
+                super.clear();
+                usersByUsername.clear();
+                usersByEmail.clear();
+            }
+
+            @Override
+            protected boolean removeEldestEntry(Map.Entry<String, CachedUser> eldest) {
+                boolean evict = size() > maxUserCacheSize;
+                if (evict) {
+                    removeUser(eldest.getValue());
+                }
+                return evict;
+            }
+
+            private void removeUser(CachedUser value) {
+                if (value.getUsername() != null) usersByUsername.remove(value.getUsername());
+                if (value.getEmail() != null) usersByEmail.remove(value.getEmail());
+            }
+        }
+
+        protected Map<String, CachedUser> usersById = Collections.synchronizedMap(new LRUCache());
+        protected Map<String, CachedUser> usersByUsername = new ConcurrentHashMap<String, CachedUser>();
+        protected Map<String, CachedUser> usersByEmail = new ConcurrentHashMap<String, CachedUser>();
+
+    }
+
+    protected ConcurrentHashMap<String, RealmUsers> realmUsers = new ConcurrentHashMap<String, RealmUsers>();
+
+    public int getMaxUserCacheSize() {
+        return maxUserCacheSize;
+    }
+
+    public void setMaxUserCacheSize(int maxUserCacheSize) {
+        this.maxUserCacheSize = maxUserCacheSize;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        clear();
+        this.enabled = enabled;
+        clear();
+    }
+
+    @Override
+    public CachedUser getCachedUser(String realmId, String id) {
+        if (realmId == null || id == null) return null;
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) return null;
+        return users.usersById.get(id);
+    }
+
+    @Override
+    public void invalidateCachedUser(String realmId, CachedUser user) {
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) return;
+        users.usersById.remove(user.getId());
+    }
+
+    @Override
+    public void invalidateCachedUserById(String realmId, String id) {
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) return;
+        users.usersById.remove(id);
+    }
+
+    @Override
+    public void addCachedUser(String realmId, CachedUser user) {
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) {
+            users = new RealmUsers();
+            realmUsers.put(realmId, users);
+        }
+        users.usersById.put(user.getId(), user);
+    }
+
+    @Override
+    public CachedUser getCachedUserByUsername(String realmId, String name) {
+        if (realmId == null || name == null) return null;
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) return null;
+        CachedUser user = users.usersByUsername.get(name);
+        if (user == null) return null;
+        users.usersById.get(user.getId()); // refresh cache entry age
+        return user;
+    }
+
+    @Override
+    public CachedUser getCachedUserByEmail(String realmId, String email) {
+        if (realmId == null || email == null) return null;
+        RealmUsers users = realmUsers.get(realmId);
+        if (users == null) return null;
+        CachedUser user = users.usersByEmail.get(email);
+        if (user == null) return null;
+        users.usersById.get(user.getId()); // refresh cache entry age
+        return user;
+    }
+
+    @Override
+    public void invalidateRealmUsers(String realmId) {
+        realmUsers.remove(realmId);
+    }
+
+    @Override
+    public void clear() {
+        realmUsers.clear();
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
index cb8a8a3..7f87bcd 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
@@ -1,103 +1,103 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class NoCacheRealmProvider implements CacheRealmProvider {
-    protected KeycloakSession session;
-    protected RealmProvider delegate;
-
-    public NoCacheRealmProvider(KeycloakSession session) {
-        this.session = session;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return false;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public RealmProvider getDelegate() {
-        if (delegate != null) return delegate;
-        delegate = session.getProvider(RealmProvider.class);
-        return delegate;
-    }
-
-    @Override
-    public void registerRealmInvalidation(String id) {
-    }
-
-    @Override
-    public void registerApplicationInvalidation(String id) {
-    }
-
-    @Override
-    public void registerRoleInvalidation(String id) {
-    }
-
-    @Override
-    public MigrationModel getMigrationModel() {
-        return getDelegate().getMigrationModel();
-    }
-
-    @Override
-    public RealmModel createRealm(String name) {
-        return getDelegate().createRealm(name);
-    }
-
-    @Override
-    public RealmModel createRealm(String id, String name) {
-        return getDelegate().createRealm(id, name);
-    }
-
-    @Override
-    public RealmModel getRealm(String id) {
-        return getDelegate().getRealm(id);
-    }
-
-    @Override
-    public RealmModel getRealmByName(String name) {
-        return getDelegate().getRealmByName(name);
-    }
-
-    @Override
-    public List<RealmModel> getRealms() {
-        // we don't cache this for now
-        return getDelegate().getRealms();
-    }
-
-    @Override
-    public boolean removeRealm(String id) {
-        return getDelegate().removeRealm(id);
-    }
-
-    @Override
-    public void close() {
-        if (delegate != null) delegate.close();
-    }
-
-    @Override
-    public RoleModel getRoleById(String id, RealmModel realm) {
-       return getDelegate().getRoleById(id, realm);
-    }
-
-    @Override
-    public ClientModel getClientById(String id, RealmModel realm) {
-        return getDelegate().getClientById(id, realm);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class NoCacheRealmProvider implements CacheRealmProvider {
+    protected KeycloakSession session;
+    protected RealmProvider delegate;
+
+    public NoCacheRealmProvider(KeycloakSession session) {
+        this.session = session;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RealmProvider getDelegate() {
+        if (delegate != null) return delegate;
+        delegate = session.getProvider(RealmProvider.class);
+        return delegate;
+    }
+
+    @Override
+    public void registerRealmInvalidation(String id) {
+    }
+
+    @Override
+    public void registerApplicationInvalidation(String id) {
+    }
+
+    @Override
+    public void registerRoleInvalidation(String id) {
+    }
+
+    @Override
+    public MigrationModel getMigrationModel() {
+        return getDelegate().getMigrationModel();
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        return getDelegate().createRealm(name);
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        return getDelegate().createRealm(id, name);
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        return getDelegate().getRealm(id);
+    }
+
+    @Override
+    public RealmModel getRealmByName(String name) {
+        return getDelegate().getRealmByName(name);
+    }
+
+    @Override
+    public List<RealmModel> getRealms() {
+        // we don't cache this for now
+        return getDelegate().getRealms();
+    }
+
+    @Override
+    public boolean removeRealm(String id) {
+        return getDelegate().removeRealm(id);
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) delegate.close();
+    }
+
+    @Override
+    public RoleModel getRoleById(String id, RealmModel realm) {
+       return getDelegate().getRoleById(id, realm);
+    }
+
+    @Override
+    public ClientModel getClientById(String id, RealmModel realm) {
+        return getDelegate().getClientById(id, realm);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProviderFactory.java
index 87e1d9e..7ee9329 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProviderFactory.java
@@ -1,36 +1,36 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class NoCacheRealmProviderFactory implements CacheRealmProviderFactory {
-    @Override
-    public CacheRealmProvider create(KeycloakSession session) {
-        return new NoCacheRealmProvider(session);
-    }
-
-    @Override
-    public void close() {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return "none";
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class NoCacheRealmProviderFactory implements CacheRealmProviderFactory {
+    @Override
+    public CacheRealmProvider create(KeycloakSession session) {
+        return new NoCacheRealmProvider(session);
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return "none";
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java
index aca466b..6137a91 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java
@@ -1,190 +1,190 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class NoCacheUserProvider implements CacheUserProvider {
-    protected KeycloakSession session;
-    protected UserProvider delegate;
-
-    public NoCacheUserProvider(KeycloakSession session) {
-        this.session = session;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return false;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-    }
-
-    @Override
-    public UserProvider getDelegate() {
-        if (delegate != null) return delegate;
-        delegate = session.getProvider(UserProvider.class);
-        return delegate;
-    }
-
-    @Override
-    public void registerUserInvalidation(RealmModel realm, String id) {
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        return getDelegate().getUserById(id, realm);
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        return getDelegate().getUserByUsername(username, realm);
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        return getDelegate().getUserByEmail(email, realm);
-    }
-
-    @Override
-    public void close() {
-        if (delegate != null) delegate.close();
-    }
-
-    @Override
-    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
-        return getDelegate().getUserByFederatedIdentity(socialLink, realm);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return getDelegate().getUsers(realm);
-    }
-
-    @Override
-    public int getUsersCount(RealmModel realm) {
-        return getDelegate().getUsersCount(realm);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().getUsers(realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return getDelegate().searchForUser(search, realm);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().searchForUser(search, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return getDelegate().searchForUserByAttributes(attributes, realm);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
-        return getDelegate().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
-    }
-
-    @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
-        return getDelegate().getFederatedIdentities(user, realm);
-    }
-
-    @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        return getDelegate().getFederatedIdentity(user, socialProvider, realm);
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
-        return getDelegate().addUser(realm, id, username, addDefaultRoles, addDefaultRequiredActions);
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String username) {
-        return getDelegate().addUser(realm, username);
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        return getDelegate().removeUser(realm, user);
-    }
-
-    @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
-        getDelegate().addFederatedIdentity(realm, user, socialLink);
-    }
-
-    @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        getDelegate().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
-    }
-
-    @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
-        return getDelegate().removeFederatedIdentity(realm, user, socialProvider);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        return getDelegate().validCredentials(realm, user, input);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return getDelegate().validCredentials(realm, user, input);
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
-        return getDelegate().validCredentials(realm, input);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        getDelegate().preRemove(realm);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
-        getDelegate().preRemove(realm, link);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        getDelegate().preRemove(realm, role);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, ClientModel client) {
-        getDelegate().preRemove(realm, client);
-    }
-
-    @Override
-    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
-        getDelegate().preRemove(client, protocolMapper);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class NoCacheUserProvider implements CacheUserProvider {
+    protected KeycloakSession session;
+    protected UserProvider delegate;
+
+    public NoCacheUserProvider(KeycloakSession session) {
+        this.session = session;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return false;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+    }
+
+    @Override
+    public UserProvider getDelegate() {
+        if (delegate != null) return delegate;
+        delegate = session.getProvider(UserProvider.class);
+        return delegate;
+    }
+
+    @Override
+    public void registerUserInvalidation(RealmModel realm, String id) {
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        return getDelegate().getUserById(id, realm);
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        return getDelegate().getUserByUsername(username, realm);
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        return getDelegate().getUserByEmail(email, realm);
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) delegate.close();
+    }
+
+    @Override
+    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
+        return getDelegate().getUserByFederatedIdentity(socialLink, realm);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getDelegate().getUsers(realm);
+    }
+
+    @Override
+    public int getUsersCount(RealmModel realm) {
+        return getDelegate().getUsersCount(realm);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().getUsers(realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return getDelegate().searchForUser(search, realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().searchForUser(search, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return getDelegate().searchForUserByAttributes(attributes, realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
+        return getDelegate().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
+    }
+
+    @Override
+    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
+        return getDelegate().getFederatedIdentities(user, realm);
+    }
+
+    @Override
+    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
+        return getDelegate().getFederatedIdentity(user, socialProvider, realm);
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+        return getDelegate().addUser(realm, id, username, addDefaultRoles, addDefaultRequiredActions);
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String username) {
+        return getDelegate().addUser(realm, username);
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        return getDelegate().removeUser(realm, user);
+    }
+
+    @Override
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
+        getDelegate().addFederatedIdentity(realm, user, socialLink);
+    }
+
+    @Override
+    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+        getDelegate().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
+    }
+
+    @Override
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
+        return getDelegate().removeFederatedIdentity(realm, user, socialProvider);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        return getDelegate().validCredentials(realm, user, input);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return getDelegate().validCredentials(realm, user, input);
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
+        return getDelegate().validCredentials(realm, input);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        getDelegate().preRemove(realm);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
+        getDelegate().preRemove(realm, link);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        getDelegate().preRemove(realm, role);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, ClientModel client) {
+        getDelegate().preRemove(realm, client);
+    }
+
+    @Override
+    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
+        getDelegate().preRemove(client, protocolMapper);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java
index 7225562..a89847b 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java
@@ -1,36 +1,36 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class NoCacheUserProviderFactory implements CacheUserProviderFactory {
-    @Override
-    public CacheUserProvider create(KeycloakSession session) {
-        return new NoCacheUserProvider(session);
-    }
-
-    @Override
-    public void close() {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return "none";
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class NoCacheUserProviderFactory implements CacheUserProviderFactory {
+    @Override
+    public CacheUserProvider create(KeycloakSession session) {
+        return new NoCacheUserProvider(session);
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return "none";
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 03ceced..fe2ded8 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -1,1181 +1,1181 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.Config;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmAdapter implements RealmModel {
-    protected CachedRealm cached;
-    protected CacheRealmProvider cacheSession;
-    protected RealmModel updated;
-    protected RealmCache cache;
-    protected volatile transient PublicKey publicKey;
-    protected volatile transient PrivateKey privateKey;
-    protected volatile transient Key codeSecretKey;
-    protected volatile transient X509Certificate certificate;
-
-    public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
-        this.cached = cached;
-        this.cacheSession = cacheSession;
-    }
-
-    protected void getDelegateForUpdate() {
-        if (updated == null) {
-            cacheSession.registerRealmInvalidation(getId());
-            updated = cacheSession.getDelegate().getRealm(getId());
-            if (updated == null) throw new IllegalStateException("Not found in database");
-        }
-    }
-
-    @Override
-    public String getId() {
-        if (updated != null) return updated.getId();
-        return cached.getId();
-    }
-
-    @Override
-    public String getName() {
-        if (updated != null) return updated.getName();
-        return cached.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        getDelegateForUpdate();
-        updated.setName(name);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        if (updated != null) return updated.isEnabled();
-        return cached.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setEnabled(enabled);
-    }
-
-    @Override
-    public SslRequired getSslRequired() {
-        if (updated != null) return updated.getSslRequired();
-        return cached.getSslRequired();
-    }
-
-    @Override
-    public void setSslRequired(SslRequired sslRequired) {
-        getDelegateForUpdate();
-        updated.setSslRequired(sslRequired);
-    }
-
-    @Override
-    public boolean isRegistrationAllowed() {
-        if (updated != null) return updated.isRegistrationAllowed();
-        return cached.isRegistrationAllowed();
-    }
-
-    @Override
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        getDelegateForUpdate();
-        updated.setRegistrationAllowed(registrationAllowed);
-    }
-
-    @Override
-    public boolean isRegistrationEmailAsUsername() {
-        if (updated != null) return updated.isRegistrationEmailAsUsername();
-        return cached.isRegistrationEmailAsUsername();
-    }
-
-    @Override
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        getDelegateForUpdate();
-        updated.setRegistrationEmailAsUsername(registrationEmailAsUsername);
-    }
-
-    @Override
-    public boolean isRememberMe() {
-        if (updated != null) return updated.isRememberMe();
-        return cached.isRememberMe();
-    }
-
-    @Override
-    public void setRememberMe(boolean rememberMe) {
-        getDelegateForUpdate();
-        updated.setRememberMe(rememberMe);
-    }
-
-    @Override
-    public boolean isBruteForceProtected() {
-        if (updated != null) return updated.isBruteForceProtected();
-        return cached.isBruteForceProtected();
-    }
-
-    @Override
-    public void setBruteForceProtected(boolean value) {
-        getDelegateForUpdate();
-        updated.setBruteForceProtected(value);
-    }
-
-    @Override
-    public int getMaxFailureWaitSeconds() {
-        if (updated != null) return updated.getMaxFailureWaitSeconds();
-        return cached.getMaxFailureWaitSeconds();
-    }
-
-    @Override
-    public void setMaxFailureWaitSeconds(int val) {
-        getDelegateForUpdate();
-        updated.setMaxFailureWaitSeconds(val);
-    }
-
-    @Override
-    public int getWaitIncrementSeconds() {
-        if (updated != null) return updated.getWaitIncrementSeconds();
-        return cached.getWaitIncrementSeconds();
-    }
-
-    @Override
-    public void setWaitIncrementSeconds(int val) {
-        getDelegateForUpdate();
-        updated.setWaitIncrementSeconds(val);
-    }
-
-    @Override
-    public int getMinimumQuickLoginWaitSeconds() {
-        if (updated != null) return updated.getMinimumQuickLoginWaitSeconds();
-        return cached.getMinimumQuickLoginWaitSeconds();
-    }
-
-    @Override
-    public void setMinimumQuickLoginWaitSeconds(int val) {
-        getDelegateForUpdate();
-        updated.setMinimumQuickLoginWaitSeconds(val);
-    }
-
-    @Override
-    public long getQuickLoginCheckMilliSeconds() {
-        if (updated != null) return updated.getQuickLoginCheckMilliSeconds();
-        return cached.getQuickLoginCheckMilliSeconds();
-    }
-
-    @Override
-    public void setQuickLoginCheckMilliSeconds(long val) {
-        getDelegateForUpdate();
-        updated.setQuickLoginCheckMilliSeconds(val);
-    }
-
-    @Override
-    public int getMaxDeltaTimeSeconds() {
-        if (updated != null) return updated.getMaxDeltaTimeSeconds();
-        return cached.getMaxDeltaTimeSeconds();
-    }
-
-    @Override
-    public void setMaxDeltaTimeSeconds(int val) {
-        getDelegateForUpdate();
-        updated.setMaxDeltaTimeSeconds(val);
-    }
-
-    @Override
-    public int getFailureFactor() {
-        if (updated != null) return updated.getFailureFactor();
-        return cached.getFailureFactor();
-    }
-
-    @Override
-    public void setFailureFactor(int failureFactor) {
-        getDelegateForUpdate();
-        updated.setFailureFactor(failureFactor);
-    }
-
-    @Override
-    public boolean isVerifyEmail() {
-        if (updated != null) return updated.isVerifyEmail();
-        return cached.isVerifyEmail();
-    }
-
-    @Override
-    public void setVerifyEmail(boolean verifyEmail) {
-        getDelegateForUpdate();
-        updated.setVerifyEmail(verifyEmail);
-    }
-
-    @Override
-    public boolean isResetPasswordAllowed() {
-        if (updated != null) return updated.isResetPasswordAllowed();
-        return cached.isResetPasswordAllowed();
-    }
-
-    @Override
-    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
-        getDelegateForUpdate();
-        updated.setResetPasswordAllowed(resetPasswordAllowed);
-    }
-
-    @Override
-    public boolean isEditUsernameAllowed() {
-        if (updated != null) return updated.isEditUsernameAllowed();
-        return cached.isEditUsernameAllowed();
-    }
-
-    @Override
-    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
-        getDelegateForUpdate();
-        updated.setEditUsernameAllowed(editUsernameAllowed);
-    }
-
-    @Override
-    public int getSsoSessionIdleTimeout() {
-        if (updated != null) return updated.getSsoSessionIdleTimeout();
-        return cached.getSsoSessionIdleTimeout();
-    }
-
-    @Override
-    public void setSsoSessionIdleTimeout(int seconds) {
-        getDelegateForUpdate();
-        updated.setSsoSessionIdleTimeout(seconds);
-    }
-
-    @Override
-    public int getSsoSessionMaxLifespan() {
-        if (updated != null) return updated.getSsoSessionMaxLifespan();
-        return cached.getSsoSessionMaxLifespan();
-    }
-
-    @Override
-    public void setSsoSessionMaxLifespan(int seconds) {
-        getDelegateForUpdate();
-        updated.setSsoSessionMaxLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessTokenLifespan() {
-        if (updated != null) return updated.getAccessTokenLifespan();
-        return cached.getAccessTokenLifespan();
-    }
-
-    @Override
-    public void setAccessTokenLifespan(int seconds) {
-        getDelegateForUpdate();
-        updated.setAccessTokenLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessCodeLifespan() {
-        if (updated != null) return updated.getAccessCodeLifespan();
-        return cached.getAccessCodeLifespan();
-    }
-
-    @Override
-    public void setAccessCodeLifespan(int seconds) {
-        getDelegateForUpdate();
-        updated.setAccessCodeLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessCodeLifespanUserAction() {
-        if (updated != null) return updated.getAccessCodeLifespanUserAction();
-        return cached.getAccessCodeLifespanUserAction();
-    }
-
-    @Override
-    public void setAccessCodeLifespanUserAction(int seconds) {
-        getDelegateForUpdate();
-        updated.setAccessCodeLifespanUserAction(seconds);
-    }
-
-    @Override
-    public int getAccessCodeLifespanLogin() {
-        if (updated != null) return updated.getAccessCodeLifespanLogin();
-        return cached.getAccessCodeLifespanLogin();
-    }
-
-    @Override
-    public void setAccessCodeLifespanLogin(int seconds) {
-        getDelegateForUpdate();
-        updated.setAccessCodeLifespanLogin(seconds);
-    }
-
-    @Override
-    public String getPublicKeyPem() {
-        if (updated != null) return updated.getPublicKeyPem();
-        return cached.getPublicKeyPem();
-    }
-
-    @Override
-    public void setPublicKeyPem(String publicKeyPem) {
-        getDelegateForUpdate();
-        updated.setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public String getPrivateKeyPem() {
-        if (updated != null) return updated.getPrivateKeyPem();
-        return cached.getPrivateKeyPem();
-    }
-
-    @Override
-    public void setPrivateKeyPem(String privateKeyPem) {
-        getDelegateForUpdate();
-        updated.setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public PublicKey getPublicKey() {
-        if (publicKey != null) return publicKey;
-        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
-        return publicKey;
-    }
-
-    @Override
-    public void setPublicKey(PublicKey publicKey) {
-        this.publicKey = publicKey;
-        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
-        setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public X509Certificate getCertificate() {
-        if (certificate != null) return certificate;
-        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
-        return certificate;
-    }
-
-    @Override
-    public void setCertificate(X509Certificate certificate) {
-        this.certificate = certificate;
-        String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
-        setCertificatePem(certPem);
-    }
-
-    @Override
-    public String getCertificatePem() {
-        if (updated != null) return updated.getCertificatePem();
-        return cached.getCertificatePem();
-    }
-
-    @Override
-    public void setCertificatePem(String certificate) {
-        getDelegateForUpdate();
-        updated.setCertificatePem(certificate);
-
-    }
-
-    @Override
-    public PrivateKey getPrivateKey() {
-        if (privateKey != null) return privateKey;
-        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
-        return privateKey;
-    }
-
-    @Override
-    public void setPrivateKey(PrivateKey privateKey) {
-        this.privateKey = privateKey;
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-        setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public String getCodeSecret() {
-        return updated != null ? updated.getCodeSecret() : cached.getCodeSecret();
-    }
-
-    @Override
-    public Key getCodeSecretKey() {
-        if (codeSecretKey == null) {
-            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
-        }
-        return codeSecretKey;
-    }
-
-    @Override
-    public void setCodeSecret(String codeSecret) {
-        getDelegateForUpdate();
-        updated.setCodeSecret(codeSecret);
-    }
-
-    @Override
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-
-        List<RequiredCredentialModel> copy = new LinkedList<RequiredCredentialModel>();
-        if (updated != null) copy.addAll(updated.getRequiredCredentials());
-        else copy.addAll(cached.getRequiredCredentials());
-        return copy;
-    }
-
-    @Override
-    public void addRequiredCredential(String cred) {
-        getDelegateForUpdate();
-        updated.addRequiredCredential(cred);
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        if (updated != null) return updated.getPasswordPolicy();
-        return cached.getPasswordPolicy();
-    }
-
-    @Override
-    public void setPasswordPolicy(PasswordPolicy policy) {
-        getDelegateForUpdate();
-        updated.setPasswordPolicy(policy);
-    }
-
-    @Override
-    public RoleModel getRoleById(String id) {
-        if (updated != null) return updated.getRoleById(id);
-        return cacheSession.getRoleById(id, this);
-     }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        if (updated != null) return updated.getDefaultRoles();
-        return cached.getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        getDelegateForUpdate();
-        updated.addDefaultRole(name);
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        getDelegateForUpdate();
-        updated.updateDefaultRoles(defaultRoles);
-    }
-
-    @Override
-    public Map<String, ClientModel> getClientNameMap() {
-        if (updated != null) return updated.getClientNameMap();
-        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
-        for (String id : cached.getClients().values()) {
-            ClientModel model = cacheSession.getClientById(id, this);
-            if (model == null) {
-                throw new IllegalStateException("Cached application not found: " + id);
-            }
-            map.put(model.getClientId(), model);
-        }
-        return map;
-    }
-
-    @Override
-    public List<ClientModel> getClients() {
-        if (updated != null) return updated.getClients();
-        List<ClientModel> apps = new LinkedList<ClientModel>();
-        for (String id : cached.getClients().values()) {
-            ClientModel model = cacheSession.getClientById(id, this);
-            if (model == null) {
-                throw new IllegalStateException("Cached application not found: " + id);
-            }
-            apps.add(model);
-        }
-        return apps;
-
-    }
-
-    @Override
-    public ClientModel addClient(String name) {
-        getDelegateForUpdate();
-        ClientModel app = updated.addClient(name);
-        cacheSession.registerApplicationInvalidation(app.getId());
-        return app;
-    }
-
-    @Override
-    public ClientModel addClient(String id, String clientId) {
-        getDelegateForUpdate();
-        ClientModel app =  updated.addClient(id, clientId);
-        cacheSession.registerApplicationInvalidation(app.getId());
-        return app;
-    }
-
-    @Override
-    public boolean removeClient(String id) {
-        cacheSession.registerApplicationInvalidation(id);
-        getDelegateForUpdate();
-        return updated.removeClient(id);
-    }
-
-    @Override
-    public ClientModel getClientById(String id) {
-        if (updated != null) return updated.getClientById(id);
-        return cacheSession.getClientById(id, this);
-    }
-
-    @Override
-    public ClientModel getClientByClientId(String clientId) {
-        if (updated != null) return updated.getClientByClientId(clientId);
-        String id = cached.getClients().get(clientId);
-        if (id == null) return null;
-        return getClientById(id);
-    }
-
-    @Override
-    public void updateRequiredCredentials(Set<String> creds) {
-        getDelegateForUpdate();
-        updated.updateRequiredCredentials(creds);
-    }
-
-    @Override
-    public Map<String, String> getBrowserSecurityHeaders() {
-        if (updated != null) return updated.getBrowserSecurityHeaders();
-        return cached.getBrowserSecurityHeaders();
-    }
-
-    @Override
-    public void setBrowserSecurityHeaders(Map<String, String> headers) {
-        getDelegateForUpdate();
-        updated.setBrowserSecurityHeaders(headers);
-
-    }
-
-    @Override
-    public Map<String, String> getSmtpConfig() {
-        if (updated != null) return updated.getSmtpConfig();
-        return cached.getSmtpConfig();
-    }
-
-    @Override
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        getDelegateForUpdate();
-        updated.setSmtpConfig(smtpConfig);
-    }
-
-
-    @Override
-    public List<IdentityProviderModel> getIdentityProviders() {
-        if (updated != null) return updated.getIdentityProviders();
-        return cached.getIdentityProviders();
-    }
-
-    @Override
-    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
-            if (identityProviderModel.getAlias().equals(alias)) {
-                return identityProviderModel;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void addIdentityProvider(IdentityProviderModel identityProvider) {
-        getDelegateForUpdate();
-        updated.addIdentityProvider(identityProvider);
-    }
-
-    @Override
-    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
-        getDelegateForUpdate();
-        updated.updateIdentityProvider(identityProvider);
-    }
-
-    @Override
-    public void removeIdentityProviderByAlias(String alias) {
-        getDelegateForUpdate();
-        updated.removeIdentityProviderByAlias(alias);
-    }
-
-    @Override
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        if (updated != null) return updated.getUserFederationProviders();
-        return cached.getUserFederationProviders();
-    }
-
-    @Override
-    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
-        getDelegateForUpdate();
-        updated.setUserFederationProviders(providers);
-    }
-
-    @Override
-    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
-        getDelegateForUpdate();
-        return updated.addUserFederationProvider(providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
-    }
-
-    @Override
-    public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        getDelegateForUpdate();
-        updated.removeUserFederationProvider(provider);
-
-    }
-
-    @Override
-    public void updateUserFederationProvider(UserFederationProviderModel provider) {
-        getDelegateForUpdate();
-        updated.updateUserFederationProvider(provider);
-
-    }
-
-    @Override
-    public String getLoginTheme() {
-        if (updated != null) return updated.getLoginTheme();
-        return cached.getLoginTheme();
-    }
-
-    @Override
-    public void setLoginTheme(String name) {
-        getDelegateForUpdate();
-        updated.setLoginTheme(name);
-    }
-
-    @Override
-    public String getAccountTheme() {
-        if (updated != null) return updated.getAccountTheme();
-        return cached.getAccountTheme();
-    }
-
-    @Override
-    public void setAccountTheme(String name) {
-        getDelegateForUpdate();
-        updated.setAccountTheme(name);
-    }
-
-    @Override
-    public String getAdminTheme() {
-        if (updated != null) return updated.getAdminTheme();
-        return cached.getAdminTheme();
-    }
-
-    @Override
-    public void setAdminTheme(String name) {
-        getDelegateForUpdate();
-        updated.setAdminTheme(name);
-    }
-
-    @Override
-    public String getEmailTheme() {
-        if (updated != null) return updated.getEmailTheme();
-        return cached.getEmailTheme();
-    }
-
-    @Override
-    public void setEmailTheme(String name) {
-        getDelegateForUpdate();
-        updated.setEmailTheme(name);
-    }
-
-    @Override
-    public int getNotBefore() {
-        if (updated != null) return updated.getNotBefore();
-        return cached.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        getDelegateForUpdate();
-        updated.setNotBefore(notBefore);
-    }
-
-    @Override
-    public boolean removeRoleById(String id) {
-        cacheSession.registerRoleInvalidation(id);
-        getDelegateForUpdate();
-        return updated.removeRoleById(id);
-    }
-
-    @Override
-    public boolean isEventsEnabled() {
-        if (updated != null) return updated.isEventsEnabled();
-        return cached.isEventsEnabled();
-    }
-
-    @Override
-    public void setEventsEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setEventsEnabled(enabled);
-    }
-
-    @Override
-    public long getEventsExpiration() {
-        if (updated != null) return updated.getEventsExpiration();
-        return cached.getEventsExpiration();
-    }
-
-    @Override
-    public void setEventsExpiration(long expiration) {
-        getDelegateForUpdate();
-        updated.setEventsExpiration(expiration);
-    }
-
-    @Override
-    public Set<String> getEventsListeners() {
-        if (updated != null) return updated.getEventsListeners();
-        return cached.getEventsListeners();
-    }
-
-    @Override
-    public void setEventsListeners(Set<String> listeners) {
-        getDelegateForUpdate();
-        updated.setEventsListeners(listeners);
-    }
-
-    @Override
-    public Set<String> getEnabledEventTypes() {
-        if (updated != null) return updated.getEnabledEventTypes();
-        return cached.getEnabledEventTypes();
-    }
-
-    @Override
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        getDelegateForUpdate();
-        updated.setEnabledEventTypes(enabledEventTypes);        
-    }
-    
-    @Override
-    public boolean isAdminEventsEnabled() {
-        if (updated != null) return updated.isAdminEventsEnabled();
-        return cached.isAdminEventsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setAdminEventsEnabled(enabled);
-    }
-
-    @Override
-    public boolean isAdminEventsDetailsEnabled() {
-        if (updated != null) return updated.isAdminEventsDetailsEnabled();
-        return cached.isAdminEventsDetailsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsDetailsEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setAdminEventsDetailsEnabled(enabled);
-    }
-    
-    @Override
-    public ClientModel getMasterAdminClient() {
-        return cacheSession.getRealm(Config.getAdminRealm()).getClientById(cached.getMasterAdminClient());
-    }
-
-    @Override
-    public void setMasterAdminClient(ClientModel client) {
-        getDelegateForUpdate();
-        updated.setMasterAdminClient(client);
-    }
-
-    @Override
-    public RoleModel getRole(String name) {
-        if (updated != null) return updated.getRole(name);
-        String id = cached.getRealmRoles().get(name);
-        if (id == null) return null;
-        return cacheSession.getRoleById(id, this);
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        getDelegateForUpdate();
-        RoleModel role = updated.addRole(name);
-        cacheSession.registerRoleInvalidation(role.getId());
-        return role;
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        getDelegateForUpdate();
-        RoleModel role =  updated.addRole(id, name);
-        cacheSession.registerRoleInvalidation(role.getId());
-        return role;
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        cacheSession.registerRoleInvalidation(role.getId());
-        getDelegateForUpdate();
-        return updated.removeRole(role);
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        if (updated != null) return updated.getRoles();
-
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String id : cached.getRealmRoles().values()) {
-            RoleModel roleById = cacheSession.getRoleById(id, this);
-            if (roleById == null) continue;
-            roles.add(roleById);
-        }
-        return roles;
-    }
-
-    @Override
-    public boolean isIdentityFederationEnabled() {
-        if (updated != null) return updated.isIdentityFederationEnabled();
-        return cached.isIdentityFederationEnabled();
-    }
-
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RealmModel)) return false;
-
-        RealmModel that = (RealmModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public boolean isInternationalizationEnabled() {
-        if (updated != null) return updated.isInternationalizationEnabled();
-        return cached.isInternationalizationEnabled();
-    }
-
-    @Override
-    public void setInternationalizationEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setInternationalizationEnabled(enabled);
-    }
-
-    @Override
-    public Set<String> getSupportedLocales() {
-        if (updated != null) return updated.getSupportedLocales();
-        return cached.getSupportedLocales();
-    }
-
-    @Override
-    public void setSupportedLocales(Set<String> locales) {
-        getDelegateForUpdate();
-        updated.setSupportedLocales(locales);
-    }
-
-    @Override
-    public String getDefaultLocale() {
-        if (updated != null) return updated.getDefaultLocale();
-        return cached.getDefaultLocale();
-    }
-
-    @Override
-    public void setDefaultLocale(String locale) {
-        updated.setDefaultLocale(locale);
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        if (updated != null) return updated.getIdentityProviderMappers();
-        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
-        for (List<IdentityProviderMapperModel> models : cached.getIdentityProviderMappers().values()) {
-            for (IdentityProviderMapperModel model : models) {
-                mappings.add(model);
-            }
-        }
-        return mappings;
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        if (updated != null) return updated.getIdentityProviderMappersByAlias(brokerAlias);
-        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
-        List<IdentityProviderMapperModel> list = cached.getIdentityProviderMappers().getList(brokerAlias);
-        for (IdentityProviderMapperModel entity : list) {
-            mappings.add(entity);
-        }
-        return mappings;
-    }
-
-    @Override
-    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
-        getDelegateForUpdate();
-        return updated.addIdentityProviderMapper(model);
-    }
-
-    @Override
-    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        getDelegateForUpdate();
-        updated.removeIdentityProviderMapper(mapping);
-    }
-
-    @Override
-    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        getDelegateForUpdate();
-        updated.updateIdentityProviderMapper(mapping);
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        if (updated != null) return updated.getIdentityProviderMapperById(id);
-        for (List<IdentityProviderMapperModel> models : cached.getIdentityProviderMappers().values()) {
-            for (IdentityProviderMapperModel model : models) {
-                if (model.getId().equals(id)) return model;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        if (updated != null) return updated.getIdentityProviderMapperByName(alias, name);
-        List<IdentityProviderMapperModel> models = cached.getIdentityProviderMappers().getList(alias);
-        if (models == null) return null;
-        for (IdentityProviderMapperModel model : models) {
-            if (model.getName().equals(name)) return model;
-        }
-        return null;
-    }
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappers() {
-        if (updated != null) return updated.getUserFederationMappers();
-        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
-        for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
-            for (UserFederationMapperModel model : models) {
-                mappers.add(model);
-            }
-        }
-        return mappers;
-    }
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
-        if (updated != null) return updated.getUserFederationMappersByFederationProvider(federationProviderId);
-        Set<UserFederationMapperModel> mappers = new HashSet<>();
-        List<UserFederationMapperModel> list = cached.getUserFederationMappers().getList(federationProviderId);
-        for (UserFederationMapperModel entity : list) {
-            mappers.add(entity);
-        }
-        return mappers;
-    }
-
-    @Override
-    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper) {
-        getDelegateForUpdate();
-        return updated.addUserFederationMapper(mapper);
-    }
-
-    @Override
-    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
-        getDelegateForUpdate();
-        updated.removeUserFederationMapper(mapper);
-    }
-
-    @Override
-    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
-        getDelegateForUpdate();
-        updated.updateUserFederationMapper(mapper);
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperById(String id) {
-        if (updated != null) return updated.getUserFederationMapperById(id);
-        for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
-            for (UserFederationMapperModel model : models) {
-                if (model.getId().equals(id)) return model;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
-        if (updated != null) return updated.getUserFederationMapperByName(federationProviderId, name);
-        List<UserFederationMapperModel> models = cached.getUserFederationMappers().getList(federationProviderId);
-        if (models == null) return null;
-        for (UserFederationMapperModel model : models) {
-            if (model.getName().equals(name)) return model;
-        }
-        return null;
-    }
-
-    @Override
-    public List<AuthenticationFlowModel> getAuthenticationFlows() {
-        if (updated != null) return updated.getAuthenticationFlows();
-        List<AuthenticationFlowModel> models = new ArrayList<>();
-        models.addAll(cached.getAuthenticationFlows().values());
-        return models;
-    }
-
-    @Override
-    public AuthenticationFlowModel getFlowByAlias(String alias) {
-        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
-            if (flow.getAlias().equals(alias)) {
-                return flow;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
-        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
-            if (config.getAlias().equals(alias)) {
-                return config;
-            }
-        }
-        return null;
-    }
-
-
-    @Override
-    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
-        getDelegateForUpdate();
-        return updated.addAuthenticationFlow(model);
-    }
-
-    @Override
-    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
-        if (updated != null) return updated.getAuthenticationFlowById(id);
-        return cached.getAuthenticationFlows().get(id);
-    }
-
-    @Override
-    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
-        getDelegateForUpdate();
-        updated.removeAuthenticationFlow(model);
-
-    }
-
-    @Override
-    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
-        getDelegateForUpdate();
-        updated.updateAuthenticationFlow(model);
-
-    }
-
-    @Override
-    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
-        if (updated != null) return updated.getAuthenticationExecutions(flowId);
-        List<AuthenticationExecutionModel> models = new ArrayList<>();
-        return cached.getAuthenticationExecutions().get(flowId);
-    }
-
-    @Override
-    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
-        if (updated != null) return updated.getAuthenticationExecutionById(id);
-        return cached.getExecutionsById().get(id);
-    }
-
-    @Override
-    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
-        getDelegateForUpdate();
-        return updated.addAuthenticatorExecution(model);
-    }
-
-    @Override
-    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
-        getDelegateForUpdate();
-        updated.updateAuthenticatorExecution(model);
-
-    }
-
-    @Override
-    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
-        getDelegateForUpdate();
-        updated.removeAuthenticatorExecution(model);
-
-    }
-
-    @Override
-    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
-        if (updated != null) return updated.getAuthenticatorConfigs();
-        List<AuthenticatorConfigModel> models = new ArrayList<>();
-        models.addAll(cached.getAuthenticatorConfigs().values());
-        return models;
-    }
-
-    @Override
-    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
-        getDelegateForUpdate();
-        return updated.addAuthenticatorConfig(model);
-    }
-
-    @Override
-    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
-        getDelegateForUpdate();
-        updated.updateAuthenticatorConfig(model);
-
-    }
-
-    @Override
-    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
-        getDelegateForUpdate();
-        updated.removeAuthenticatorConfig(model);
-
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
-        if (updated != null) return updated.getAuthenticatorConfigById(id);
-        return cached.getAuthenticatorConfigs().get(id);
-    }
-
-    @Override
-    public List<RequiredActionProviderModel> getRequiredActionProviders() {
-        if (updated != null) return updated.getRequiredActionProviders();
-        List<RequiredActionProviderModel> models = new ArrayList<>();
-        models.addAll(cached.getRequiredActionProviders().values());
-        return models;
-    }
-
-    @Override
-    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
-        getDelegateForUpdate();
-        return updated.addRequiredActionProvider(model);
-    }
-
-    @Override
-    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
-        getDelegateForUpdate();
-        updated.updateRequiredActionProvider(model);
-
-    }
-
-    @Override
-    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
-        getDelegateForUpdate();
-        updated.removeRequiredActionProvider(model);
-
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
-        if (updated != null) return updated.getRequiredActionProviderById(id);
-        return cached.getRequiredActionProviders().get(id);
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
-        if (updated != null) return updated.getRequiredActionProviderByAlias(alias);
-        return cached.getRequiredActionProvidersByAlias().get(alias);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmAdapter implements RealmModel {
+    protected CachedRealm cached;
+    protected CacheRealmProvider cacheSession;
+    protected RealmModel updated;
+    protected RealmCache cache;
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+    protected volatile transient Key codeSecretKey;
+    protected volatile transient X509Certificate certificate;
+
+    public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
+        this.cached = cached;
+        this.cacheSession = cacheSession;
+    }
+
+    protected void getDelegateForUpdate() {
+        if (updated == null) {
+            cacheSession.registerRealmInvalidation(getId());
+            updated = cacheSession.getDelegate().getRealm(getId());
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
+
+    @Override
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
+
+    @Override
+    public String getName() {
+        if (updated != null) return updated.getName();
+        return cached.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getDelegateForUpdate();
+        updated.setName(name);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        if (updated != null) return updated.isEnabled();
+        return cached.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setEnabled(enabled);
+    }
+
+    @Override
+    public SslRequired getSslRequired() {
+        if (updated != null) return updated.getSslRequired();
+        return cached.getSslRequired();
+    }
+
+    @Override
+    public void setSslRequired(SslRequired sslRequired) {
+        getDelegateForUpdate();
+        updated.setSslRequired(sslRequired);
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        if (updated != null) return updated.isRegistrationAllowed();
+        return cached.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        getDelegateForUpdate();
+        updated.setRegistrationAllowed(registrationAllowed);
+    }
+
+    @Override
+    public boolean isRegistrationEmailAsUsername() {
+        if (updated != null) return updated.isRegistrationEmailAsUsername();
+        return cached.isRegistrationEmailAsUsername();
+    }
+
+    @Override
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        getDelegateForUpdate();
+        updated.setRegistrationEmailAsUsername(registrationEmailAsUsername);
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        if (updated != null) return updated.isRememberMe();
+        return cached.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        getDelegateForUpdate();
+        updated.setRememberMe(rememberMe);
+    }
+
+    @Override
+    public boolean isBruteForceProtected() {
+        if (updated != null) return updated.isBruteForceProtected();
+        return cached.isBruteForceProtected();
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        getDelegateForUpdate();
+        updated.setBruteForceProtected(value);
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        if (updated != null) return updated.getMaxFailureWaitSeconds();
+        return cached.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMaxFailureWaitSeconds(val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        if (updated != null) return updated.getWaitIncrementSeconds();
+        return cached.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setWaitIncrementSeconds(val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        if (updated != null) return updated.getMinimumQuickLoginWaitSeconds();
+        return cached.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMinimumQuickLoginWaitSeconds(val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        if (updated != null) return updated.getQuickLoginCheckMilliSeconds();
+        return cached.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        getDelegateForUpdate();
+        updated.setQuickLoginCheckMilliSeconds(val);
+    }
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        if (updated != null) return updated.getMaxDeltaTimeSeconds();
+        return cached.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMaxDeltaTimeSeconds(val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        if (updated != null) return updated.getFailureFactor();
+        return cached.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        getDelegateForUpdate();
+        updated.setFailureFactor(failureFactor);
+    }
+
+    @Override
+    public boolean isVerifyEmail() {
+        if (updated != null) return updated.isVerifyEmail();
+        return cached.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        getDelegateForUpdate();
+        updated.setVerifyEmail(verifyEmail);
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        if (updated != null) return updated.isResetPasswordAllowed();
+        return cached.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
+        getDelegateForUpdate();
+        updated.setResetPasswordAllowed(resetPasswordAllowed);
+    }
+
+    @Override
+    public boolean isEditUsernameAllowed() {
+        if (updated != null) return updated.isEditUsernameAllowed();
+        return cached.isEditUsernameAllowed();
+    }
+
+    @Override
+    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+        getDelegateForUpdate();
+        updated.setEditUsernameAllowed(editUsernameAllowed);
+    }
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        if (updated != null) return updated.getSsoSessionIdleTimeout();
+        return cached.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        getDelegateForUpdate();
+        updated.setSsoSessionIdleTimeout(seconds);
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        if (updated != null) return updated.getSsoSessionMaxLifespan();
+        return cached.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setSsoSessionMaxLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        if (updated != null) return updated.getAccessTokenLifespan();
+        return cached.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessTokenLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        if (updated != null) return updated.getAccessCodeLifespan();
+        return cached.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessCodeLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        if (updated != null) return updated.getAccessCodeLifespanUserAction();
+        return cached.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessCodeLifespanUserAction(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespanLogin() {
+        if (updated != null) return updated.getAccessCodeLifespanLogin();
+        return cached.getAccessCodeLifespanLogin();
+    }
+
+    @Override
+    public void setAccessCodeLifespanLogin(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessCodeLifespanLogin(seconds);
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        if (updated != null) return updated.getPublicKeyPem();
+        return cached.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        getDelegateForUpdate();
+        updated.setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public String getPrivateKeyPem() {
+        if (updated != null) return updated.getPrivateKeyPem();
+        return cached.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        getDelegateForUpdate();
+        updated.setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public X509Certificate getCertificate() {
+        if (certificate != null) return certificate;
+        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
+        return certificate;
+    }
+
+    @Override
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+        String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
+        setCertificatePem(certPem);
+    }
+
+    @Override
+    public String getCertificatePem() {
+        if (updated != null) return updated.getCertificatePem();
+        return cached.getCertificatePem();
+    }
+
+    @Override
+    public void setCertificatePem(String certificate) {
+        getDelegateForUpdate();
+        updated.setCertificatePem(certificate);
+
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public String getCodeSecret() {
+        return updated != null ? updated.getCodeSecret() : cached.getCodeSecret();
+    }
+
+    @Override
+    public Key getCodeSecretKey() {
+        if (codeSecretKey == null) {
+            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
+        }
+        return codeSecretKey;
+    }
+
+    @Override
+    public void setCodeSecret(String codeSecret) {
+        getDelegateForUpdate();
+        updated.setCodeSecret(codeSecret);
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+
+        List<RequiredCredentialModel> copy = new LinkedList<RequiredCredentialModel>();
+        if (updated != null) copy.addAll(updated.getRequiredCredentials());
+        else copy.addAll(cached.getRequiredCredentials());
+        return copy;
+    }
+
+    @Override
+    public void addRequiredCredential(String cred) {
+        getDelegateForUpdate();
+        updated.addRequiredCredential(cred);
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (updated != null) return updated.getPasswordPolicy();
+        return cached.getPasswordPolicy();
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        getDelegateForUpdate();
+        updated.setPasswordPolicy(policy);
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        if (updated != null) return updated.getRoleById(id);
+        return cacheSession.getRoleById(id, this);
+     }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        if (updated != null) return updated.getDefaultRoles();
+        return cached.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        getDelegateForUpdate();
+        updated.addDefaultRole(name);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        getDelegateForUpdate();
+        updated.updateDefaultRoles(defaultRoles);
+    }
+
+    @Override
+    public Map<String, ClientModel> getClientNameMap() {
+        if (updated != null) return updated.getClientNameMap();
+        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
+        for (String id : cached.getClients().values()) {
+            ClientModel model = cacheSession.getClientById(id, this);
+            if (model == null) {
+                throw new IllegalStateException("Cached application not found: " + id);
+            }
+            map.put(model.getClientId(), model);
+        }
+        return map;
+    }
+
+    @Override
+    public List<ClientModel> getClients() {
+        if (updated != null) return updated.getClients();
+        List<ClientModel> apps = new LinkedList<ClientModel>();
+        for (String id : cached.getClients().values()) {
+            ClientModel model = cacheSession.getClientById(id, this);
+            if (model == null) {
+                throw new IllegalStateException("Cached application not found: " + id);
+            }
+            apps.add(model);
+        }
+        return apps;
+
+    }
+
+    @Override
+    public ClientModel addClient(String name) {
+        getDelegateForUpdate();
+        ClientModel app = updated.addClient(name);
+        cacheSession.registerApplicationInvalidation(app.getId());
+        return app;
+    }
+
+    @Override
+    public ClientModel addClient(String id, String clientId) {
+        getDelegateForUpdate();
+        ClientModel app =  updated.addClient(id, clientId);
+        cacheSession.registerApplicationInvalidation(app.getId());
+        return app;
+    }
+
+    @Override
+    public boolean removeClient(String id) {
+        cacheSession.registerApplicationInvalidation(id);
+        getDelegateForUpdate();
+        return updated.removeClient(id);
+    }
+
+    @Override
+    public ClientModel getClientById(String id) {
+        if (updated != null) return updated.getClientById(id);
+        return cacheSession.getClientById(id, this);
+    }
+
+    @Override
+    public ClientModel getClientByClientId(String clientId) {
+        if (updated != null) return updated.getClientByClientId(clientId);
+        String id = cached.getClients().get(clientId);
+        if (id == null) return null;
+        return getClientById(id);
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        getDelegateForUpdate();
+        updated.updateRequiredCredentials(creds);
+    }
+
+    @Override
+    public Map<String, String> getBrowserSecurityHeaders() {
+        if (updated != null) return updated.getBrowserSecurityHeaders();
+        return cached.getBrowserSecurityHeaders();
+    }
+
+    @Override
+    public void setBrowserSecurityHeaders(Map<String, String> headers) {
+        getDelegateForUpdate();
+        updated.setBrowserSecurityHeaders(headers);
+
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        if (updated != null) return updated.getSmtpConfig();
+        return cached.getSmtpConfig();
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        getDelegateForUpdate();
+        updated.setSmtpConfig(smtpConfig);
+    }
+
+
+    @Override
+    public List<IdentityProviderModel> getIdentityProviders() {
+        if (updated != null) return updated.getIdentityProviders();
+        return cached.getIdentityProviders();
+    }
+
+    @Override
+    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
+            if (identityProviderModel.getAlias().equals(alias)) {
+                return identityProviderModel;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void addIdentityProvider(IdentityProviderModel identityProvider) {
+        getDelegateForUpdate();
+        updated.addIdentityProvider(identityProvider);
+    }
+
+    @Override
+    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
+        getDelegateForUpdate();
+        updated.updateIdentityProvider(identityProvider);
+    }
+
+    @Override
+    public void removeIdentityProviderByAlias(String alias) {
+        getDelegateForUpdate();
+        updated.removeIdentityProviderByAlias(alias);
+    }
+
+    @Override
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        if (updated != null) return updated.getUserFederationProviders();
+        return cached.getUserFederationProviders();
+    }
+
+    @Override
+    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
+        getDelegateForUpdate();
+        updated.setUserFederationProviders(providers);
+    }
+
+    @Override
+    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
+        getDelegateForUpdate();
+        return updated.addUserFederationProvider(providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+    }
+
+    @Override
+    public void removeUserFederationProvider(UserFederationProviderModel provider) {
+        getDelegateForUpdate();
+        updated.removeUserFederationProvider(provider);
+
+    }
+
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel provider) {
+        getDelegateForUpdate();
+        updated.updateUserFederationProvider(provider);
+
+    }
+
+    @Override
+    public String getLoginTheme() {
+        if (updated != null) return updated.getLoginTheme();
+        return cached.getLoginTheme();
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        getDelegateForUpdate();
+        updated.setLoginTheme(name);
+    }
+
+    @Override
+    public String getAccountTheme() {
+        if (updated != null) return updated.getAccountTheme();
+        return cached.getAccountTheme();
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        getDelegateForUpdate();
+        updated.setAccountTheme(name);
+    }
+
+    @Override
+    public String getAdminTheme() {
+        if (updated != null) return updated.getAdminTheme();
+        return cached.getAdminTheme();
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        getDelegateForUpdate();
+        updated.setAdminTheme(name);
+    }
+
+    @Override
+    public String getEmailTheme() {
+        if (updated != null) return updated.getEmailTheme();
+        return cached.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        getDelegateForUpdate();
+        updated.setEmailTheme(name);
+    }
+
+    @Override
+    public int getNotBefore() {
+        if (updated != null) return updated.getNotBefore();
+        return cached.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        getDelegateForUpdate();
+        updated.setNotBefore(notBefore);
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        cacheSession.registerRoleInvalidation(id);
+        getDelegateForUpdate();
+        return updated.removeRoleById(id);
+    }
+
+    @Override
+    public boolean isEventsEnabled() {
+        if (updated != null) return updated.isEventsEnabled();
+        return cached.isEventsEnabled();
+    }
+
+    @Override
+    public void setEventsEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setEventsEnabled(enabled);
+    }
+
+    @Override
+    public long getEventsExpiration() {
+        if (updated != null) return updated.getEventsExpiration();
+        return cached.getEventsExpiration();
+    }
+
+    @Override
+    public void setEventsExpiration(long expiration) {
+        getDelegateForUpdate();
+        updated.setEventsExpiration(expiration);
+    }
+
+    @Override
+    public Set<String> getEventsListeners() {
+        if (updated != null) return updated.getEventsListeners();
+        return cached.getEventsListeners();
+    }
+
+    @Override
+    public void setEventsListeners(Set<String> listeners) {
+        getDelegateForUpdate();
+        updated.setEventsListeners(listeners);
+    }
+
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        if (updated != null) return updated.getEnabledEventTypes();
+        return cached.getEnabledEventTypes();
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        getDelegateForUpdate();
+        updated.setEnabledEventTypes(enabledEventTypes);        
+    }
+    
+    @Override
+    public boolean isAdminEventsEnabled() {
+        if (updated != null) return updated.isAdminEventsEnabled();
+        return cached.isAdminEventsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setAdminEventsEnabled(enabled);
+    }
+
+    @Override
+    public boolean isAdminEventsDetailsEnabled() {
+        if (updated != null) return updated.isAdminEventsDetailsEnabled();
+        return cached.isAdminEventsDetailsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsDetailsEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setAdminEventsDetailsEnabled(enabled);
+    }
+    
+    @Override
+    public ClientModel getMasterAdminClient() {
+        return cacheSession.getRealm(Config.getAdminRealm()).getClientById(cached.getMasterAdminClient());
+    }
+
+    @Override
+    public void setMasterAdminClient(ClientModel client) {
+        getDelegateForUpdate();
+        updated.setMasterAdminClient(client);
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        if (updated != null) return updated.getRole(name);
+        String id = cached.getRealmRoles().get(name);
+        if (id == null) return null;
+        return cacheSession.getRoleById(id, this);
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        getDelegateForUpdate();
+        RoleModel role = updated.addRole(name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        getDelegateForUpdate();
+        RoleModel role =  updated.addRole(id, name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        cacheSession.registerRoleInvalidation(role.getId());
+        getDelegateForUpdate();
+        return updated.removeRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        if (updated != null) return updated.getRoles();
+
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String id : cached.getRealmRoles().values()) {
+            RoleModel roleById = cacheSession.getRoleById(id, this);
+            if (roleById == null) continue;
+            roles.add(roleById);
+        }
+        return roles;
+    }
+
+    @Override
+    public boolean isIdentityFederationEnabled() {
+        if (updated != null) return updated.isIdentityFederationEnabled();
+        return cached.isIdentityFederationEnabled();
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public boolean isInternationalizationEnabled() {
+        if (updated != null) return updated.isInternationalizationEnabled();
+        return cached.isInternationalizationEnabled();
+    }
+
+    @Override
+    public void setInternationalizationEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setInternationalizationEnabled(enabled);
+    }
+
+    @Override
+    public Set<String> getSupportedLocales() {
+        if (updated != null) return updated.getSupportedLocales();
+        return cached.getSupportedLocales();
+    }
+
+    @Override
+    public void setSupportedLocales(Set<String> locales) {
+        getDelegateForUpdate();
+        updated.setSupportedLocales(locales);
+    }
+
+    @Override
+    public String getDefaultLocale() {
+        if (updated != null) return updated.getDefaultLocale();
+        return cached.getDefaultLocale();
+    }
+
+    @Override
+    public void setDefaultLocale(String locale) {
+        updated.setDefaultLocale(locale);
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
+        if (updated != null) return updated.getIdentityProviderMappers();
+        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
+        for (List<IdentityProviderMapperModel> models : cached.getIdentityProviderMappers().values()) {
+            for (IdentityProviderMapperModel model : models) {
+                mappings.add(model);
+            }
+        }
+        return mappings;
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
+        if (updated != null) return updated.getIdentityProviderMappersByAlias(brokerAlias);
+        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
+        List<IdentityProviderMapperModel> list = cached.getIdentityProviderMappers().getList(brokerAlias);
+        for (IdentityProviderMapperModel entity : list) {
+            mappings.add(entity);
+        }
+        return mappings;
+    }
+
+    @Override
+    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
+        getDelegateForUpdate();
+        return updated.addIdentityProviderMapper(model);
+    }
+
+    @Override
+    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        getDelegateForUpdate();
+        updated.removeIdentityProviderMapper(mapping);
+    }
+
+    @Override
+    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        getDelegateForUpdate();
+        updated.updateIdentityProviderMapper(mapping);
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
+        if (updated != null) return updated.getIdentityProviderMapperById(id);
+        for (List<IdentityProviderMapperModel> models : cached.getIdentityProviderMappers().values()) {
+            for (IdentityProviderMapperModel model : models) {
+                if (model.getId().equals(id)) return model;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
+        if (updated != null) return updated.getIdentityProviderMapperByName(alias, name);
+        List<IdentityProviderMapperModel> models = cached.getIdentityProviderMappers().getList(alias);
+        if (models == null) return null;
+        for (IdentityProviderMapperModel model : models) {
+            if (model.getName().equals(name)) return model;
+        }
+        return null;
+    }
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappers() {
+        if (updated != null) return updated.getUserFederationMappers();
+        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
+        for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
+            for (UserFederationMapperModel model : models) {
+                mappers.add(model);
+            }
+        }
+        return mappers;
+    }
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
+        if (updated != null) return updated.getUserFederationMappersByFederationProvider(federationProviderId);
+        Set<UserFederationMapperModel> mappers = new HashSet<>();
+        List<UserFederationMapperModel> list = cached.getUserFederationMappers().getList(federationProviderId);
+        for (UserFederationMapperModel entity : list) {
+            mappers.add(entity);
+        }
+        return mappers;
+    }
+
+    @Override
+    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel mapper) {
+        getDelegateForUpdate();
+        return updated.addUserFederationMapper(mapper);
+    }
+
+    @Override
+    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
+        getDelegateForUpdate();
+        updated.removeUserFederationMapper(mapper);
+    }
+
+    @Override
+    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
+        getDelegateForUpdate();
+        updated.updateUserFederationMapper(mapper);
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperById(String id) {
+        if (updated != null) return updated.getUserFederationMapperById(id);
+        for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
+            for (UserFederationMapperModel model : models) {
+                if (model.getId().equals(id)) return model;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
+        if (updated != null) return updated.getUserFederationMapperByName(federationProviderId, name);
+        List<UserFederationMapperModel> models = cached.getUserFederationMappers().getList(federationProviderId);
+        if (models == null) return null;
+        for (UserFederationMapperModel model : models) {
+            if (model.getName().equals(name)) return model;
+        }
+        return null;
+    }
+
+    @Override
+    public List<AuthenticationFlowModel> getAuthenticationFlows() {
+        if (updated != null) return updated.getAuthenticationFlows();
+        List<AuthenticationFlowModel> models = new ArrayList<>();
+        models.addAll(cached.getAuthenticationFlows().values());
+        return models;
+    }
+
+    @Override
+    public AuthenticationFlowModel getFlowByAlias(String alias) {
+        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
+            if (flow.getAlias().equals(alias)) {
+                return flow;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
+        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
+            if (config.getAlias().equals(alias)) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+
+    @Override
+    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
+        getDelegateForUpdate();
+        return updated.addAuthenticationFlow(model);
+    }
+
+    @Override
+    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
+        if (updated != null) return updated.getAuthenticationFlowById(id);
+        return cached.getAuthenticationFlows().get(id);
+    }
+
+    @Override
+    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
+        getDelegateForUpdate();
+        updated.removeAuthenticationFlow(model);
+
+    }
+
+    @Override
+    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
+        getDelegateForUpdate();
+        updated.updateAuthenticationFlow(model);
+
+    }
+
+    @Override
+    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
+        if (updated != null) return updated.getAuthenticationExecutions(flowId);
+        List<AuthenticationExecutionModel> models = new ArrayList<>();
+        return cached.getAuthenticationExecutions().get(flowId);
+    }
+
+    @Override
+    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
+        if (updated != null) return updated.getAuthenticationExecutionById(id);
+        return cached.getExecutionsById().get(id);
+    }
+
+    @Override
+    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
+        getDelegateForUpdate();
+        return updated.addAuthenticatorExecution(model);
+    }
+
+    @Override
+    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
+        getDelegateForUpdate();
+        updated.updateAuthenticatorExecution(model);
+
+    }
+
+    @Override
+    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
+        getDelegateForUpdate();
+        updated.removeAuthenticatorExecution(model);
+
+    }
+
+    @Override
+    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
+        if (updated != null) return updated.getAuthenticatorConfigs();
+        List<AuthenticatorConfigModel> models = new ArrayList<>();
+        models.addAll(cached.getAuthenticatorConfigs().values());
+        return models;
+    }
+
+    @Override
+    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
+        getDelegateForUpdate();
+        return updated.addAuthenticatorConfig(model);
+    }
+
+    @Override
+    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
+        getDelegateForUpdate();
+        updated.updateAuthenticatorConfig(model);
+
+    }
+
+    @Override
+    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
+        getDelegateForUpdate();
+        updated.removeAuthenticatorConfig(model);
+
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
+        if (updated != null) return updated.getAuthenticatorConfigById(id);
+        return cached.getAuthenticatorConfigs().get(id);
+    }
+
+    @Override
+    public List<RequiredActionProviderModel> getRequiredActionProviders() {
+        if (updated != null) return updated.getRequiredActionProviders();
+        List<RequiredActionProviderModel> models = new ArrayList<>();
+        models.addAll(cached.getRequiredActionProviders().values());
+        return models;
+    }
+
+    @Override
+    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
+        getDelegateForUpdate();
+        return updated.addRequiredActionProvider(model);
+    }
+
+    @Override
+    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
+        getDelegateForUpdate();
+        updated.updateRequiredActionProvider(model);
+
+    }
+
+    @Override
+    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
+        getDelegateForUpdate();
+        updated.removeRequiredActionProvider(model);
+
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
+        if (updated != null) return updated.getRequiredActionProviderById(id);
+        return cached.getRequiredActionProviders().get(id);
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
+        if (updated != null) return updated.getRequiredActionProviderByAlias(alias);
+        return cached.getRequiredActionProvidersByAlias().get(alias);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
index b683f57..9c895c3 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
@@ -1,45 +1,45 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.cache.entities.CachedClient;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.entities.CachedRole;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RealmCache {
-    void clear();
-
-    CachedRealm getCachedRealm(String id);
-
-    void invalidateCachedRealm(CachedRealm realm);
-
-    void addCachedRealm(CachedRealm realm);
-
-    CachedRealm getCachedRealmByName(String name);
-
-    void invalidateCachedRealmById(String id);
-
-    CachedClient getApplication(String id);
-
-    void invalidateApplication(CachedClient app);
-
-    void addCachedClient(CachedClient app);
-
-    void invalidateCachedApplicationById(String id);
-
-    CachedRole getRole(String id);
-
-    void invalidateRole(CachedRole role);
-
-    void addCachedRole(CachedRole role);
-
-    void invalidateCachedRoleById(String id);
-
-    void invalidateRoleById(String id);
-
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.cache.entities.CachedClient;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedRole;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmCache {
+    void clear();
+
+    CachedRealm getCachedRealm(String id);
+
+    void invalidateCachedRealm(CachedRealm realm);
+
+    void addCachedRealm(CachedRealm realm);
+
+    CachedRealm getCachedRealmByName(String name);
+
+    void invalidateCachedRealmById(String id);
+
+    CachedClient getApplication(String id);
+
+    void invalidateApplication(CachedClient app);
+
+    void addCachedClient(CachedClient app);
+
+    void invalidateCachedApplicationById(String id);
+
+    CachedRole getRole(String id);
+
+    void invalidateRole(CachedRole role);
+
+    void addCachedRole(CachedRole role);
+
+    void invalidateCachedRoleById(String id);
+
+    void invalidateRoleById(String id);
+
+    boolean isEnabled();
+
+    void setEnabled(boolean enabled);
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
index 3323338..16cf515 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
@@ -1,137 +1,137 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.cache.entities.CachedClientRole;
-import org.keycloak.models.cache.entities.CachedRealmRole;
-import org.keycloak.models.cache.entities.CachedRole;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleAdapter implements RoleModel {
-
-    protected RoleModel updated;
-    protected CachedRole cached;
-    protected RealmCache cache;
-    protected CacheRealmProvider cacheSession;
-    protected RealmModel realm;
-
-    public RoleAdapter(CachedRole cached, RealmCache cache, CacheRealmProvider session, RealmModel realm) {
-        this.cached = cached;
-        this.cache = cache;
-        this.cacheSession = session;
-        this.realm = realm;
-    }
-
-    protected void getDelegateForUpdate() {
-        if (updated == null) {
-            cacheSession.registerRoleInvalidation(getId());
-            updated = cacheSession.getDelegate().getRoleById(getId(), realm);
-            if (updated == null) throw new IllegalStateException("Not found in database");
-        }
-    }
-
-
-    @Override
-    public String getName() {
-        if (updated != null) return updated.getName();
-        return cached.getName();
-    }
-
-    @Override
-    public String getDescription() {
-        if (updated != null) return updated.getDescription();
-        return cached.getDescription();
-    }
-
-    @Override
-    public void setDescription(String description) {
-        getDelegateForUpdate();
-        updated.setDescription(description);
-    }
-
-    @Override
-    public String getId() {
-        if (updated != null) return updated.getId();
-        return cached.getId();
-    }
-
-    @Override
-    public void setName(String name) {
-        getDelegateForUpdate();
-        updated.setName(name);
-    }
-
-    @Override
-    public boolean isComposite() {
-        if (updated != null) return updated.isComposite();
-        return cached.isComposite();
-    }
-
-    @Override
-    public void addCompositeRole(RoleModel role) {
-        getDelegateForUpdate();
-        updated.addCompositeRole(role);
-    }
-
-    @Override
-    public void removeCompositeRole(RoleModel role) {
-        getDelegateForUpdate();
-        updated.removeCompositeRole(role);
-    }
-
-    @Override
-    public Set<RoleModel> getComposites() {
-        if (updated != null) return updated.getComposites();
-        Set<RoleModel> set = new HashSet<RoleModel>();
-        for (String id : cached.getComposites()) {
-            RoleModel role = realm.getRoleById(id);
-            if (role == null) {
-                throw new IllegalStateException("Could not find composite: " + id);
-            }
-            set.add(role);
-        }
-        return set;
-    }
-
-    @Override
-    public RoleContainerModel getContainer() {
-        if (cached instanceof CachedRealmRole) {
-            return realm;
-        } else {
-            CachedClientRole appRole = (CachedClientRole)cached;
-            return realm.getClientById(appRole.getIdClient());
-        }
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        if (this.equals(role)) return true;
-        if (!isComposite()) return false;
-
-        Set<RoleModel> visited = new HashSet<RoleModel>();
-        return KeycloakModelUtils.searchFor(role, this, visited);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RoleModel)) return false;
-
-        RoleModel that = (RoleModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.cache.entities.CachedClientRole;
+import org.keycloak.models.cache.entities.CachedRealmRole;
+import org.keycloak.models.cache.entities.CachedRole;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleAdapter implements RoleModel {
+
+    protected RoleModel updated;
+    protected CachedRole cached;
+    protected RealmCache cache;
+    protected CacheRealmProvider cacheSession;
+    protected RealmModel realm;
+
+    public RoleAdapter(CachedRole cached, RealmCache cache, CacheRealmProvider session, RealmModel realm) {
+        this.cached = cached;
+        this.cache = cache;
+        this.cacheSession = session;
+        this.realm = realm;
+    }
+
+    protected void getDelegateForUpdate() {
+        if (updated == null) {
+            cacheSession.registerRoleInvalidation(getId());
+            updated = cacheSession.getDelegate().getRoleById(getId(), realm);
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
+
+
+    @Override
+    public String getName() {
+        if (updated != null) return updated.getName();
+        return cached.getName();
+    }
+
+    @Override
+    public String getDescription() {
+        if (updated != null) return updated.getDescription();
+        return cached.getDescription();
+    }
+
+    @Override
+    public void setDescription(String description) {
+        getDelegateForUpdate();
+        updated.setDescription(description);
+    }
+
+    @Override
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
+
+    @Override
+    public void setName(String name) {
+        getDelegateForUpdate();
+        updated.setName(name);
+    }
+
+    @Override
+    public boolean isComposite() {
+        if (updated != null) return updated.isComposite();
+        return cached.isComposite();
+    }
+
+    @Override
+    public void addCompositeRole(RoleModel role) {
+        getDelegateForUpdate();
+        updated.addCompositeRole(role);
+    }
+
+    @Override
+    public void removeCompositeRole(RoleModel role) {
+        getDelegateForUpdate();
+        updated.removeCompositeRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getComposites() {
+        if (updated != null) return updated.getComposites();
+        Set<RoleModel> set = new HashSet<RoleModel>();
+        for (String id : cached.getComposites()) {
+            RoleModel role = realm.getRoleById(id);
+            if (role == null) {
+                throw new IllegalStateException("Could not find composite: " + id);
+            }
+            set.add(role);
+        }
+        return set;
+    }
+
+    @Override
+    public RoleContainerModel getContainer() {
+        if (cached instanceof CachedRealmRole) {
+            return realm;
+        } else {
+            CachedClientRole appRole = (CachedClientRole)cached;
+            return realm.getClientById(appRole.getIdClient());
+        }
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        if (this.equals(role)) return true;
+        if (!isComposite()) return false;
+
+        Set<RoleModel> visited = new HashSet<RoleModel>();
+        return KeycloakModelUtils.searchFor(role, this, visited);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RoleModel)) return false;
+
+        RoleModel that = (RoleModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
index 5c84b51..46130a9 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
@@ -1,347 +1,347 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.cache.entities.CachedUser;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAdapter implements UserModel {
-    protected UserModel updated;
-    protected CachedUser cached;
-    protected CacheUserProvider userProviderCache;
-    protected KeycloakSession keycloakSession;
-    protected RealmModel realm;
-
-    public UserAdapter(CachedUser cached, CacheUserProvider userProvider, KeycloakSession keycloakSession, RealmModel realm) {
-        this.cached = cached;
-        this.userProviderCache = userProvider;
-        this.keycloakSession = keycloakSession;
-        this.realm = realm;
-    }
-
-    protected void getDelegateForUpdate() {
-        if (updated == null) {
-            userProviderCache.registerUserInvalidation(realm, getId());
-            updated = userProviderCache.getDelegate().getUserById(getId(), realm);
-            if (updated == null) throw new IllegalStateException("Not found in database");
-        }
-    }
-    @Override
-    public String getId() {
-        if (updated != null) return updated.getId();
-        return cached.getId();
-    }
-
-    @Override
-    public String getUsername() {
-        if (updated != null) return updated.getUsername();
-        return cached.getUsername();
-    }
-
-    @Override
-    public void setUsername(String username) {
-        getDelegateForUpdate();
-        updated.setUsername(username);
-    }
-
-    @Override
-    public Long getCreatedTimestamp() {
-        // get from cached always as it is immutable
-        return cached.getCreatedTimestamp();
-    }
-
-    @Override
-    public void setCreatedTimestamp(Long timestamp) {
-        // nothing to do as this value is immutable
-    }
-
-    @Override
-    public boolean isEnabled() {
-        if (updated != null) return updated.isEnabled();
-        return cached.isEnabled();
-    }
-
-    @Override
-    public boolean isTotp() {
-        if (updated != null) return updated.isTotp();
-        return cached.isTotp();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        getDelegateForUpdate();
-        updated.setEnabled(enabled);
-    }
-
-    @Override
-    public void setSingleAttribute(String name, String value) {
-        getDelegateForUpdate();
-        updated.setSingleAttribute(name, value);
-    }
-
-    @Override
-    public void setAttribute(String name, List<String> values) {
-        getDelegateForUpdate();
-        updated.setAttribute(name, values);
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        getDelegateForUpdate();
-        updated.removeAttribute(name);
-    }
-
-    @Override
-    public String getFirstAttribute(String name) {
-        if (updated != null) return updated.getFirstAttribute(name);
-        return cached.getAttributes().getFirst(name);
-    }
-
-    @Override
-    public List<String> getAttribute(String name) {
-        if (updated != null) return updated.getAttribute(name);
-        List<String> result = cached.getAttributes().get(name);
-        return (result == null) ? Collections.<String>emptyList() : result;
-    }
-
-    @Override
-    public Map<String, List<String>> getAttributes() {
-        if (updated != null) return updated.getAttributes();
-        return cached.getAttributes();
-    }
-
-    @Override
-    public Set<String> getRequiredActions() {
-        if (updated != null) return updated.getRequiredActions();
-        return cached.getRequiredActions();
-    }
-
-    @Override
-    public void addRequiredAction(RequiredAction action) {
-        getDelegateForUpdate();
-        updated.addRequiredAction(action);
-    }
-
-    @Override
-    public void removeRequiredAction(RequiredAction action) {
-        getDelegateForUpdate();
-        updated.removeRequiredAction(action);
-    }
-
-    @Override
-    public void addRequiredAction(String action) {
-        getDelegateForUpdate();
-        updated.addRequiredAction(action);
-    }
-
-    @Override
-    public void removeRequiredAction(String action) {
-        getDelegateForUpdate();
-        updated.removeRequiredAction(action);
-    }
-
-    @Override
-    public String getFirstName() {
-        if (updated != null) return updated.getFirstName();
-        return cached.getFirstName();
-    }
-
-    @Override
-    public void setFirstName(String firstName) {
-        getDelegateForUpdate();
-        updated.setFirstName(firstName);
-    }
-
-    @Override
-    public String getLastName() {
-        if (updated != null) return updated.getLastName();
-        return cached.getLastName();
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        getDelegateForUpdate();
-        updated.setLastName(lastName);
-    }
-
-    @Override
-    public String getEmail() {
-        if (updated != null) return updated.getEmail();
-        return cached.getEmail();
-    }
-
-    @Override
-    public void setEmail(String email) {
-        getDelegateForUpdate();
-        updated.setEmail(email);
-    }
-
-    @Override
-    public boolean isEmailVerified() {
-        if (updated != null) return updated.isEmailVerified();
-        return cached.isEmailVerified();
-    }
-
-    @Override
-    public void setEmailVerified(boolean verified) {
-        getDelegateForUpdate();
-        updated.setEmailVerified(verified);
-    }
-
-    @Override
-    public void setTotp(boolean totp) {
-        getDelegateForUpdate();
-        updated.setTotp(totp);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-        getDelegateForUpdate();
-        updated.updateCredential(cred);
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly() {
-        if (updated != null) return updated.getCredentialsDirectly();
-        return cached.getCredentials();
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel cred) {
-        getDelegateForUpdate();
-        updated.updateCredentialDirectly(cred);
-    }
-
-    @Override
-    public String getFederationLink() {
-        if (updated != null) return updated.getFederationLink();
-        return cached.getFederationLink();
-    }
-
-    @Override
-    public void setFederationLink(String link) {
-        getDelegateForUpdate();
-        updated.setFederationLink(link);
-   }
-
-    @Override
-    public Set<RoleModel> getRealmRoleMappings() {
-        if (updated != null) return updated.getRealmRoleMappings();
-        Set<RoleModel> roleMappings = getRoleMappings();
-        Set<RoleModel> realmMappings = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-                if (((RealmModel) container).getId().equals(realm.getId())) {
-                    realmMappings.add(role);
-                }
-            }
-        }
-        return realmMappings;
-    }
-
-    @Override
-    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        if (updated != null) return updated.getClientRoleMappings(app);
-        Set<RoleModel> roleMappings = getRoleMappings();
-        Set<RoleModel> appMappings = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof ClientModel) {
-                if (((ClientModel) container).getId().equals(app.getId())) {
-                    appMappings.add(role);
-                }
-            }
-        }
-        return appMappings;
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        if (updated != null) return updated.hasRole(role);
-        if (cached.getRoleMappings().contains(role.getId())) return true;
-
-        Set<RoleModel> mappings = getRoleMappings();
-        for (RoleModel mapping: mappings) {
-           if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void grantRole(RoleModel role) {
-        getDelegateForUpdate();
-        updated.grantRole(role);
-    }
-
-    @Override
-    public Set<RoleModel> getRoleMappings() {
-        if (updated != null) return updated.getRoleMappings();
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String id : cached.getRoleMappings()) {
-            RoleModel roleById = keycloakSession.realms().getRoleById(id, realm);
-            if (roleById == null) {
-                // chance that role was removed, so just delete to persistence and get user invalidated
-                getDelegateForUpdate();
-                return updated.getRoleMappings();
-            }
-            roles.add(roleById);
-
-        }
-        return roles;
-    }
-
-    @Override
-    public void deleteRoleMapping(RoleModel role) {
-        getDelegateForUpdate();
-        updated.deleteRoleMapping(role);
-    }
-
-    @Override
-    public void addConsent(UserConsentModel consent) {
-        getDelegateForUpdate();
-        updated.addConsent(consent);
-    }
-
-    @Override
-    public UserConsentModel getConsentByClient(String clientId) {
-        // TODO: caching?
-        getDelegateForUpdate();
-        return updated.getConsentByClient(clientId);
-    }
-
-    @Override
-    public List<UserConsentModel> getConsents() {
-        // TODO: caching?
-        getDelegateForUpdate();
-        return updated.getConsents();
-    }
-
-    @Override
-    public void updateConsent(UserConsentModel consent) {
-        getDelegateForUpdate();
-        updated.updateConsent(consent);
-    }
-
-    @Override
-    public boolean revokeConsentForClient(String clientId) {
-        getDelegateForUpdate();
-        return updated.revokeConsentForClient(clientId);
-    }
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.cache.entities.CachedUser;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAdapter implements UserModel {
+    protected UserModel updated;
+    protected CachedUser cached;
+    protected CacheUserProvider userProviderCache;
+    protected KeycloakSession keycloakSession;
+    protected RealmModel realm;
+
+    public UserAdapter(CachedUser cached, CacheUserProvider userProvider, KeycloakSession keycloakSession, RealmModel realm) {
+        this.cached = cached;
+        this.userProviderCache = userProvider;
+        this.keycloakSession = keycloakSession;
+        this.realm = realm;
+    }
+
+    protected void getDelegateForUpdate() {
+        if (updated == null) {
+            userProviderCache.registerUserInvalidation(realm, getId());
+            updated = userProviderCache.getDelegate().getUserById(getId(), realm);
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
+    @Override
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
+
+    @Override
+    public String getUsername() {
+        if (updated != null) return updated.getUsername();
+        return cached.getUsername();
+    }
+
+    @Override
+    public void setUsername(String username) {
+        getDelegateForUpdate();
+        updated.setUsername(username);
+    }
+
+    @Override
+    public Long getCreatedTimestamp() {
+        // get from cached always as it is immutable
+        return cached.getCreatedTimestamp();
+    }
+
+    @Override
+    public void setCreatedTimestamp(Long timestamp) {
+        // nothing to do as this value is immutable
+    }
+
+    @Override
+    public boolean isEnabled() {
+        if (updated != null) return updated.isEnabled();
+        return cached.isEnabled();
+    }
+
+    @Override
+    public boolean isTotp() {
+        if (updated != null) return updated.isTotp();
+        return cached.isTotp();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setEnabled(enabled);
+    }
+
+    @Override
+    public void setSingleAttribute(String name, String value) {
+        getDelegateForUpdate();
+        updated.setSingleAttribute(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, List<String> values) {
+        getDelegateForUpdate();
+        updated.setAttribute(name, values);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        getDelegateForUpdate();
+        updated.removeAttribute(name);
+    }
+
+    @Override
+    public String getFirstAttribute(String name) {
+        if (updated != null) return updated.getFirstAttribute(name);
+        return cached.getAttributes().getFirst(name);
+    }
+
+    @Override
+    public List<String> getAttribute(String name) {
+        if (updated != null) return updated.getAttribute(name);
+        List<String> result = cached.getAttributes().get(name);
+        return (result == null) ? Collections.<String>emptyList() : result;
+    }
+
+    @Override
+    public Map<String, List<String>> getAttributes() {
+        if (updated != null) return updated.getAttributes();
+        return cached.getAttributes();
+    }
+
+    @Override
+    public Set<String> getRequiredActions() {
+        if (updated != null) return updated.getRequiredActions();
+        return cached.getRequiredActions();
+    }
+
+    @Override
+    public void addRequiredAction(RequiredAction action) {
+        getDelegateForUpdate();
+        updated.addRequiredAction(action);
+    }
+
+    @Override
+    public void removeRequiredAction(RequiredAction action) {
+        getDelegateForUpdate();
+        updated.removeRequiredAction(action);
+    }
+
+    @Override
+    public void addRequiredAction(String action) {
+        getDelegateForUpdate();
+        updated.addRequiredAction(action);
+    }
+
+    @Override
+    public void removeRequiredAction(String action) {
+        getDelegateForUpdate();
+        updated.removeRequiredAction(action);
+    }
+
+    @Override
+    public String getFirstName() {
+        if (updated != null) return updated.getFirstName();
+        return cached.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        getDelegateForUpdate();
+        updated.setFirstName(firstName);
+    }
+
+    @Override
+    public String getLastName() {
+        if (updated != null) return updated.getLastName();
+        return cached.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        getDelegateForUpdate();
+        updated.setLastName(lastName);
+    }
+
+    @Override
+    public String getEmail() {
+        if (updated != null) return updated.getEmail();
+        return cached.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        getDelegateForUpdate();
+        updated.setEmail(email);
+    }
+
+    @Override
+    public boolean isEmailVerified() {
+        if (updated != null) return updated.isEmailVerified();
+        return cached.isEmailVerified();
+    }
+
+    @Override
+    public void setEmailVerified(boolean verified) {
+        getDelegateForUpdate();
+        updated.setEmailVerified(verified);
+    }
+
+    @Override
+    public void setTotp(boolean totp) {
+        getDelegateForUpdate();
+        updated.setTotp(totp);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        getDelegateForUpdate();
+        updated.updateCredential(cred);
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        if (updated != null) return updated.getCredentialsDirectly();
+        return cached.getCredentials();
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel cred) {
+        getDelegateForUpdate();
+        updated.updateCredentialDirectly(cred);
+    }
+
+    @Override
+    public String getFederationLink() {
+        if (updated != null) return updated.getFederationLink();
+        return cached.getFederationLink();
+    }
+
+    @Override
+    public void setFederationLink(String link) {
+        getDelegateForUpdate();
+        updated.setFederationLink(link);
+   }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings() {
+        if (updated != null) return updated.getRealmRoleMappings();
+        Set<RoleModel> roleMappings = getRoleMappings();
+        Set<RoleModel> realmMappings = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+                if (((RealmModel) container).getId().equals(realm.getId())) {
+                    realmMappings.add(role);
+                }
+            }
+        }
+        return realmMappings;
+    }
+
+    @Override
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        if (updated != null) return updated.getClientRoleMappings(app);
+        Set<RoleModel> roleMappings = getRoleMappings();
+        Set<RoleModel> appMappings = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof ClientModel) {
+                if (((ClientModel) container).getId().equals(app.getId())) {
+                    appMappings.add(role);
+                }
+            }
+        }
+        return appMappings;
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        if (updated != null) return updated.hasRole(role);
+        if (cached.getRoleMappings().contains(role.getId())) return true;
+
+        Set<RoleModel> mappings = getRoleMappings();
+        for (RoleModel mapping: mappings) {
+           if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void grantRole(RoleModel role) {
+        getDelegateForUpdate();
+        updated.grantRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoleMappings() {
+        if (updated != null) return updated.getRoleMappings();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String id : cached.getRoleMappings()) {
+            RoleModel roleById = keycloakSession.realms().getRoleById(id, realm);
+            if (roleById == null) {
+                // chance that role was removed, so just delete to persistence and get user invalidated
+                getDelegateForUpdate();
+                return updated.getRoleMappings();
+            }
+            roles.add(roleById);
+
+        }
+        return roles;
+    }
+
+    @Override
+    public void deleteRoleMapping(RoleModel role) {
+        getDelegateForUpdate();
+        updated.deleteRoleMapping(role);
+    }
+
+    @Override
+    public void addConsent(UserConsentModel consent) {
+        getDelegateForUpdate();
+        updated.addConsent(consent);
+    }
+
+    @Override
+    public UserConsentModel getConsentByClient(String clientId) {
+        // TODO: caching?
+        getDelegateForUpdate();
+        return updated.getConsentByClient(clientId);
+    }
+
+    @Override
+    public List<UserConsentModel> getConsents() {
+        // TODO: caching?
+        getDelegateForUpdate();
+        return updated.getConsents();
+    }
+
+    @Override
+    public void updateConsent(UserConsentModel consent) {
+        getDelegateForUpdate();
+        updated.updateConsent(consent);
+    }
+
+    @Override
+    public boolean revokeConsentForClient(String clientId) {
+        getDelegateForUpdate();
+        return updated.revokeConsentForClient(clientId);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
index 61f1188..9b0336f 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
@@ -1,29 +1,29 @@
-package org.keycloak.models.cache;
-
-import org.keycloak.models.cache.entities.CachedUser;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface UserCache {
-    void clear();
-
-    CachedUser getCachedUser(String realmId, String id);
-
-    void invalidateCachedUser(String realmId, CachedUser user);
-
-    void addCachedUser(String realmId, CachedUser user);
-
-    CachedUser getCachedUserByUsername(String realmId, String name);
-
-    CachedUser getCachedUserByEmail(String realmId, String name);
-
-    void invalidateCachedUserById(String realmId, String id);
-
-    void invalidateRealmUsers(String realmId);
-
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
-}
+package org.keycloak.models.cache;
+
+import org.keycloak.models.cache.entities.CachedUser;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserCache {
+    void clear();
+
+    CachedUser getCachedUser(String realmId, String id);
+
+    void invalidateCachedUser(String realmId, CachedUser user);
+
+    void addCachedUser(String realmId, CachedUser user);
+
+    CachedUser getCachedUserByUsername(String realmId, String name);
+
+    CachedUser getCachedUserByEmail(String realmId, String name);
+
+    void invalidateCachedUserById(String realmId, String id);
+
+    void invalidateRealmUsers(String realmId);
+
+    boolean isEnabled();
+
+    void setEnabled(boolean enabled);
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheRealmProviderFactory b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheRealmProviderFactory
index 82ddea9..4d92613 100755
--- a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheRealmProviderFactory
+++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheRealmProviderFactory
@@ -1,2 +1,2 @@
-org.keycloak.models.cache.MemoryCacheRealmProviderFactory
+org.keycloak.models.cache.MemoryCacheRealmProviderFactory
 org.keycloak.models.cache.NoCacheRealmProviderFactory
\ No newline at end of file
diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory
index 438f9e1..a2f107f 100755
--- a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory
+++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory
@@ -1,2 +1,2 @@
-org.keycloak.models.cache.MemoryCacheUserProviderFactory
-org.keycloak.models.cache.NoCacheUserProviderFactory
+org.keycloak.models.cache.MemoryCacheUserProviderFactory
+org.keycloak.models.cache.NoCacheUserProviderFactory
diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index d793d8a..0b60b88 100755
--- a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,2 +1,2 @@
-org.keycloak.models.cache.CacheRealmProviderSpi
+org.keycloak.models.cache.CacheRealmProviderSpi
 org.keycloak.models.cache.CacheUserProviderSpi
\ No newline at end of file
diff --git a/model/invalidation-cache/pom.xml b/model/invalidation-cache/pom.xml
index e48a4d0..ace9e00 100755
--- a/model/invalidation-cache/pom.xml
+++ b/model/invalidation-cache/pom.xml
@@ -1,31 +1,31 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak Model Invalidation Cache Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-invalidation-cache-model-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>model-adapters</module>
-        <module>infinispan</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak Model Invalidation Cache Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-invalidation-cache-model-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>model-adapters</module>
+        <module>infinispan</module>
+    </modules>
+</project>

model/jpa/pom.xml 188(+94 -94)

diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml
index d96c261..51b5281 100755
--- a/model/jpa/pom.xml
+++ b/model/jpa/pom.xml
@@ -1,94 +1,94 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-jpa</artifactId>
-    <name>Keycloak Model JPA</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-invalidation-cache-model</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-sessions-mem</artifactId>
-            <scope>test</scope>
-
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-jpa</artifactId>
+    <name>Keycloak Model JPA</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-sessions-mem</artifactId>
+            <scope>test</scope>
+
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index 7e4906a..704d987 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -1,675 +1,675 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.jpa.entities.ClientEntity;
-import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
-import org.keycloak.models.jpa.entities.RoleEntity;
-import org.keycloak.models.jpa.entities.ScopeMappingEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientAdapter implements ClientModel {
-
-    protected KeycloakSession session;
-    protected RealmModel realm;
-    protected EntityManager em;
-    protected ClientEntity entity;
-
-    public ClientAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientEntity entity) {
-        this.session = session;
-        this.realm = realm;
-        this.em = em;
-        this.entity = entity;
-    }
-
-    public ClientEntity getEntity() {
-        return entity;
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public String getName() {
-        return entity.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        entity.setName(name);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return entity.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        entity.setEnabled(enabled);
-    }
-
-    @Override
-    public boolean isPublicClient() {
-        return entity.isPublicClient();
-    }
-
-    @Override
-    public void setPublicClient(boolean flag) {
-        entity.setPublicClient(flag);
-    }
-
-    @Override
-    public boolean isFrontchannelLogout() {
-        return entity.isFrontchannelLogout();
-    }
-
-    @Override
-    public void setFrontchannelLogout(boolean flag) {
-        entity.setFrontchannelLogout(flag);
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        return entity.isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        entity.setFullScopeAllowed(value);
-    }
-
-    @Override
-    public Set<String> getWebOrigins() {
-        Set<String> result = new HashSet<String>();
-        result.addAll(entity.getWebOrigins());
-        return result;
-    }
-
-
-
-    @Override
-    public void setWebOrigins(Set<String> webOrigins) {
-        entity.setWebOrigins(webOrigins);
-    }
-
-    @Override
-    public void addWebOrigin(String webOrigin) {
-        entity.getWebOrigins().add(webOrigin);
-    }
-
-    @Override
-    public void removeWebOrigin(String webOrigin) {
-        entity.getWebOrigins().remove(webOrigin);
-    }
-
-    @Override
-    public Set<String> getRedirectUris() {
-        Set<String> result = new HashSet<String>();
-        result.addAll(entity.getRedirectUris());
-        return result;
-    }
-
-    @Override
-    public void setRedirectUris(Set<String> redirectUris) {
-        entity.setRedirectUris(redirectUris);
-    }
-
-    @Override
-    public void addRedirectUri(String redirectUri) {
-        entity.getRedirectUris().add(redirectUri);
-    }
-
-    @Override
-    public void removeRedirectUri(String redirectUri) {
-        entity.getRedirectUris().remove(redirectUri);
-    }
-
-    @Override
-    public String getSecret() {
-        return entity.getSecret();
-    }
-
-    @Override
-    public void setSecret(String secret) {
-        entity.setSecret(secret);
-    }
-
-    @Override
-    public boolean validateSecret(String secret) {
-        return secret.equals(entity.getSecret());
-    }
-
-    @Override
-    public int getNotBefore() {
-        return entity.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        entity.setNotBefore(notBefore);
-    }
-
-    @Override
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> roleMappings = getScopeMappings();
-
-        Set<RoleModel> appRoles = new HashSet<>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-                if (((RealmModel) container).getId().equals(realm.getId())) {
-                    appRoles.add(role);
-                }
-            }
-        }
-
-        return appRoles;
-    }
-
-    @Override
-    public Set<RoleModel> getScopeMappings() {
-        TypedQuery<String> query = em.createNamedQuery("clientScopeMappingIds", String.class);
-        query.setParameter("client", getEntity());
-        List<String> ids = query.getResultList();
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String roleId : ids) {
-            RoleModel role = realm.getRoleById(roleId);
-            if (role == null) continue;
-            roles.add(role);
-        }
-        return roles;
-    }
-
-    @Override
-    public void addScopeMapping(RoleModel role) {
-        if (hasScope(role)) return;
-        ScopeMappingEntity entity = new ScopeMappingEntity();
-        entity.setClient(getEntity());
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        entity.setRole(roleEntity);
-        em.persist(entity);
-        em.flush();
-        em.detach(entity);
-    }
-
-    @Override
-    public void deleteScopeMapping(RoleModel role) {
-        TypedQuery<ScopeMappingEntity> query = getRealmScopeMappingQuery(role);
-        List<ScopeMappingEntity> results = query.getResultList();
-        if (results.size() == 0) return;
-        for (ScopeMappingEntity entity : results) {
-            em.remove(entity);
-        }
-    }
-
-    protected TypedQuery<ScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
-        TypedQuery<ScopeMappingEntity> query = em.createNamedQuery("hasScope", ScopeMappingEntity.class);
-        query.setParameter("client", getEntity());
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        query.setParameter("role", roleEntity);
-        return query;
-    }
-
-    @Override
-    public String getProtocol() {
-        return entity.getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        entity.setProtocol(protocol);
-
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        entity.getAttributes().put(name, value);
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        entity.getAttributes().remove(name);
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        return entity.getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getAttributes());
-        return copy;
-    }
-
-    public static boolean contains(String str, String[] array) {
-        for (String s : array) {
-            if (str.equals(s)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        Set<ProtocolMapperModel> mappings = new HashSet<ProtocolMapperModel>();
-        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
-            ProtocolMapperModel mapping = new ProtocolMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setProtocol(entity.getProtocol());
-            mapping.setProtocolMapper(entity.getProtocolMapper());
-            mapping.setConsentRequired(entity.isConsentRequired());
-            mapping.setConsentText(entity.getConsentText());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
-        ProtocolMapperEntity entity = new ProtocolMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setProtocol(model.getProtocol());
-        entity.setProtocolMapper(model.getProtocolMapper());
-        entity.setClient(this.entity);
-        entity.setConfig(model.getConfig());
-        entity.setConsentRequired(model.isConsentRequired());
-        entity.setConsentText(model.getConsentText());
-
-        em.persist(entity);
-        this.entity.getProtocolMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntity(String id) {
-        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
-        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
-            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity toDelete = getProtocolMapperEntity(mapping.getId());
-        if (toDelete != null) {
-            session.users().preRemove(this, mapping);
-
-            this.entity.getProtocolMappers().remove(toDelete);
-            em.remove(toDelete);
-        }
-
-    }
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity entity = getProtocolMapperEntity(mapping.getId());
-        entity.setProtocolMapper(mapping.getProtocolMapper());
-        entity.setConsentRequired(mapping.isConsentRequired());
-        entity.setConsentText(mapping.getConsentText());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapping.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        }
-        em.flush();
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        ProtocolMapperEntity entity = getProtocolMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
-        ProtocolMapperModel mapping = new ProtocolMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setProtocol(entity.getProtocol());
-        mapping.setProtocolMapper(entity.getProtocolMapper());
-        mapping.setConsentRequired(entity.isConsentRequired());
-        mapping.setConsentText(entity.getConsentText());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-    @Override
-    public void updateClient() {
-        em.flush();
-    }
-
-    @Override
-    public String getClientId() {
-        return entity.getClientId();
-    }
-
-    @Override
-    public void setClientId(String clientId) {
-        entity.setClientId(clientId);
-    }
-
-    @Override
-    public boolean isSurrogateAuthRequired() {
-        return entity.isSurrogateAuthRequired();
-    }
-
-    @Override
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        entity.setSurrogateAuthRequired(surrogateAuthRequired);
-    }
-
-    @Override
-    public String getManagementUrl() {
-        return entity.getManagementUrl();
-    }
-
-    @Override
-    public void setManagementUrl(String url) {
-        entity.setManagementUrl(url);
-    }
-
-    @Override
-    public String getBaseUrl() {
-        return entity.getBaseUrl();
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-        entity.setBaseUrl(url);
-    }
-
-    @Override
-    public boolean isBearerOnly() {
-        return entity.isBearerOnly();
-    }
-
-    @Override
-    public void setBearerOnly(boolean only) {
-        entity.setBearerOnly(only);
-    }
-
-    @Override
-    public boolean isConsentRequired() {
-        return entity.isConsentRequired();
-    }
-
-    @Override
-    public void setConsentRequired(boolean consentRequired) {
-        entity.setConsentRequired(consentRequired);
-    }
-
-    @Override
-    public boolean isDirectGrantsOnly() {
-        return entity.isDirectGrantsOnly();
-    }
-
-    @Override
-    public void setDirectGrantsOnly(boolean flag) {
-        entity.setDirectGrantsOnly(flag);
-    }
-
-    @Override
-    public RoleModel getRole(String name) {
-        TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoleByName", RoleEntity.class);
-        query.setParameter("name", name);
-        query.setParameter("client", entity);
-        List<RoleEntity> roles = query.getResultList();
-        if (roles.size() == 0) return null;
-        return new RoleAdapter(realm, em, roles.get(0));
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        return this.addRole(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        RoleEntity roleEntity = new RoleEntity();
-        roleEntity.setId(id);
-        roleEntity.setName(name);
-        roleEntity.setClient(entity);
-        roleEntity.setClientRole(true);
-        roleEntity.setRealmId(realm.getId());
-        em.persist(roleEntity);
-        entity.getRoles().add(roleEntity);
-        em.flush();
-        return new RoleAdapter(realm, em, roleEntity);
-    }
-
-    @Override
-    public boolean removeRole(RoleModel roleModel) {
-        if (roleModel == null) {
-            return false;
-        }
-        if (!roleModel.getContainer().equals(this)) return false;
-
-        session.users().preRemove(getRealm(), roleModel);
-        RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
-        if (!role.isClientRole()) return false;
-
-        entity.getRoles().remove(role);
-        entity.getDefaultRoles().remove(role);
-        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
-        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate();
-        role.setClient(null);
-        em.flush();
-        em.remove(role);
-        em.flush();
-
-        return true;
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        Set<RoleModel> list = new HashSet<RoleModel>();
-        Collection<RoleEntity> roles = entity.getRoles();
-        if (roles == null) return list;
-        for (RoleEntity entity : roles) {
-            list.add(new RoleAdapter(realm, em, entity));
-        }
-        return list;
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        roles = getRoles();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
-        Set<RoleModel> roleMappings = client.getScopeMappings();
-
-        Set<RoleModel> appRoles = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-            } else {
-                ClientModel app = (ClientModel)container;
-                if (app.getId().equals(getId())) {
-                    appRoles.add(role);
-                }
-            }
-        }
-
-        return appRoles;
-    }
-
-
-
-
-    @Override
-    public List<String> getDefaultRoles() {
-        Collection<RoleEntity> entities = entity.getDefaultRoles();
-        List<String> roles = new ArrayList<String>();
-        if (entities == null) return roles;
-        for (RoleEntity entity : entities) {
-            roles.add(entity.getName());
-        }
-        return roles;
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            role = addRole(name);
-        }
-        Collection<RoleEntity> entities = entity.getDefaultRoles();
-        for (RoleEntity entity : entities) {
-            if (entity.getId().equals(role.getId())) {
-                return;
-            }
-        }
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        entities.add(roleEntity);
-        em.flush();
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        Collection<RoleEntity> entities = entity.getDefaultRoles();
-        Set<String> already = new HashSet<String>();
-        List<RoleEntity> remove = new ArrayList<RoleEntity>();
-        for (RoleEntity rel : entities) {
-            if (!contains(rel.getName(), defaultRoles)) {
-                remove.add(rel);
-            } else {
-                already.add(rel.getName());
-            }
-        }
-        for (RoleEntity entity : remove) {
-            entities.remove(entity);
-        }
-        em.flush();
-        for (String roleName : defaultRoles) {
-            if (!already.contains(roleName)) {
-                addDefaultRole(roleName);
-            }
-        }
-        em.flush();
-    }
-
-    @Override
-    public int getNodeReRegistrationTimeout() {
-        return entity.getNodeReRegistrationTimeout();
-    }
-
-    @Override
-    public void setNodeReRegistrationTimeout(int timeout) {
-        entity.setNodeReRegistrationTimeout(timeout);
-    }
-
-    @Override
-    public Map<String, Integer> getRegisteredNodes() {
-        return entity.getRegisteredNodes();
-    }
-
-    @Override
-    public void registerNode(String nodeHost, int registrationTime) {
-        Map<String, Integer> currentNodes = getRegisteredNodes();
-        currentNodes.put(nodeHost, registrationTime);
-        em.flush();
-    }
-
-    @Override
-    public void unregisterNode(String nodeHost) {
-        Map<String, Integer> currentNodes = getRegisteredNodes();
-        currentNodes.remove(nodeHost);
-        em.flush();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof ClientModel)) return false;
-
-        ClientModel that = (ClientModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    public String toString() {
-        return getClientId();
-    }
-
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.jpa.entities.ClientEntity;
+import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.jpa.entities.ScopeMappingEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientAdapter implements ClientModel {
+
+    protected KeycloakSession session;
+    protected RealmModel realm;
+    protected EntityManager em;
+    protected ClientEntity entity;
+
+    public ClientAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientEntity entity) {
+        this.session = session;
+        this.realm = realm;
+        this.em = em;
+        this.entity = entity;
+    }
+
+    public ClientEntity getEntity() {
+        return entity;
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public String getName() {
+        return entity.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        entity.setName(name);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return entity.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        entity.setEnabled(enabled);
+    }
+
+    @Override
+    public boolean isPublicClient() {
+        return entity.isPublicClient();
+    }
+
+    @Override
+    public void setPublicClient(boolean flag) {
+        entity.setPublicClient(flag);
+    }
+
+    @Override
+    public boolean isFrontchannelLogout() {
+        return entity.isFrontchannelLogout();
+    }
+
+    @Override
+    public void setFrontchannelLogout(boolean flag) {
+        entity.setFrontchannelLogout(flag);
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        return entity.isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        entity.setFullScopeAllowed(value);
+    }
+
+    @Override
+    public Set<String> getWebOrigins() {
+        Set<String> result = new HashSet<String>();
+        result.addAll(entity.getWebOrigins());
+        return result;
+    }
+
+
+
+    @Override
+    public void setWebOrigins(Set<String> webOrigins) {
+        entity.setWebOrigins(webOrigins);
+    }
+
+    @Override
+    public void addWebOrigin(String webOrigin) {
+        entity.getWebOrigins().add(webOrigin);
+    }
+
+    @Override
+    public void removeWebOrigin(String webOrigin) {
+        entity.getWebOrigins().remove(webOrigin);
+    }
+
+    @Override
+    public Set<String> getRedirectUris() {
+        Set<String> result = new HashSet<String>();
+        result.addAll(entity.getRedirectUris());
+        return result;
+    }
+
+    @Override
+    public void setRedirectUris(Set<String> redirectUris) {
+        entity.setRedirectUris(redirectUris);
+    }
+
+    @Override
+    public void addRedirectUri(String redirectUri) {
+        entity.getRedirectUris().add(redirectUri);
+    }
+
+    @Override
+    public void removeRedirectUri(String redirectUri) {
+        entity.getRedirectUris().remove(redirectUri);
+    }
+
+    @Override
+    public String getSecret() {
+        return entity.getSecret();
+    }
+
+    @Override
+    public void setSecret(String secret) {
+        entity.setSecret(secret);
+    }
+
+    @Override
+    public boolean validateSecret(String secret) {
+        return secret.equals(entity.getSecret());
+    }
+
+    @Override
+    public int getNotBefore() {
+        return entity.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        entity.setNotBefore(notBefore);
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> roleMappings = getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+                if (((RealmModel) container).getId().equals(realm.getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings() {
+        TypedQuery<String> query = em.createNamedQuery("clientScopeMappingIds", String.class);
+        query.setParameter("client", getEntity());
+        List<String> ids = query.getResultList();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String roleId : ids) {
+            RoleModel role = realm.getRoleById(roleId);
+            if (role == null) continue;
+            roles.add(role);
+        }
+        return roles;
+    }
+
+    @Override
+    public void addScopeMapping(RoleModel role) {
+        if (hasScope(role)) return;
+        ScopeMappingEntity entity = new ScopeMappingEntity();
+        entity.setClient(getEntity());
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        entity.setRole(roleEntity);
+        em.persist(entity);
+        em.flush();
+        em.detach(entity);
+    }
+
+    @Override
+    public void deleteScopeMapping(RoleModel role) {
+        TypedQuery<ScopeMappingEntity> query = getRealmScopeMappingQuery(role);
+        List<ScopeMappingEntity> results = query.getResultList();
+        if (results.size() == 0) return;
+        for (ScopeMappingEntity entity : results) {
+            em.remove(entity);
+        }
+    }
+
+    protected TypedQuery<ScopeMappingEntity> getRealmScopeMappingQuery(RoleModel role) {
+        TypedQuery<ScopeMappingEntity> query = em.createNamedQuery("hasScope", ScopeMappingEntity.class);
+        query.setParameter("client", getEntity());
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        query.setParameter("role", roleEntity);
+        return query;
+    }
+
+    @Override
+    public String getProtocol() {
+        return entity.getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        entity.setProtocol(protocol);
+
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        entity.getAttributes().put(name, value);
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        entity.getAttributes().remove(name);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return entity.getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getAttributes());
+        return copy;
+    }
+
+    public static boolean contains(String str, String[] array) {
+        for (String s : array) {
+            if (str.equals(s)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> mappings = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setProtocol(entity.getProtocol());
+            mapping.setProtocolMapper(entity.getProtocolMapper());
+            mapping.setConsentRequired(entity.isConsentRequired());
+            mapping.setConsentText(entity.getConsentText());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setProtocol(model.getProtocol());
+        entity.setProtocolMapper(model.getProtocolMapper());
+        entity.setClient(this.entity);
+        entity.setConfig(model.getConfig());
+        entity.setConsentRequired(model.isConsentRequired());
+        entity.setConsentText(model.getConsentText());
+
+        em.persist(entity);
+        this.entity.getProtocolMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntity(String id) {
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity toDelete = getProtocolMapperEntity(mapping.getId());
+        if (toDelete != null) {
+            session.users().preRemove(this, mapping);
+
+            this.entity.getProtocolMappers().remove(toDelete);
+            em.remove(toDelete);
+        }
+
+    }
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolMapperEntity(mapping.getId());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
+        entity.setConsentRequired(mapping.isConsentRequired());
+        entity.setConsentText(mapping.getConsentText());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapping.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        }
+        em.flush();
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
+        mapping.setConsentRequired(entity.isConsentRequired());
+        mapping.setConsentText(entity.getConsentText());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+    @Override
+    public void updateClient() {
+        em.flush();
+    }
+
+    @Override
+    public String getClientId() {
+        return entity.getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        entity.setClientId(clientId);
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return entity.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        entity.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return entity.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        entity.setManagementUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return entity.getBaseUrl();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        entity.setBaseUrl(url);
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return entity.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        entity.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return entity.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        entity.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return entity.isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        entity.setDirectGrantsOnly(flag);
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoleByName", RoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("client", entity);
+        List<RoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(realm, em, roles.get(0));
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        RoleEntity roleEntity = new RoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setClient(entity);
+        roleEntity.setClientRole(true);
+        roleEntity.setRealmId(realm.getId());
+        em.persist(roleEntity);
+        entity.getRoles().add(roleEntity);
+        em.flush();
+        return new RoleAdapter(realm, em, roleEntity);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel roleModel) {
+        if (roleModel == null) {
+            return false;
+        }
+        if (!roleModel.getContainer().equals(this)) return false;
+
+        session.users().preRemove(getRealm(), roleModel);
+        RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
+        if (!role.isClientRole()) return false;
+
+        entity.getRoles().remove(role);
+        entity.getDefaultRoles().remove(role);
+        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
+        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate();
+        role.setClient(null);
+        em.flush();
+        em.remove(role);
+        em.flush();
+
+        return true;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        Set<RoleModel> list = new HashSet<RoleModel>();
+        Collection<RoleEntity> roles = entity.getRoles();
+        if (roles == null) return list;
+        for (RoleEntity entity : roles) {
+            list.add(new RoleAdapter(realm, em, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> roleMappings = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ClientModel app = (ClientModel)container;
+                if (app.getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+
+
+
+    @Override
+    public List<String> getDefaultRoles() {
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        List<String> roles = new ArrayList<String>();
+        if (entities == null) return roles;
+        for (RoleEntity entity : entities) {
+            roles.add(entity.getName());
+        }
+        return roles;
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            role = addRole(name);
+        }
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        for (RoleEntity entity : entities) {
+            if (entity.getId().equals(role.getId())) {
+                return;
+            }
+        }
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        entities.add(roleEntity);
+        em.flush();
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        Set<String> already = new HashSet<String>();
+        List<RoleEntity> remove = new ArrayList<RoleEntity>();
+        for (RoleEntity rel : entities) {
+            if (!contains(rel.getName(), defaultRoles)) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getName());
+            }
+        }
+        for (RoleEntity entity : remove) {
+            entities.remove(entity);
+        }
+        em.flush();
+        for (String roleName : defaultRoles) {
+            if (!already.contains(roleName)) {
+                addDefaultRole(roleName);
+            }
+        }
+        em.flush();
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return entity.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        entity.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return entity.getRegisteredNodes();
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        Map<String, Integer> currentNodes = getRegisteredNodes();
+        currentNodes.put(nodeHost, registrationTime);
+        em.flush();
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        Map<String, Integer> currentNodes = getRegisteredNodes();
+        currentNodes.remove(nodeHost);
+        em.flush();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    public String toString() {
+        return getClientId();
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
index c5e9019..60dfccd 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
@@ -1,139 +1,139 @@
-package org.keycloak.models.jpa.entities;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="AUTHENTICATION_EXECUTION")
-@Entity
-@NamedQueries({
-        @NamedQuery(name="getAuthenticationExecutionsByFlow", query="select authenticator from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
-        @NamedQuery(name="deleteAuthenticationExecutionsByRealm", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm"),
-        @NamedQuery(name="deleteAuthenticationExecutionsByRealmAndFlow", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
-})
-public class AuthenticationExecutionEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "FLOW_ID")
-    protected AuthenticationFlowEntity parentFlow;
-
-    @Column(name="AUTHENTICATOR")
-    protected String authenticator;
-
-    @Column(name="AUTH_CONFIG")
-    protected String authenticatorConfig;
-
-    @Column(name="AUTH_FLOW_ID")
-    protected String flowId;
-
-    @Column(name="REQUIREMENT")
-    protected AuthenticationExecutionModel.Requirement requirement;
-
-    @Column(name="PRIORITY")
-    protected int priority;
-
-    @Column(name="USER_SETUP_ALLOWED")
-    private boolean userSetupAllowed;
-
-    @Column(name="AUTHENTICATOR_FLOW")
-    private boolean autheticatorFlow;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public String getAuthenticator() {
-        return authenticator;
-    }
-
-    public void setAuthenticator(String authenticator) {
-        this.authenticator = authenticator;
-    }
-
-    public AuthenticationExecutionModel.Requirement getRequirement() {
-        return requirement;
-    }
-
-    public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
-        this.requirement = requirement;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public boolean isUserSetupAllowed() {
-        return userSetupAllowed;
-    }
-
-    public void setUserSetupAllowed(boolean userSetupAllowed) {
-        this.userSetupAllowed = userSetupAllowed;
-    }
-
-    public boolean isAutheticatorFlow() {
-        return autheticatorFlow;
-    }
-
-    public void setAutheticatorFlow(boolean autheticatorFlow) {
-        this.autheticatorFlow = autheticatorFlow;
-    }
-
-    public AuthenticationFlowEntity getParentFlow() {
-        return parentFlow;
-    }
-
-    public void setParentFlow(AuthenticationFlowEntity flow) {
-        this.parentFlow = flow;
-    }
-
-    public String getFlowId() {
-        return flowId;
-    }
-
-    public void setFlowId(String flowId) {
-        this.flowId = flowId;
-    }
-
-    public String getAuthenticatorConfig() {
-        return authenticatorConfig;
-    }
-
-    public void setAuthenticatorConfig(String authenticatorConfig) {
-        this.authenticatorConfig = authenticatorConfig;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="AUTHENTICATION_EXECUTION")
+@Entity
+@NamedQueries({
+        @NamedQuery(name="getAuthenticationExecutionsByFlow", query="select authenticator from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
+        @NamedQuery(name="deleteAuthenticationExecutionsByRealm", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm"),
+        @NamedQuery(name="deleteAuthenticationExecutionsByRealmAndFlow", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.parentFlow = :parentFlow"),
+})
+public class AuthenticationExecutionEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "FLOW_ID")
+    protected AuthenticationFlowEntity parentFlow;
+
+    @Column(name="AUTHENTICATOR")
+    protected String authenticator;
+
+    @Column(name="AUTH_CONFIG")
+    protected String authenticatorConfig;
+
+    @Column(name="AUTH_FLOW_ID")
+    protected String flowId;
+
+    @Column(name="REQUIREMENT")
+    protected AuthenticationExecutionModel.Requirement requirement;
+
+    @Column(name="PRIORITY")
+    protected int priority;
+
+    @Column(name="USER_SETUP_ALLOWED")
+    private boolean userSetupAllowed;
+
+    @Column(name="AUTHENTICATOR_FLOW")
+    private boolean autheticatorFlow;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public String getAuthenticator() {
+        return authenticator;
+    }
+
+    public void setAuthenticator(String authenticator) {
+        this.authenticator = authenticator;
+    }
+
+    public AuthenticationExecutionModel.Requirement getRequirement() {
+        return requirement;
+    }
+
+    public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
+        this.requirement = requirement;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public boolean isUserSetupAllowed() {
+        return userSetupAllowed;
+    }
+
+    public void setUserSetupAllowed(boolean userSetupAllowed) {
+        this.userSetupAllowed = userSetupAllowed;
+    }
+
+    public boolean isAutheticatorFlow() {
+        return autheticatorFlow;
+    }
+
+    public void setAutheticatorFlow(boolean autheticatorFlow) {
+        this.autheticatorFlow = autheticatorFlow;
+    }
+
+    public AuthenticationFlowEntity getParentFlow() {
+        return parentFlow;
+    }
+
+    public void setParentFlow(AuthenticationFlowEntity flow) {
+        this.parentFlow = flow;
+    }
+
+    public String getFlowId() {
+        return flowId;
+    }
+
+    public void setFlowId(String flowId) {
+        this.flowId = flowId;
+    }
+
+    public String getAuthenticatorConfig() {
+        return authenticatorConfig;
+    }
+
+    public void setAuthenticatorConfig(String authenticatorConfig) {
+        this.authenticatorConfig = authenticatorConfig;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
index 622ef19..f62b7d3 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
@@ -1,117 +1,117 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="AUTHENTICATION_FLOW")
-@Entity
-@NamedQueries({
-        @NamedQuery(name="getAuthenticationFlowsByRealm", query="select flow from AuthenticationFlowEntity flow where flow.realm = :realm"),
-        @NamedQuery(name="deleteAuthenticationFlowByRealm", query="delete from AuthenticationFlowEntity flow where flow.realm = :realm")
-})
-public class AuthenticationFlowEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @Column(name="ALIAS")
-    protected String alias;
-
-    @Column(name="PROVIDER_ID")
-    protected String providerId;
-
-    @Column(name="DESCRIPTION")
-    protected String description;
-
-    @Column(name="TOP_LEVEL")
-    protected boolean topLevel;
-
-    @Column(name="BUILT_IN")
-    protected boolean builtIn;
-
-
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "parentFlow")
-    Collection<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Collection<AuthenticationExecutionEntity> getExecutions() {
-        return executions;
-    }
-
-    public void setExecutions(Collection<AuthenticationExecutionEntity> executions) {
-        this.executions = executions;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public boolean isTopLevel() {
-        return topLevel;
-    }
-
-    public void setTopLevel(boolean topLevel) {
-        this.topLevel = topLevel;
-    }
-
-    public boolean isBuiltIn() {
-        return builtIn;
-    }
-
-    public void setBuiltIn(boolean builtIn) {
-        this.builtIn = builtIn;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="AUTHENTICATION_FLOW")
+@Entity
+@NamedQueries({
+        @NamedQuery(name="getAuthenticationFlowsByRealm", query="select flow from AuthenticationFlowEntity flow where flow.realm = :realm"),
+        @NamedQuery(name="deleteAuthenticationFlowByRealm", query="delete from AuthenticationFlowEntity flow where flow.realm = :realm")
+})
+public class AuthenticationFlowEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @Column(name="ALIAS")
+    protected String alias;
+
+    @Column(name="PROVIDER_ID")
+    protected String providerId;
+
+    @Column(name="DESCRIPTION")
+    protected String description;
+
+    @Column(name="TOP_LEVEL")
+    protected boolean topLevel;
+
+    @Column(name="BUILT_IN")
+    protected boolean builtIn;
+
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "parentFlow")
+    Collection<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Collection<AuthenticationExecutionEntity> getExecutions() {
+        return executions;
+    }
+
+    public void setExecutions(Collection<AuthenticationExecutionEntity> executions) {
+        this.executions = executions;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public boolean isTopLevel() {
+        return topLevel;
+    }
+
+    public void setTopLevel(boolean topLevel) {
+        this.topLevel = topLevel;
+    }
+
+    public boolean isBuiltIn() {
+        return builtIn;
+    }
+
+    public void setBuiltIn(boolean builtIn) {
+        this.builtIn = builtIn;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
index ae97860..7a4e2c9 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
@@ -1,72 +1,72 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="AUTHENTICATOR_CONFIG")
-@Entity
-public class AuthenticatorConfigEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="ALIAS")
-    protected String alias;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @ElementCollection
-    @MapKeyColumn(name="NAME")
-    @Column(name="VALUE")
-    @CollectionTable(name="AUTHENTICATOR_CONFIG_ENTRY", joinColumns={ @JoinColumn(name="AUTHENTICATOR_ID") })
-    private Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="AUTHENTICATOR_CONFIG")
+@Entity
+public class AuthenticatorConfigEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="ALIAS")
+    protected String alias;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE")
+    @CollectionTable(name="AUTHENTICATOR_CONFIG_ENTRY", joinColumns={ @JoinColumn(name="AUTHENTICATOR_ID") })
+    private Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index ff6f14c..a42fa67 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -1,321 +1,321 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CascadeType;
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "CLIENT_ID"})})
-public class ClientEntity {
-
-    @Id
-    @Column(name="ID", length = 36)
-    private String id;
-    @Column(name = "NAME")
-    private String name;
-    @Column(name = "CLIENT_ID")
-    private String clientId;
-    @Column(name="ENABLED")
-    private boolean enabled;
-    @Column(name="SECRET")
-    private String secret;
-    @Column(name="NOT_BEFORE")
-    private int notBefore;
-    @Column(name="PUBLIC_CLIENT")
-    private boolean publicClient;
-    @Column(name="PROTOCOL")
-    private String protocol;
-    @Column(name="FRONTCHANNEL_LOGOUT")
-    private boolean frontchannelLogout;
-    @Column(name="FULL_SCOPE_ALLOWED")
-    private boolean fullScopeAllowed;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @ElementCollection
-    @Column(name="VALUE")
-    @CollectionTable(name = "WEB_ORIGINS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
-    protected Set<String> webOrigins = new HashSet<String>();
-
-    @ElementCollection
-    @Column(name="VALUE")
-    @CollectionTable(name = "REDIRECT_URIS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
-    protected Set<String> redirectUris = new HashSet<String>();
-
-    @ElementCollection
-    @MapKeyColumn(name="NAME")
-    @Column(name="VALUE", length = 2048)
-    @CollectionTable(name="CLIENT_ATTRIBUTES", joinColumns={ @JoinColumn(name="CLIENT_ID") })
-    protected Map<String, String> attributes = new HashMap<String, String>();
-
-    @OneToMany(fetch = FetchType.LAZY, mappedBy = "client", cascade = CascadeType.REMOVE)
-    Collection<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client")
-    Collection<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
-
-    @Column(name="SURROGATE_AUTH_REQUIRED")
-    private boolean surrogateAuthRequired;
-
-    @Column(name="BASE_URL")
-    private String baseUrl;
-
-    @Column(name="MANAGEMENT_URL")
-    private String managementUrl;
-
-    @Column(name="DIRECT_GRANTS_ONLY")
-    protected boolean directGrantsOnly;
-
-    @Column(name="BEARER_ONLY")
-    private boolean bearerOnly;
-
-    @Column(name="CONSENT_REQUIRED")
-    private boolean consentRequired;
-
-    @Column(name="NODE_REREG_TIMEOUT")
-    private int nodeReRegistrationTimeout;
-
-    @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client")
-    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
-
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
-    Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
-
-    @ElementCollection
-    @MapKeyColumn(name="NAME")
-    @Column(name="VALUE")
-    @CollectionTable(name="CLIENT_NODE_REGISTRATIONS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
-    Map<String, Integer> registeredNodes = new HashMap<String, Integer>();
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public Set<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public void setWebOrigins(Set<String> webOrigins) {
-        this.webOrigins = webOrigins;
-    }
-
-    public Set<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public void setRedirectUris(Set<String> redirectUris) {
-        this.redirectUris = redirectUris;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public void setFullScopeAllowed(boolean fullScopeAllowed) {
-        this.fullScopeAllowed = fullScopeAllowed;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, String> attributes) {
-        this.attributes = attributes;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public void setFrontchannelLogout(boolean frontchannelLogout) {
-        this.frontchannelLogout = frontchannelLogout;
-    }
-
-    public Collection<ClientIdentityProviderMappingEntity> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(Collection<ClientIdentityProviderMappingEntity> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public Collection<ProtocolMapperEntity> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(Collection<ProtocolMapperEntity> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public boolean isSurrogateAuthRequired() {
-        return surrogateAuthRequired;
-    }
-
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        this.surrogateAuthRequired = surrogateAuthRequired;
-    }
-
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
-    public String getManagementUrl() {
-        return managementUrl;
-    }
-
-    public void setManagementUrl(String managementUrl) {
-        this.managementUrl = managementUrl;
-    }
-
-    public Collection<RoleEntity> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(Collection<RoleEntity> roles) {
-        this.roles = roles;
-    }
-
-    public Collection<RoleEntity> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
-        this.defaultRoles = defaultRoles;
-    }
-
-    public boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public void setBearerOnly(boolean bearerOnly) {
-        this.bearerOnly = bearerOnly;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public boolean isDirectGrantsOnly() {
-        return directGrantsOnly;
-    }
-
-    public void setDirectGrantsOnly(boolean directGrantsOnly) {
-        this.directGrantsOnly = directGrantsOnly;
-    }
-
-    public int getNodeReRegistrationTimeout() {
-        return nodeReRegistrationTimeout;
-    }
-
-    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
-        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
-    }
-
-    public Map<String, Integer> getRegisteredNodes() {
-        return registeredNodes;
-    }
-
-    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
-        this.registeredNodes = registeredNodes;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "CLIENT_ID"})})
+public class ClientEntity {
+
+    @Id
+    @Column(name="ID", length = 36)
+    private String id;
+    @Column(name = "NAME")
+    private String name;
+    @Column(name = "CLIENT_ID")
+    private String clientId;
+    @Column(name="ENABLED")
+    private boolean enabled;
+    @Column(name="SECRET")
+    private String secret;
+    @Column(name="NOT_BEFORE")
+    private int notBefore;
+    @Column(name="PUBLIC_CLIENT")
+    private boolean publicClient;
+    @Column(name="PROTOCOL")
+    private String protocol;
+    @Column(name="FRONTCHANNEL_LOGOUT")
+    private boolean frontchannelLogout;
+    @Column(name="FULL_SCOPE_ALLOWED")
+    private boolean fullScopeAllowed;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name = "WEB_ORIGINS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
+    protected Set<String> webOrigins = new HashSet<String>();
+
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name = "REDIRECT_URIS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
+    protected Set<String> redirectUris = new HashSet<String>();
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE", length = 2048)
+    @CollectionTable(name="CLIENT_ATTRIBUTES", joinColumns={ @JoinColumn(name="CLIENT_ID") })
+    protected Map<String, String> attributes = new HashMap<String, String>();
+
+    @OneToMany(fetch = FetchType.LAZY, mappedBy = "client", cascade = CascadeType.REMOVE)
+    Collection<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client")
+    Collection<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
+
+    @Column(name="SURROGATE_AUTH_REQUIRED")
+    private boolean surrogateAuthRequired;
+
+    @Column(name="BASE_URL")
+    private String baseUrl;
+
+    @Column(name="MANAGEMENT_URL")
+    private String managementUrl;
+
+    @Column(name="DIRECT_GRANTS_ONLY")
+    protected boolean directGrantsOnly;
+
+    @Column(name="BEARER_ONLY")
+    private boolean bearerOnly;
+
+    @Column(name="CONSENT_REQUIRED")
+    private boolean consentRequired;
+
+    @Column(name="NODE_REREG_TIMEOUT")
+    private int nodeReRegistrationTimeout;
+
+    @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client")
+    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
+    @JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
+    Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE")
+    @CollectionTable(name="CLIENT_NODE_REGISTRATIONS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
+    Map<String, Integer> registeredNodes = new HashMap<String, Integer>();
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public Set<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public void setWebOrigins(Set<String> webOrigins) {
+        this.webOrigins = webOrigins;
+    }
+
+    public Set<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public void setRedirectUris(Set<String> redirectUris) {
+        this.redirectUris = redirectUris;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public void setFullScopeAllowed(boolean fullScopeAllowed) {
+        this.fullScopeAllowed = fullScopeAllowed;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public void setFrontchannelLogout(boolean frontchannelLogout) {
+        this.frontchannelLogout = frontchannelLogout;
+    }
+
+    public Collection<ClientIdentityProviderMappingEntity> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public void setIdentityProviders(Collection<ClientIdentityProviderMappingEntity> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public Collection<ProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Collection<ProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        this.surrogateAuthRequired = surrogateAuthRequired;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public String getManagementUrl() {
+        return managementUrl;
+    }
+
+    public void setManagementUrl(String managementUrl) {
+        this.managementUrl = managementUrl;
+    }
+
+    public Collection<RoleEntity> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Collection<RoleEntity> roles) {
+        this.roles = roles;
+    }
+
+    public Collection<RoleEntity> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public void setDirectGrantsOnly(boolean directGrantsOnly) {
+        this.directGrantsOnly = directGrantsOnly;
+    }
+
+    public int getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
+        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+
+    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
+        this.registeredNodes = registeredNodes;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientIdentityProviderMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientIdentityProviderMappingEntity.java
index 2fd87ae..4870a21 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientIdentityProviderMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientIdentityProviderMappingEntity.java
@@ -1,121 +1,121 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author pedroigor
- */
-@Table(name="CLIENT_IDENTITY_PROV_MAPPING")
-@Entity
-@IdClass(ClientIdentityProviderMappingEntity.Key.class)
-public class ClientIdentityProviderMappingEntity {
-
-    @Id
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_ID")
-    private ClientEntity client;
-
-    @Id
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "IDENTITY_PROVIDER_ID")
-    private IdentityProviderEntity identityProvider;
-
-    @Column(name = "RETRIEVE_TOKEN")
-    private boolean retrieveToken;
-
-    public ClientEntity getClient() {
-        return this.client;
-    }
-
-    public void setClient(ClientEntity client) {
-        this.client = client;
-    }
-
-    public IdentityProviderEntity getIdentityProvider() {
-        return this.identityProvider;
-    }
-
-    public void setIdentityProvider(IdentityProviderEntity identityProvider) {
-        this.identityProvider = identityProvider;
-    }
-
-    public void setRetrieveToken(boolean retrieveToken) {
-        this.retrieveToken = retrieveToken;
-    }
-
-    public boolean isRetrieveToken() {
-        return retrieveToken;
-    }
-
-    public static class Key implements Serializable {
-
-        private ClientEntity client;
-        private IdentityProviderEntity identityProvider;
-
-        public Key() {
-        }
-
-        public Key(ClientEntity client, IdentityProviderEntity identityProvider) {
-            this.client = client;
-            this.identityProvider = identityProvider;
-        }
-
-        public ClientEntity getUser() {
-            return client;
-        }
-
-        public IdentityProviderEntity getIdentityProvider() {
-            return identityProvider;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (identityProvider != null ? !identityProvider.getAlias().equals(key.identityProvider.getAlias()) : key.identityProvider != null)
-                return false;
-            if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = client != null ? client.getId().hashCode() : 0;
-            result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
-            return result;
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ClientIdentityProviderMappingEntity key = (ClientIdentityProviderMappingEntity) o;
-
-        if (identityProvider != null ? !identityProvider.getAlias().equals(key.identityProvider.getAlias()) : key.identityProvider != null)
-            return false;
-        if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = client != null ? client.getId().hashCode() : 0;
-        result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
-        return result;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author pedroigor
+ */
+@Table(name="CLIENT_IDENTITY_PROV_MAPPING")
+@Entity
+@IdClass(ClientIdentityProviderMappingEntity.Key.class)
+public class ClientIdentityProviderMappingEntity {
+
+    @Id
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_ID")
+    private ClientEntity client;
+
+    @Id
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "IDENTITY_PROVIDER_ID")
+    private IdentityProviderEntity identityProvider;
+
+    @Column(name = "RETRIEVE_TOKEN")
+    private boolean retrieveToken;
+
+    public ClientEntity getClient() {
+        return this.client;
+    }
+
+    public void setClient(ClientEntity client) {
+        this.client = client;
+    }
+
+    public IdentityProviderEntity getIdentityProvider() {
+        return this.identityProvider;
+    }
+
+    public void setIdentityProvider(IdentityProviderEntity identityProvider) {
+        this.identityProvider = identityProvider;
+    }
+
+    public void setRetrieveToken(boolean retrieveToken) {
+        this.retrieveToken = retrieveToken;
+    }
+
+    public boolean isRetrieveToken() {
+        return retrieveToken;
+    }
+
+    public static class Key implements Serializable {
+
+        private ClientEntity client;
+        private IdentityProviderEntity identityProvider;
+
+        public Key() {
+        }
+
+        public Key(ClientEntity client, IdentityProviderEntity identityProvider) {
+            this.client = client;
+            this.identityProvider = identityProvider;
+        }
+
+        public ClientEntity getUser() {
+            return client;
+        }
+
+        public IdentityProviderEntity getIdentityProvider() {
+            return identityProvider;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (identityProvider != null ? !identityProvider.getAlias().equals(key.identityProvider.getAlias()) : key.identityProvider != null)
+                return false;
+            if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = client != null ? client.getId().hashCode() : 0;
+            result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
+            return result;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClientIdentityProviderMappingEntity key = (ClientIdentityProviderMappingEntity) o;
+
+        if (identityProvider != null ? !identityProvider.getAlias().equals(key.identityProvider.getAlias()) : key.identityProvider != null)
+            return false;
+        if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = client != null ? client.getId().hashCode() : 0;
+        result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
index 998c469..f247f01 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
@@ -1,111 +1,111 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type"),
-        @NamedQuery(name="deleteCredentialsByRealm", query="delete from CredentialEntity cred where cred.user IN (select u from UserEntity u where u.realmId=:realmId)"),
-        @NamedQuery(name="deleteCredentialsByRealmAndLink", query="delete from CredentialEntity cred where cred.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
-
-})
-@Table(name="CREDENTIAL")
-@Entity
-public class CredentialEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="TYPE")
-    protected String type;
-    @Column(name="VALUE")
-    protected String value;
-    @Column(name="DEVICE")
-    protected String device;
-    @Column(name="SALT")
-    protected byte[] salt;
-    @Column(name="HASH_ITERATIONS")
-    protected int hashIterations;
-    @Column(name="CREATED_DATE")
-    protected Long createdDate;
-    
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name="USER_ID")
-    protected UserEntity user;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getDevice() {
-        return device;
-    }
-
-    public void setDevice(String device) {
-        this.device = device;
-    }
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-    public byte[] getSalt() {
-        return salt;
-    }
-
-    public void setSalt(byte[] salt) {
-        this.salt = salt;
-    }
-
-    public int getHashIterations() {
-        return hashIterations;
-    }
-
-    public void setHashIterations(int hashIterations) {
-        this.hashIterations = hashIterations;
-    }
-
-    public Long getCreatedDate() {
-        return createdDate;
-    }
-
-    public void setCreatedDate(Long createdDate) {
-        this.createdDate = createdDate;
-    }
-    
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type"),
+        @NamedQuery(name="deleteCredentialsByRealm", query="delete from CredentialEntity cred where cred.user IN (select u from UserEntity u where u.realmId=:realmId)"),
+        @NamedQuery(name="deleteCredentialsByRealmAndLink", query="delete from CredentialEntity cred where cred.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
+
+})
+@Table(name="CREDENTIAL")
+@Entity
+public class CredentialEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="TYPE")
+    protected String type;
+    @Column(name="VALUE")
+    protected String value;
+    @Column(name="DEVICE")
+    protected String device;
+    @Column(name="SALT")
+    protected byte[] salt;
+    @Column(name="HASH_ITERATIONS")
+    protected int hashIterations;
+    @Column(name="CREATED_DATE")
+    protected Long createdDate;
+    
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name="USER_ID")
+    protected UserEntity user;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getDevice() {
+        return device;
+    }
+
+    public void setDevice(String device) {
+        this.device = device;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    public byte[] getSalt() {
+        return salt;
+    }
+
+    public void setSalt(byte[] salt) {
+        this.salt = salt;
+    }
+
+    public int getHashIterations() {
+        return hashIterations;
+    }
+
+    public void setHashIterations(int hashIterations) {
+        this.hashIterations = hashIterations;
+    }
+
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public void setCreatedDate(Long createdDate) {
+        this.createdDate = createdDate;
+    }
+    
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/FederatedIdentityEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/FederatedIdentityEntity.java
index ccb1465..6e92982 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/FederatedIdentityEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/FederatedIdentityEntity.java
@@ -1,143 +1,143 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name= "findFederatedIdentityByUser", query="select link from FederatedIdentityEntity link where link.user = :user"),
-        @NamedQuery(name= "findFederatedIdentityByUserAndProvider", query="select link from FederatedIdentityEntity link where link.user = :user and link.identityProvider = :identityProvider"),
-        @NamedQuery(name= "findUserByFederatedIdentityAndRealm", query="select link.user from FederatedIdentityEntity link where link.realmId = :realmId and link.identityProvider = :identityProvider and link.userId = :userId"),
-        @NamedQuery(name= "deleteFederatedIdentityByRealm", query="delete from FederatedIdentityEntity social where social.user IN (select u from UserEntity u where realmId=:realmId)"),
-        @NamedQuery(name= "deleteFederatedIdentityByRealmAndLink", query="delete from FederatedIdentityEntity social where social.user IN (select u from UserEntity u where realmId=:realmId and u.federationLink=:link)"),
-        @NamedQuery(name= "deleteFederatedIdentityByUser", query="delete from FederatedIdentityEntity social where social.user = :user")
-})
-@Table(name="FEDERATED_IDENTITY")
-@Entity
-@IdClass(FederatedIdentityEntity.Key.class)
-public class FederatedIdentityEntity {
-
-    @Id
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "USER_ID")
-    private UserEntity user;
-
-    @Column(name = "REALM_ID")
-    protected String realmId;
-
-    @Id
-    @Column(name = "IDENTITY_PROVIDER")
-    protected String identityProvider;
-    @Column(name = "FEDERATED_USER_ID")
-    protected String userId;
-    @Column(name = "FEDERATED_USERNAME")
-    protected String userName;
-
-    @Column(name = "TOKEN")
-    protected String token;
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-    public String getIdentityProvider() {
-        return identityProvider;
-    }
-
-    public void setIdentityProvider(String identityProvider) {
-        this.identityProvider = identityProvider;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    public String getUserName() {
-        return userName;
-    }
-
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public void setToken(String token) {
-        this.token = token;
-    }
-
-    public String getToken() {
-        return token;
-    }
-
-    public static class Key implements Serializable {
-
-        protected UserEntity user;
-
-        protected String identityProvider;
-
-        public Key() {
-        }
-
-        public Key(UserEntity user, String identityProvider) {
-            this.user = user;
-            this.identityProvider = identityProvider;
-        }
-
-        public UserEntity getUser() {
-            return user;
-        }
-
-        public String getIdentityProvider() {
-            return identityProvider;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (identityProvider != null ? !identityProvider.equals(key.identityProvider) : key.identityProvider != null)
-                return false;
-            if (user != null ? !user.getId().equals(key.user != null ? key.user.getId() : null) : key.user != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = user != null ? user.getId().hashCode() : 0;
-            result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name= "findFederatedIdentityByUser", query="select link from FederatedIdentityEntity link where link.user = :user"),
+        @NamedQuery(name= "findFederatedIdentityByUserAndProvider", query="select link from FederatedIdentityEntity link where link.user = :user and link.identityProvider = :identityProvider"),
+        @NamedQuery(name= "findUserByFederatedIdentityAndRealm", query="select link.user from FederatedIdentityEntity link where link.realmId = :realmId and link.identityProvider = :identityProvider and link.userId = :userId"),
+        @NamedQuery(name= "deleteFederatedIdentityByRealm", query="delete from FederatedIdentityEntity social where social.user IN (select u from UserEntity u where realmId=:realmId)"),
+        @NamedQuery(name= "deleteFederatedIdentityByRealmAndLink", query="delete from FederatedIdentityEntity social where social.user IN (select u from UserEntity u where realmId=:realmId and u.federationLink=:link)"),
+        @NamedQuery(name= "deleteFederatedIdentityByUser", query="delete from FederatedIdentityEntity social where social.user = :user")
+})
+@Table(name="FEDERATED_IDENTITY")
+@Entity
+@IdClass(FederatedIdentityEntity.Key.class)
+public class FederatedIdentityEntity {
+
+    @Id
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "USER_ID")
+    private UserEntity user;
+
+    @Column(name = "REALM_ID")
+    protected String realmId;
+
+    @Id
+    @Column(name = "IDENTITY_PROVIDER")
+    protected String identityProvider;
+    @Column(name = "FEDERATED_USER_ID")
+    protected String userId;
+    @Column(name = "FEDERATED_USERNAME")
+    protected String userName;
+
+    @Column(name = "TOKEN")
+    protected String token;
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    public String getIdentityProvider() {
+        return identityProvider;
+    }
+
+    public void setIdentityProvider(String identityProvider) {
+        this.identityProvider = identityProvider;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public static class Key implements Serializable {
+
+        protected UserEntity user;
+
+        protected String identityProvider;
+
+        public Key() {
+        }
+
+        public Key(UserEntity user, String identityProvider) {
+            this.user = user;
+            this.identityProvider = identityProvider;
+        }
+
+        public UserEntity getUser() {
+            return user;
+        }
+
+        public String getIdentityProvider() {
+            return identityProvider;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (identityProvider != null ? !identityProvider.equals(key.identityProvider) : key.identityProvider != null)
+                return false;
+            if (user != null ? !user.getId().equals(key.user != null ? key.user.getId() : null) : key.user != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = user != null ? user.getId().hashCode() : 0;
+            result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
index feaa8b9..35787db 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
@@ -1,109 +1,109 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.Table;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name="IDENTITY_PROVIDER_MAPPER")
-public class IdentityProviderMapperEntity {
-
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="NAME")
-    protected String name;
-
-    @Column(name = "IDP_ALIAS")
-    protected String identityProviderAlias;
-    @Column(name = "IDP_MAPPER_NAME")
-    protected String identityProviderMapper;
-
-    @ElementCollection
-    @MapKeyColumn(name="name")
-    @Column(name="value")
-    @CollectionTable(name="IDP_MAPPER_CONFIG", joinColumns={ @JoinColumn(name="IDP_MAPPER_ID") })
-    private Map<String, String> config;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    private RealmEntity realm;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getIdentityProviderAlias() {
-        return identityProviderAlias;
-    }
-
-    public void setIdentityProviderAlias(String identityProviderAlias) {
-        this.identityProviderAlias = identityProviderAlias;
-    }
-
-    public String getIdentityProviderMapper() {
-        return identityProviderMapper;
-    }
-
-    public void setIdentityProviderMapper(String identityProviderMapper) {
-        this.identityProviderMapper = identityProviderMapper;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        IdentityProviderMapperEntity that = (IdentityProviderMapperEntity) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.Table;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name="IDENTITY_PROVIDER_MAPPER")
+public class IdentityProviderMapperEntity {
+
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="NAME")
+    protected String name;
+
+    @Column(name = "IDP_ALIAS")
+    protected String identityProviderAlias;
+    @Column(name = "IDP_MAPPER_NAME")
+    protected String identityProviderMapper;
+
+    @ElementCollection
+    @MapKeyColumn(name="name")
+    @Column(name="value")
+    @CollectionTable(name="IDP_MAPPER_CONFIG", joinColumns={ @JoinColumn(name="IDP_MAPPER_ID") })
+    private Map<String, String> config;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    private RealmEntity realm;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getIdentityProviderAlias() {
+        return identityProviderAlias;
+    }
+
+    public void setIdentityProviderAlias(String identityProviderAlias) {
+        this.identityProviderAlias = identityProviderAlias;
+    }
+
+    public String getIdentityProviderMapper() {
+        return identityProviderMapper;
+    }
+
+    public void setIdentityProviderMapper(String identityProviderMapper) {
+        this.identityProviderMapper = identityProviderMapper;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        IdentityProviderMapperEntity that = (IdentityProviderMapperEntity) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
index a29873e..2e7d209 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
@@ -1,43 +1,43 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="MIGRATION_MODEL")
-@Entity
-public class MigrationModelEntity {
-    public static final String SINGLETON_ID = "SINGLETON";
-    @Id
-    @Column(name="ID", length = 36)
-    private String id;
-
-    @Column(name="VERSION", length = 36)
-    protected String version;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="MIGRATION_MODEL")
+@Entity
+public class MigrationModelEntity {
+    public static final String SINGLETON_ID = "SINGLETON";
+    @Id
+    @Column(name="ID", length = 36)
+    private String id;
+
+    @Column(name="VERSION", length = 36)
+    protected String version;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
index ccce0d9..54872d8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
@@ -1,129 +1,129 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.Table;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name="PROTOCOL_MAPPER")
-public class ProtocolMapperEntity {
-
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="NAME")
-    protected String name;
-
-    @Column(name = "PROTOCOL")
-    protected String protocol;
-    @Column(name = "PROTOCOL_MAPPER_NAME")
-    protected String protocolMapper;
-    @Column(name="CONSENT_REQUIRED")
-    protected boolean consentRequired;
-    @Column(name="CONSENT_TEXT")
-    protected String consentText;
-
-    @ElementCollection
-    @MapKeyColumn(name="name")
-    @Column(name="value")
-    @CollectionTable(name="PROTOCOL_MAPPER_CONFIG", joinColumns={ @JoinColumn(name="PROTOCOL_MAPPER_ID") })
-    private Map<String, String> config;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_ID")
-    private ClientEntity client;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public String getProtocolMapper() {
-        return protocolMapper;
-    }
-
-    public void setProtocolMapper(String protocolMapper) {
-        this.protocolMapper = protocolMapper;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public ClientEntity getClient() {
-        return client;
-    }
-
-    public void setClient(ClientEntity client) {
-        this.client = client;
-    }
-
-    public boolean isConsentRequired() {
-        return consentRequired;
-    }
-
-    public void setConsentRequired(boolean consentRequired) {
-        this.consentRequired = consentRequired;
-    }
-
-    public String getConsentText() {
-        return consentText;
-    }
-
-    public void setConsentText(String consentText) {
-        this.consentText = consentText;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ProtocolMapperEntity that = (ProtocolMapperEntity) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.Table;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name="PROTOCOL_MAPPER")
+public class ProtocolMapperEntity {
+
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="NAME")
+    protected String name;
+
+    @Column(name = "PROTOCOL")
+    protected String protocol;
+    @Column(name = "PROTOCOL_MAPPER_NAME")
+    protected String protocolMapper;
+    @Column(name="CONSENT_REQUIRED")
+    protected boolean consentRequired;
+    @Column(name="CONSENT_TEXT")
+    protected String consentText;
+
+    @ElementCollection
+    @MapKeyColumn(name="name")
+    @Column(name="value")
+    @CollectionTable(name="PROTOCOL_MAPPER_CONFIG", joinColumns={ @JoinColumn(name="PROTOCOL_MAPPER_ID") })
+    private Map<String, String> config;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_ID")
+    private ClientEntity client;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProtocolMapper() {
+        return protocolMapper;
+    }
+
+    public void setProtocolMapper(String protocolMapper) {
+        this.protocolMapper = protocolMapper;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public ClientEntity getClient() {
+        return client;
+    }
+
+    public void setClient(ClientEntity client) {
+        this.client = client;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public String getConsentText() {
+        return consentText;
+    }
+
+    public void setConsentText(String consentText) {
+        this.consentText = consentText;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ProtocolMapperEntity that = (ProtocolMapperEntity) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributeEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributeEntity.java
index 2e025cc..2f13f6c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributeEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmAttributeEntity.java
@@ -1,105 +1,105 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="deleteRealmAttributesByRealm", query="delete from RealmAttributeEntity attr where attr.realm = :realm")
-})
-@Table(name="REALM_ATTRIBUTE")
-@Entity
-@IdClass(RealmAttributeEntity.Key.class)
-public class RealmAttributeEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @Id
-    @Column(name = "NAME")
-    protected String name;
-    @Column(name = "VALUE")
-    protected String value;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public static class Key implements Serializable {
-
-        protected RealmEntity realm;
-
-        protected String name;
-
-        public Key() {
-        }
-
-        public Key(RealmEntity user, String name) {
-            this.realm = user;
-            this.name = name;
-        }
-
-        public RealmEntity getRealm() {
-            return realm;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (name != null ? !name.equals(key.name) : key.name != null) return false;
-            if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = realm != null ? realm.getId().hashCode() : 0;
-            result = 31 * result + (name != null ? name.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="deleteRealmAttributesByRealm", query="delete from RealmAttributeEntity attr where attr.realm = :realm")
+})
+@Table(name="REALM_ATTRIBUTE")
+@Entity
+@IdClass(RealmAttributeEntity.Key.class)
+public class RealmAttributeEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @Id
+    @Column(name = "NAME")
+    protected String name;
+    @Column(name = "VALUE")
+    protected String value;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public static class Key implements Serializable {
+
+        protected RealmEntity realm;
+
+        protected String name;
+
+        public Key() {
+        }
+
+        public Key(RealmEntity user, String name) {
+            this.realm = user;
+            this.name = name;
+        }
+
+        public RealmEntity getRealm() {
+            return realm;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (name != null ? !name.equals(key.name) : key.name != null) return false;
+            if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = realm != null ? realm.getId().hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 193f1fa..fe9b10d 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -1,584 +1,584 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CascadeType;
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-import javax.persistence.Table;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="REALM")
-@Entity
-@NamedQueries({
-        @NamedQuery(name="getAllRealms", query="select realm from RealmEntity realm"),
-        @NamedQuery(name="getRealmByName", query="select realm from RealmEntity realm where realm.name = :name"),
-})
-public class RealmEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="NAME", unique = true)
-    protected String name;
-
-    @Column(name="ENABLED")
-    protected boolean enabled;
-    @Column(name="SSL_REQUIRED")
-    protected String sslRequired;
-    @Column(name="REGISTRATION_ALLOWED")
-    protected boolean registrationAllowed;
-    @Column(name = "REG_EMAIL_AS_USERNAME")
-    protected boolean registrationEmailAsUsername;
-    @Column(name="VERIFY_EMAIL")
-    protected boolean verifyEmail;
-    @Column(name="RESET_PASSWORD_ALLOWED")
-    protected boolean resetPasswordAllowed;
-    @Column(name="REMEMBER_ME")
-    protected boolean rememberMe;
-    @Column(name="PASSWORD_POLICY")
-    protected String passwordPolicy;
-    @Column(name="EDIT_USERNAME_ALLOWED")
-    protected boolean editUsernameAllowed;
-
-    @Column(name="SSO_IDLE_TIMEOUT")
-    private int ssoSessionIdleTimeout;
-    @Column(name="SSO_MAX_LIFESPAN")
-    private int ssoSessionMaxLifespan;
-    @Column(name="ACCESS_TOKEN_LIFESPAN")
-    protected int accessTokenLifespan;
-    @Column(name="ACCESS_CODE_LIFESPAN")
-    protected int accessCodeLifespan;
-    @Column(name="USER_ACTION_LIFESPAN")
-    protected int accessCodeLifespanUserAction;
-    @Column(name="LOGIN_LIFESPAN")
-    protected int accessCodeLifespanLogin;
-    @Column(name="NOT_BEFORE")
-    protected int notBefore;
-
-    @Column(name="PUBLIC_KEY", length = 2048)
-    protected String publicKeyPem;
-    @Column(name="PRIVATE_KEY", length = 2048)
-    protected String privateKeyPem;
-    @Column(name="CERTIFICATE", length = 2048)
-    protected String certificatePem;
-    @Column(name="CODE_SECRET", length = 255)
-    protected String codeSecret;
-
-    @Column(name="LOGIN_THEME")
-    protected String loginTheme;
-    @Column(name="ACCOUNT_THEME")
-    protected String accountTheme;
-    @Column(name="ADMIN_THEME")
-    protected String adminTheme;
-    @Column(name="EMAIL_THEME")
-    protected String emailTheme;
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<RealmAttributeEntity> attributes = new ArrayList<RealmAttributeEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="FED_PROVIDERS")
-    List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
-
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="REALM_CLIENT", joinColumns={ @JoinColumn(name="REALM_ID") }, inverseJoinColumns={ @JoinColumn(name="CLIENT_ID") })
-    Collection<ClientEntity> clients = new ArrayList<>();
-
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
-
-    @ElementCollection
-    @MapKeyColumn(name="NAME")
-    @Column(name="VALUE")
-    @CollectionTable(name="REALM_SMTP_CONFIG", joinColumns={ @JoinColumn(name="REALM_ID") })
-    protected Map<String, String> smtpConfig = new HashMap<String, String>();
-
-    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
-    @JoinTable(name="REALM_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="REALM_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
-    protected Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
-
-    @Column(name="EVENTS_ENABLED")
-    protected boolean eventsEnabled;
-    @Column(name="EVENTS_EXPIRATION")
-    protected long eventsExpiration;
-
-    @ElementCollection
-    @Column(name="VALUE")
-    @CollectionTable(name="REALM_EVENTS_LISTENERS", joinColumns={ @JoinColumn(name="REALM_ID") })
-    protected Set<String> eventsListeners = new HashSet<String>();
-    
-    @ElementCollection
-    @Column(name="VALUE")
-    @CollectionTable(name="REALM_ENABLED_EVENT_TYPES", joinColumns={ @JoinColumn(name="REALM_ID") })
-    protected Set<String> enabledEventTypes = new HashSet<String>();
-    
-    @Column(name="ADMIN_EVENTS_ENABLED")
-    protected boolean adminEventsEnabled;
-    
-    @Column(name="ADMIN_EVENTS_DETAILS_ENABLED")
-    protected boolean adminEventsDetailsEnabled;
-    
-    @OneToOne
-    @JoinColumn(name="MASTER_ADMIN_CLIENT")
-    protected ClientEntity masterAdminClient;
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    protected List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<AuthenticatorConfigEntity> authenticators = new ArrayList<>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<RequiredActionProviderEntity> requiredActionProviders = new ArrayList<>();
-
-    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<AuthenticationFlowEntity> authenticationFlows = new ArrayList<>();
-
-
-
-    @Column(name="INTERNATIONALIZATION_ENABLED")
-    protected boolean internationalizationEnabled;
-
-    @ElementCollection
-    @Column(name="VALUE")
-    @CollectionTable(name="REALM_SUPPORTED_LOCALES", joinColumns={ @JoinColumn(name="REALM_ID") })
-    protected Set<String> supportedLocales = new HashSet<String>();
-
-    @Column(name="DEFAULT_LOCALE")
-    protected String defaultLocale;
-
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getSslRequired() {
-        return sslRequired;
-    }
-
-    public void setSslRequired(String sslRequired) {
-        this.sslRequired = sslRequired;
-    }
-
-    public boolean isRegistrationAllowed() {
-        return registrationAllowed;
-    }
-
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        this.registrationAllowed = registrationAllowed;
-    }
-
-    public boolean isRegistrationEmailAsUsername() {
-        return registrationEmailAsUsername;
-    }
-
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        this.registrationEmailAsUsername = registrationEmailAsUsername;
-    }
-
-    public boolean isRememberMe() {
-        return rememberMe;
-    }
-
-    public void setRememberMe(boolean rememberMe) {
-        this.rememberMe = rememberMe;
-    }
-
-    public boolean isVerifyEmail() {
-        return verifyEmail;
-    }
-
-    public void setVerifyEmail(boolean verifyEmail) {
-        this.verifyEmail = verifyEmail;
-    }
-
-    public boolean isResetPasswordAllowed() {
-        return resetPasswordAllowed;
-    }
-
-    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
-        this.resetPasswordAllowed = resetPasswordAllowed;
-    }
-
-    public boolean isEditUsernameAllowed() {
-        return editUsernameAllowed;
-    }
-
-    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
-        this.editUsernameAllowed = editUsernameAllowed;
-    }
-
-    public int getSsoSessionIdleTimeout() {
-        return ssoSessionIdleTimeout;
-    }
-
-    public void setSsoSessionIdleTimeout(int ssoSessionIdleTimeout) {
-        this.ssoSessionIdleTimeout = ssoSessionIdleTimeout;
-    }
-
-    public int getSsoSessionMaxLifespan() {
-        return ssoSessionMaxLifespan;
-    }
-
-    public void setSsoSessionMaxLifespan(int ssoSessionMaxLifespan) {
-        this.ssoSessionMaxLifespan = ssoSessionMaxLifespan;
-    }
-
-    public int getAccessTokenLifespan() {
-        return accessTokenLifespan;
-    }
-
-    public void setAccessTokenLifespan(int accessTokenLifespan) {
-        this.accessTokenLifespan = accessTokenLifespan;
-    }
-
-    public int getAccessCodeLifespan() {
-        return accessCodeLifespan;
-    }
-
-    public void setAccessCodeLifespan(int accessCodeLifespan) {
-        this.accessCodeLifespan = accessCodeLifespan;
-    }
-
-    public int getAccessCodeLifespanUserAction() {
-        return accessCodeLifespanUserAction;
-    }
-
-    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
-        this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
-    }
-    public int getAccessCodeLifespanLogin() {
-        return accessCodeLifespanLogin;
-    }
-
-    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
-        this.accessCodeLifespanLogin = accessCodeLifespanLogin;
-    }
-
-    public String getPublicKeyPem() {
-        return publicKeyPem;
-    }
-
-    public void setPublicKeyPem(String publicKeyPem) {
-        this.publicKeyPem = publicKeyPem;
-    }
-
-    public String getPrivateKeyPem() {
-        return privateKeyPem;
-    }
-
-    public void setPrivateKeyPem(String privateKeyPem) {
-        this.privateKeyPem = privateKeyPem;
-    }
-
-    public String getCodeSecret() {
-        return codeSecret;
-    }
-
-    public void setCodeSecret(String codeSecret) {
-        this.codeSecret = codeSecret;
-    }
-
-    public Collection<RequiredCredentialEntity> getRequiredCredentials() {
-        return requiredCredentials;
-    }
-
-    public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
-        this.requiredCredentials = requiredCredentials;
-    }
-
-    public Collection<ClientEntity> getClients() {
-        return clients;
-    }
-
-    public void setClients(Collection<ClientEntity> clients) {
-        this.clients = clients;
-    }
-
-    public Collection<RoleEntity> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(Collection<RoleEntity> roles) {
-        this.roles = roles;
-    }
-
-    public void addRole(RoleEntity role) {
-        if (roles == null) {
-            roles = new ArrayList<RoleEntity>();
-        }
-        roles.add(role);
-    }
-
-    public Map<String, String> getSmtpConfig() {
-        return smtpConfig;
-    }
-
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        this.smtpConfig = smtpConfig;
-    }
-
-    public Collection<RoleEntity> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
-        this.defaultRoles = defaultRoles;
-    }
-
-    public String getPasswordPolicy() {
-        return passwordPolicy;
-    }
-
-    public void setPasswordPolicy(String passwordPolicy) {
-        this.passwordPolicy = passwordPolicy;
-    }
-
-    public String getLoginTheme() {
-        return loginTheme;
-    }
-
-    public void setLoginTheme(String theme) {
-        this.loginTheme = theme;
-    }
-
-    public String getAccountTheme() {
-        return accountTheme;
-    }
-
-    public void setAccountTheme(String theme) {
-        this.accountTheme = theme;
-    }
-
-    public String getAdminTheme() {
-        return adminTheme;
-    }
-
-    public void setAdminTheme(String adminTheme) {
-        this.adminTheme = adminTheme;
-    }
-
-    public String getEmailTheme() {
-        return emailTheme;
-    }
-
-    public void setEmailTheme(String emailTheme) {
-        this.emailTheme = emailTheme;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public boolean isEventsEnabled() {
-        return eventsEnabled;
-    }
-
-    public void setEventsEnabled(boolean eventsEnabled) {
-        this.eventsEnabled = eventsEnabled;
-    }
-
-    public long getEventsExpiration() {
-        return eventsExpiration;
-    }
-
-    public void setEventsExpiration(long eventsExpiration) {
-        this.eventsExpiration = eventsExpiration;
-    }
-
-    public Set<String> getEventsListeners() {
-        return eventsListeners;
-    }
-
-    public void setEventsListeners(Set<String> eventsListeners) {
-        this.eventsListeners = eventsListeners;
-    }
-    
-    public Set<String> getEnabledEventTypes() {
-        return enabledEventTypes;
-    }
-
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        this.enabledEventTypes = enabledEventTypes;
-    }
-    
-    public boolean isAdminEventsEnabled() {
-        return adminEventsEnabled;
-    }
-
-    public void setAdminEventsEnabled(boolean adminEventsEnabled) {
-        this.adminEventsEnabled = adminEventsEnabled;
-    }
-
-    public boolean isAdminEventsDetailsEnabled() {
-        return adminEventsDetailsEnabled;
-    }
-
-    public void setAdminEventsDetailsEnabled(boolean adminEventsDetailsEnabled) {
-        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
-    }
-
-    public ClientEntity getMasterAdminClient() {
-        return masterAdminClient;
-    }
-
-    public void setMasterAdminClient(ClientEntity masterAdminClient) {
-        this.masterAdminClient = masterAdminClient;
-    }
-
-    public List<UserFederationProviderEntity> getUserFederationProviders() {
-        return userFederationProviders;
-    }
-
-    public void setUserFederationProviders(List<UserFederationProviderEntity> userFederationProviders) {
-        this.userFederationProviders = userFederationProviders;
-    }
-
-    public Collection<UserFederationMapperEntity> getUserFederationMappers() {
-        return userFederationMappers;
-    }
-
-    public void setUserFederationMappers(Collection<UserFederationMapperEntity> userFederationMappers) {
-        this.userFederationMappers = userFederationMappers;
-    }
-
-    public Collection<RealmAttributeEntity> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Collection<RealmAttributeEntity> attributes) {
-        this.attributes = attributes;
-    }
-
-    public String getCertificatePem() {
-        return certificatePem;
-    }
-
-    public void setCertificatePem(String certificatePem) {
-        this.certificatePem = certificatePem;
-    }
-
-    public List<IdentityProviderEntity> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(List<IdentityProviderEntity> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public void addIdentityProvider(IdentityProviderEntity entity) {
-        entity.setRealm(this);
-        getIdentityProviders().add(entity);
-    }
-
-    public boolean isInternationalizationEnabled() {
-        return internationalizationEnabled;
-    }
-
-    public void setInternationalizationEnabled(boolean internationalizationEnabled) {
-        this.internationalizationEnabled = internationalizationEnabled;
-    }
-
-    public Set<String> getSupportedLocales() {
-        return supportedLocales;
-    }
-
-    public void setSupportedLocales(Set<String> supportedLocales) {
-        this.supportedLocales = supportedLocales;
-    }
-
-    public String getDefaultLocale() {
-        return defaultLocale;
-    }
-
-    public void setDefaultLocale(String defaultLocale) {
-        this.defaultLocale = defaultLocale;
-    }
-
-    public Collection<IdentityProviderMapperEntity> getIdentityProviderMappers() {
-        return identityProviderMappers;
-    }
-
-    public void setIdentityProviderMappers(Collection<IdentityProviderMapperEntity> identityProviderMappers) {
-        this.identityProviderMappers = identityProviderMappers;
-    }
-
-    public Collection<AuthenticatorConfigEntity> getAuthenticatorConfigs() {
-        return authenticators;
-    }
-
-    public void setAuthenticatorConfigs(Collection<AuthenticatorConfigEntity> authenticators) {
-        this.authenticators = authenticators;
-    }
-
-    public Collection<RequiredActionProviderEntity> getRequiredActionProviders() {
-        return requiredActionProviders;
-    }
-
-    public void setRequiredActionProviders(Collection<RequiredActionProviderEntity> requiredActionProviders) {
-        this.requiredActionProviders = requiredActionProviders;
-    }
-
-    public Collection<AuthenticationFlowEntity> getAuthenticationFlows() {
-        return authenticationFlows;
-    }
-
-    public void setAuthenticationFlows(Collection<AuthenticationFlowEntity> authenticationFlows) {
-        this.authenticationFlows = authenticationFlows;
-    }
-
-}
-
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="REALM")
+@Entity
+@NamedQueries({
+        @NamedQuery(name="getAllRealms", query="select realm from RealmEntity realm"),
+        @NamedQuery(name="getRealmByName", query="select realm from RealmEntity realm where realm.name = :name"),
+})
+public class RealmEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="NAME", unique = true)
+    protected String name;
+
+    @Column(name="ENABLED")
+    protected boolean enabled;
+    @Column(name="SSL_REQUIRED")
+    protected String sslRequired;
+    @Column(name="REGISTRATION_ALLOWED")
+    protected boolean registrationAllowed;
+    @Column(name = "REG_EMAIL_AS_USERNAME")
+    protected boolean registrationEmailAsUsername;
+    @Column(name="VERIFY_EMAIL")
+    protected boolean verifyEmail;
+    @Column(name="RESET_PASSWORD_ALLOWED")
+    protected boolean resetPasswordAllowed;
+    @Column(name="REMEMBER_ME")
+    protected boolean rememberMe;
+    @Column(name="PASSWORD_POLICY")
+    protected String passwordPolicy;
+    @Column(name="EDIT_USERNAME_ALLOWED")
+    protected boolean editUsernameAllowed;
+
+    @Column(name="SSO_IDLE_TIMEOUT")
+    private int ssoSessionIdleTimeout;
+    @Column(name="SSO_MAX_LIFESPAN")
+    private int ssoSessionMaxLifespan;
+    @Column(name="ACCESS_TOKEN_LIFESPAN")
+    protected int accessTokenLifespan;
+    @Column(name="ACCESS_CODE_LIFESPAN")
+    protected int accessCodeLifespan;
+    @Column(name="USER_ACTION_LIFESPAN")
+    protected int accessCodeLifespanUserAction;
+    @Column(name="LOGIN_LIFESPAN")
+    protected int accessCodeLifespanLogin;
+    @Column(name="NOT_BEFORE")
+    protected int notBefore;
+
+    @Column(name="PUBLIC_KEY", length = 2048)
+    protected String publicKeyPem;
+    @Column(name="PRIVATE_KEY", length = 2048)
+    protected String privateKeyPem;
+    @Column(name="CERTIFICATE", length = 2048)
+    protected String certificatePem;
+    @Column(name="CODE_SECRET", length = 255)
+    protected String codeSecret;
+
+    @Column(name="LOGIN_THEME")
+    protected String loginTheme;
+    @Column(name="ACCOUNT_THEME")
+    protected String accountTheme;
+    @Column(name="ADMIN_THEME")
+    protected String adminTheme;
+    @Column(name="EMAIL_THEME")
+    protected String emailTheme;
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<RealmAttributeEntity> attributes = new ArrayList<RealmAttributeEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
+    @JoinTable(name="FED_PROVIDERS")
+    List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
+    @JoinTable(name="REALM_CLIENT", joinColumns={ @JoinColumn(name="REALM_ID") }, inverseJoinColumns={ @JoinColumn(name="CLIENT_ID") })
+    Collection<ClientEntity> clients = new ArrayList<>();
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE")
+    @CollectionTable(name="REALM_SMTP_CONFIG", joinColumns={ @JoinColumn(name="REALM_ID") })
+    protected Map<String, String> smtpConfig = new HashMap<String, String>();
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
+    @JoinTable(name="REALM_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="REALM_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
+    protected Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
+
+    @Column(name="EVENTS_ENABLED")
+    protected boolean eventsEnabled;
+    @Column(name="EVENTS_EXPIRATION")
+    protected long eventsExpiration;
+
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name="REALM_EVENTS_LISTENERS", joinColumns={ @JoinColumn(name="REALM_ID") })
+    protected Set<String> eventsListeners = new HashSet<String>();
+    
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name="REALM_ENABLED_EVENT_TYPES", joinColumns={ @JoinColumn(name="REALM_ID") })
+    protected Set<String> enabledEventTypes = new HashSet<String>();
+    
+    @Column(name="ADMIN_EVENTS_ENABLED")
+    protected boolean adminEventsEnabled;
+    
+    @Column(name="ADMIN_EVENTS_DETAILS_ENABLED")
+    protected boolean adminEventsDetailsEnabled;
+    
+    @OneToOne
+    @JoinColumn(name="MASTER_ADMIN_CLIENT")
+    protected ClientEntity masterAdminClient;
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    protected List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<AuthenticatorConfigEntity> authenticators = new ArrayList<>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<RequiredActionProviderEntity> requiredActionProviders = new ArrayList<>();
+
+    @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
+    Collection<AuthenticationFlowEntity> authenticationFlows = new ArrayList<>();
+
+
+
+    @Column(name="INTERNATIONALIZATION_ENABLED")
+    protected boolean internationalizationEnabled;
+
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name="REALM_SUPPORTED_LOCALES", joinColumns={ @JoinColumn(name="REALM_ID") })
+    protected Set<String> supportedLocales = new HashSet<String>();
+
+    @Column(name="DEFAULT_LOCALE")
+    protected String defaultLocale;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getSslRequired() {
+        return sslRequired;
+    }
+
+    public void setSslRequired(String sslRequired) {
+        this.sslRequired = sslRequired;
+    }
+
+    public boolean isRegistrationAllowed() {
+        return registrationAllowed;
+    }
+
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        this.registrationAllowed = registrationAllowed;
+    }
+
+    public boolean isRegistrationEmailAsUsername() {
+        return registrationEmailAsUsername;
+    }
+
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        this.registrationEmailAsUsername = registrationEmailAsUsername;
+    }
+
+    public boolean isRememberMe() {
+        return rememberMe;
+    }
+
+    public void setRememberMe(boolean rememberMe) {
+        this.rememberMe = rememberMe;
+    }
+
+    public boolean isVerifyEmail() {
+        return verifyEmail;
+    }
+
+    public void setVerifyEmail(boolean verifyEmail) {
+        this.verifyEmail = verifyEmail;
+    }
+
+    public boolean isResetPasswordAllowed() {
+        return resetPasswordAllowed;
+    }
+
+    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
+        this.resetPasswordAllowed = resetPasswordAllowed;
+    }
+
+    public boolean isEditUsernameAllowed() {
+        return editUsernameAllowed;
+    }
+
+    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+        this.editUsernameAllowed = editUsernameAllowed;
+    }
+
+    public int getSsoSessionIdleTimeout() {
+        return ssoSessionIdleTimeout;
+    }
+
+    public void setSsoSessionIdleTimeout(int ssoSessionIdleTimeout) {
+        this.ssoSessionIdleTimeout = ssoSessionIdleTimeout;
+    }
+
+    public int getSsoSessionMaxLifespan() {
+        return ssoSessionMaxLifespan;
+    }
+
+    public void setSsoSessionMaxLifespan(int ssoSessionMaxLifespan) {
+        this.ssoSessionMaxLifespan = ssoSessionMaxLifespan;
+    }
+
+    public int getAccessTokenLifespan() {
+        return accessTokenLifespan;
+    }
+
+    public void setAccessTokenLifespan(int accessTokenLifespan) {
+        this.accessTokenLifespan = accessTokenLifespan;
+    }
+
+    public int getAccessCodeLifespan() {
+        return accessCodeLifespan;
+    }
+
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        this.accessCodeLifespan = accessCodeLifespan;
+    }
+
+    public int getAccessCodeLifespanUserAction() {
+        return accessCodeLifespanUserAction;
+    }
+
+    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
+        this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
+    }
+    public int getAccessCodeLifespanLogin() {
+        return accessCodeLifespanLogin;
+    }
+
+    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
+        this.accessCodeLifespanLogin = accessCodeLifespanLogin;
+    }
+
+    public String getPublicKeyPem() {
+        return publicKeyPem;
+    }
+
+    public void setPublicKeyPem(String publicKeyPem) {
+        this.publicKeyPem = publicKeyPem;
+    }
+
+    public String getPrivateKeyPem() {
+        return privateKeyPem;
+    }
+
+    public void setPrivateKeyPem(String privateKeyPem) {
+        this.privateKeyPem = privateKeyPem;
+    }
+
+    public String getCodeSecret() {
+        return codeSecret;
+    }
+
+    public void setCodeSecret(String codeSecret) {
+        this.codeSecret = codeSecret;
+    }
+
+    public Collection<RequiredCredentialEntity> getRequiredCredentials() {
+        return requiredCredentials;
+    }
+
+    public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
+        this.requiredCredentials = requiredCredentials;
+    }
+
+    public Collection<ClientEntity> getClients() {
+        return clients;
+    }
+
+    public void setClients(Collection<ClientEntity> clients) {
+        this.clients = clients;
+    }
+
+    public Collection<RoleEntity> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Collection<RoleEntity> roles) {
+        this.roles = roles;
+    }
+
+    public void addRole(RoleEntity role) {
+        if (roles == null) {
+            roles = new ArrayList<RoleEntity>();
+        }
+        roles.add(role);
+    }
+
+    public Map<String, String> getSmtpConfig() {
+        return smtpConfig;
+    }
+
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        this.smtpConfig = smtpConfig;
+    }
+
+    public Collection<RoleEntity> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public String getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public void setPasswordPolicy(String passwordPolicy) {
+        this.passwordPolicy = passwordPolicy;
+    }
+
+    public String getLoginTheme() {
+        return loginTheme;
+    }
+
+    public void setLoginTheme(String theme) {
+        this.loginTheme = theme;
+    }
+
+    public String getAccountTheme() {
+        return accountTheme;
+    }
+
+    public void setAccountTheme(String theme) {
+        this.accountTheme = theme;
+    }
+
+    public String getAdminTheme() {
+        return adminTheme;
+    }
+
+    public void setAdminTheme(String adminTheme) {
+        this.adminTheme = adminTheme;
+    }
+
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public void setEmailTheme(String emailTheme) {
+        this.emailTheme = emailTheme;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public boolean isEventsEnabled() {
+        return eventsEnabled;
+    }
+
+    public void setEventsEnabled(boolean eventsEnabled) {
+        this.eventsEnabled = eventsEnabled;
+    }
+
+    public long getEventsExpiration() {
+        return eventsExpiration;
+    }
+
+    public void setEventsExpiration(long eventsExpiration) {
+        this.eventsExpiration = eventsExpiration;
+    }
+
+    public Set<String> getEventsListeners() {
+        return eventsListeners;
+    }
+
+    public void setEventsListeners(Set<String> eventsListeners) {
+        this.eventsListeners = eventsListeners;
+    }
+    
+    public Set<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
+    
+    public boolean isAdminEventsEnabled() {
+        return adminEventsEnabled;
+    }
+
+    public void setAdminEventsEnabled(boolean adminEventsEnabled) {
+        this.adminEventsEnabled = adminEventsEnabled;
+    }
+
+    public boolean isAdminEventsDetailsEnabled() {
+        return adminEventsDetailsEnabled;
+    }
+
+    public void setAdminEventsDetailsEnabled(boolean adminEventsDetailsEnabled) {
+        this.adminEventsDetailsEnabled = adminEventsDetailsEnabled;
+    }
+
+    public ClientEntity getMasterAdminClient() {
+        return masterAdminClient;
+    }
+
+    public void setMasterAdminClient(ClientEntity masterAdminClient) {
+        this.masterAdminClient = masterAdminClient;
+    }
+
+    public List<UserFederationProviderEntity> getUserFederationProviders() {
+        return userFederationProviders;
+    }
+
+    public void setUserFederationProviders(List<UserFederationProviderEntity> userFederationProviders) {
+        this.userFederationProviders = userFederationProviders;
+    }
+
+    public Collection<UserFederationMapperEntity> getUserFederationMappers() {
+        return userFederationMappers;
+    }
+
+    public void setUserFederationMappers(Collection<UserFederationMapperEntity> userFederationMappers) {
+        this.userFederationMappers = userFederationMappers;
+    }
+
+    public Collection<RealmAttributeEntity> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Collection<RealmAttributeEntity> attributes) {
+        this.attributes = attributes;
+    }
+
+    public String getCertificatePem() {
+        return certificatePem;
+    }
+
+    public void setCertificatePem(String certificatePem) {
+        this.certificatePem = certificatePem;
+    }
+
+    public List<IdentityProviderEntity> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public void setIdentityProviders(List<IdentityProviderEntity> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public void addIdentityProvider(IdentityProviderEntity entity) {
+        entity.setRealm(this);
+        getIdentityProviders().add(entity);
+    }
+
+    public boolean isInternationalizationEnabled() {
+        return internationalizationEnabled;
+    }
+
+    public void setInternationalizationEnabled(boolean internationalizationEnabled) {
+        this.internationalizationEnabled = internationalizationEnabled;
+    }
+
+    public Set<String> getSupportedLocales() {
+        return supportedLocales;
+    }
+
+    public void setSupportedLocales(Set<String> supportedLocales) {
+        this.supportedLocales = supportedLocales;
+    }
+
+    public String getDefaultLocale() {
+        return defaultLocale;
+    }
+
+    public void setDefaultLocale(String defaultLocale) {
+        this.defaultLocale = defaultLocale;
+    }
+
+    public Collection<IdentityProviderMapperEntity> getIdentityProviderMappers() {
+        return identityProviderMappers;
+    }
+
+    public void setIdentityProviderMappers(Collection<IdentityProviderMapperEntity> identityProviderMappers) {
+        this.identityProviderMappers = identityProviderMappers;
+    }
+
+    public Collection<AuthenticatorConfigEntity> getAuthenticatorConfigs() {
+        return authenticators;
+    }
+
+    public void setAuthenticatorConfigs(Collection<AuthenticatorConfigEntity> authenticators) {
+        this.authenticators = authenticators;
+    }
+
+    public Collection<RequiredActionProviderEntity> getRequiredActionProviders() {
+        return requiredActionProviders;
+    }
+
+    public void setRequiredActionProviders(Collection<RequiredActionProviderEntity> requiredActionProviders) {
+        this.requiredActionProviders = requiredActionProviders;
+    }
+
+    public Collection<AuthenticationFlowEntity> getAuthenticationFlows() {
+        return authenticationFlows;
+    }
+
+    public void setAuthenticationFlows(Collection<AuthenticationFlowEntity> authenticationFlows) {
+        this.authenticationFlows = authenticationFlows;
+    }
+
+}
+
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
index 4c5ecdd..972df5c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
@@ -1,118 +1,118 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKeyColumn;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="REQUIRED_ACTION_PROVIDER")
-@Entity
-@NamedQueries({
-        @NamedQuery(name="deleteRequiredActionProviderByRealm", query="delete from RequiredActionProviderEntity action where action.realm = :realm"),})
-public class RequiredActionProviderEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name="ALIAS")
-    protected String alias;
-
-    @Column(name="NAME")
-    protected String name;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @Column(name="PROVIDER_ID")
-    protected String providerId;
-
-    @Column(name="ENABLED")
-    protected boolean enabled;
-
-    @Column(name="DEFAULT_ACTION")
-    protected boolean defaultAction;
-
-    @ElementCollection
-    @MapKeyColumn(name="NAME")
-    @Column(name="VALUE")
-    @CollectionTable(name="REQUIRED_ACTION_CONFIG", joinColumns={ @JoinColumn(name="REQUIRED_ACTION_ID") })
-    private Map<String, String> config;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public boolean isDefaultAction() {
-        return defaultAction;
-    }
-
-    public void setDefaultAction(boolean defaultAction) {
-        this.defaultAction = defaultAction;
-    }
-
-    public String getProviderId() {
-        return providerId;
-    }
-
-    public void setProviderId(String providerId) {
-        this.providerId = providerId;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public Map<String, String> getConfig() {
-        return config;
-    }
-
-    public void setConfig(Map<String, String> config) {
-        this.config = config;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="REQUIRED_ACTION_PROVIDER")
+@Entity
+@NamedQueries({
+        @NamedQuery(name="deleteRequiredActionProviderByRealm", query="delete from RequiredActionProviderEntity action where action.realm = :realm"),})
+public class RequiredActionProviderEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name="ALIAS")
+    protected String alias;
+
+    @Column(name="NAME")
+    protected String name;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @Column(name="PROVIDER_ID")
+    protected String providerId;
+
+    @Column(name="ENABLED")
+    protected boolean enabled;
+
+    @Column(name="DEFAULT_ACTION")
+    protected boolean defaultAction;
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE")
+    @CollectionTable(name="REQUIRED_ACTION_CONFIG", joinColumns={ @JoinColumn(name="REQUIRED_ACTION_ID") })
+    private Map<String, String> config;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public boolean isDefaultAction() {
+        return defaultAction;
+    }
+
+    public void setDefaultAction(boolean defaultAction) {
+        this.defaultAction = defaultAction;
+    }
+
+    public String getProviderId() {
+        return providerId;
+    }
+
+    public void setProviderId(String providerId) {
+        this.providerId = providerId;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public Map<String, String> getConfig() {
+        return config;
+    }
+
+    public void setConfig(Map<String, String> config) {
+        this.config = config;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
index 7e4245c..3a4333f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
@@ -1,120 +1,120 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Table(name="REALM_REQUIRED_CREDENTIAL")
-@Entity
-@IdClass(RequiredCredentialEntity.Key.class)
-public class RequiredCredentialEntity {
-
-    @Id
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM_ID")
-    protected RealmEntity realm;
-
-    @Id
-    @Column(name = "TYPE")
-    protected String type;
-    @Column(name = "INPUT")
-    protected boolean input;
-    @Column(name = "SECRET")
-    protected boolean secret;
-    @Column(name = "FORM_LABEL")
-    protected String formLabel;
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public boolean isInput() {
-        return input;
-    }
-
-    public void setInput(boolean input) {
-        this.input = input;
-    }
-
-    public boolean isSecret() {
-        return secret;
-    }
-
-    public void setSecret(boolean secret) {
-        this.secret = secret;
-    }
-
-    public String getFormLabel() {
-        return formLabel;
-    }
-
-    public void setFormLabel(String formLabel) {
-        this.formLabel = formLabel;
-    }
-
-    public static class Key implements Serializable {
-
-        protected RealmEntity realm;
-
-        protected String type;
-
-        public Key() {
-        }
-
-        public Key(RealmEntity realm, String type) {
-            this.realm = realm;
-            this.type = type;
-        }
-
-        public RealmEntity getRealm() {
-            return realm;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
-            if (type != null ? !type.equals(key.type) : key.type != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = realm != null ? realm.getId().hashCode() : 0;
-            result = 31 * result + (type != null ? type.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Table(name="REALM_REQUIRED_CREDENTIAL")
+@Entity
+@IdClass(RequiredCredentialEntity.Key.class)
+public class RequiredCredentialEntity {
+
+    @Id
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM_ID")
+    protected RealmEntity realm;
+
+    @Id
+    @Column(name = "TYPE")
+    protected String type;
+    @Column(name = "INPUT")
+    protected boolean input;
+    @Column(name = "SECRET")
+    protected boolean secret;
+    @Column(name = "FORM_LABEL")
+    protected String formLabel;
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public boolean isInput() {
+        return input;
+    }
+
+    public void setInput(boolean input) {
+        this.input = input;
+    }
+
+    public boolean isSecret() {
+        return secret;
+    }
+
+    public void setSecret(boolean secret) {
+        this.secret = secret;
+    }
+
+    public String getFormLabel() {
+        return formLabel;
+    }
+
+    public void setFormLabel(String formLabel) {
+        this.formLabel = formLabel;
+    }
+
+    public static class Key implements Serializable {
+
+        protected RealmEntity realm;
+
+        protected String type;
+
+        public Key() {
+        }
+
+        public Key(RealmEntity realm, String type) {
+            this.realm = realm;
+            this.type = type;
+        }
+
+        public RealmEntity getRealm() {
+            return realm;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (realm != null ? !realm.getId().equals(key.realm != null ? key.realm.getId() : null) : key.realm != null) return false;
+            if (type != null ? !type.equals(key.type) : key.type != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = realm != null ? realm.getId().hashCode() : 0;
+            result = 31 * result + (type != null ? type.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
index 262a469..4c9edb7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
@@ -1,156 +1,156 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name="KEYCLOAK_ROLE", uniqueConstraints = {
-        @UniqueConstraint(columnNames = { "NAME", "CLIENT_REALM_CONSTRAINT" })
-})
-@NamedQueries({
-        @NamedQuery(name="getClientRoleByName", query="select role from RoleEntity role where role.name = :name and role.client = :client"),
-        @NamedQuery(name="getRealmRoleByName", query="select role from RoleEntity role where role.clientRole = false and role.name = :name and role.realm = :realm")
-})
-
-public class RoleEntity {
-    @Id
-    @Column(name="id", length = 36)
-    private String id;
-
-    @Column(name = "NAME")
-    private String name;
-    @Column(name = "DESCRIPTION")
-    private String description;
-
-    // hax! couldn't get constraint to work properly
-    @Column(name = "REALM_ID")
-    private String realmId;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "REALM")
-    private RealmEntity realm;
-
-    @Column(name="CLIENT_ROLE")
-    private boolean clientRole;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "CLIENT")
-    private ClientEntity client;
-
-    // Hack to ensure that either name+client or name+realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint
-    @Column(name="CLIENT_REALM_CONSTRAINT", length = 36)
-    private String clientRealmConstraint;
-
-    @ManyToMany(fetch = FetchType.LAZY, cascade = {})
-    @JoinTable(name = "COMPOSITE_ROLE", joinColumns = @JoinColumn(name = "COMPOSITE"), inverseJoinColumns = @JoinColumn(name = "CHILD_ROLE"))
-    private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Collection<RoleEntity> getCompositeRoles() {
-        return compositeRoles;
-    }
-
-    public void setCompositeRoles(Collection<RoleEntity> compositeRoles) {
-        this.compositeRoles = compositeRoles;
-    }
-
-    public boolean isClientRole() {
-        return clientRole;
-    }
-
-    public void setClientRole(boolean clientRole) {
-        this.clientRole = clientRole;
-    }
-
-    public RealmEntity getRealm() {
-        return realm;
-    }
-
-    public void setRealm(RealmEntity realm) {
-        this.realm = realm;
-        this.clientRealmConstraint = realm.getId();
-    }
-
-    public ClientEntity getClient() {
-        return client;
-    }
-
-    public void setClient(ClientEntity client) {
-        this.client = client;
-        if (client != null) {
-            this.clientRealmConstraint = client.getId();
-        }
-    }
-
-    public String getClientRealmConstraint() {
-        return clientRealmConstraint;
-    }
-
-    public void setClientRealmConstraint(String clientRealmConstraint) {
-        this.clientRealmConstraint = clientRealmConstraint;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof RoleEntity)) return false;
-
-        RoleEntity that = (RoleEntity) o;
-
-        if (!id.equals(that.getId())) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name="KEYCLOAK_ROLE", uniqueConstraints = {
+        @UniqueConstraint(columnNames = { "NAME", "CLIENT_REALM_CONSTRAINT" })
+})
+@NamedQueries({
+        @NamedQuery(name="getClientRoleByName", query="select role from RoleEntity role where role.name = :name and role.client = :client"),
+        @NamedQuery(name="getRealmRoleByName", query="select role from RoleEntity role where role.clientRole = false and role.name = :name and role.realm = :realm")
+})
+
+public class RoleEntity {
+    @Id
+    @Column(name="id", length = 36)
+    private String id;
+
+    @Column(name = "NAME")
+    private String name;
+    @Column(name = "DESCRIPTION")
+    private String description;
+
+    // hax! couldn't get constraint to work properly
+    @Column(name = "REALM_ID")
+    private String realmId;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "REALM")
+    private RealmEntity realm;
+
+    @Column(name="CLIENT_ROLE")
+    private boolean clientRole;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "CLIENT")
+    private ClientEntity client;
+
+    // Hack to ensure that either name+client or name+realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint
+    @Column(name="CLIENT_REALM_CONSTRAINT", length = 36)
+    private String clientRealmConstraint;
+
+    @ManyToMany(fetch = FetchType.LAZY, cascade = {})
+    @JoinTable(name = "COMPOSITE_ROLE", joinColumns = @JoinColumn(name = "COMPOSITE"), inverseJoinColumns = @JoinColumn(name = "CHILD_ROLE"))
+    private Collection<RoleEntity> compositeRoles = new ArrayList<RoleEntity>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Collection<RoleEntity> getCompositeRoles() {
+        return compositeRoles;
+    }
+
+    public void setCompositeRoles(Collection<RoleEntity> compositeRoles) {
+        this.compositeRoles = compositeRoles;
+    }
+
+    public boolean isClientRole() {
+        return clientRole;
+    }
+
+    public void setClientRole(boolean clientRole) {
+        this.clientRole = clientRole;
+    }
+
+    public RealmEntity getRealm() {
+        return realm;
+    }
+
+    public void setRealm(RealmEntity realm) {
+        this.realm = realm;
+        this.clientRealmConstraint = realm.getId();
+    }
+
+    public ClientEntity getClient() {
+        return client;
+    }
+
+    public void setClient(ClientEntity client) {
+        this.client = client;
+        if (client != null) {
+            this.clientRealmConstraint = client.getId();
+        }
+    }
+
+    public String getClientRealmConstraint() {
+        return clientRealmConstraint;
+    }
+
+    public void setClientRealmConstraint(String clientRealmConstraint) {
+        this.clientRealmConstraint = clientRealmConstraint;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof RoleEntity)) return false;
+
+        RoleEntity that = (RoleEntity) o;
+
+        if (!id.equals(that.getId())) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
index 2c8b494..20a23b7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
@@ -1,99 +1,99 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="hasScope", query="select m from ScopeMappingEntity m where m.client = :client and m.role = :role"),
-        @NamedQuery(name="clientScopeMappings", query="select m from ScopeMappingEntity m where m.client = :client"),
-        @NamedQuery(name="clientScopeMappingIds", query="select m.role.id from ScopeMappingEntity m where m.client = :client"),
-        @NamedQuery(name="deleteScopeMappingByRole", query="delete from ScopeMappingEntity where role = :role"),
-        @NamedQuery(name="deleteScopeMappingByClient", query="delete from ScopeMappingEntity where client = :client")
-})
-@Table(name="SCOPE_MAPPING")
-@Entity
-@IdClass(ScopeMappingEntity.Key.class)
-public class ScopeMappingEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_ID")
-    protected ClientEntity client;
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name="ROLE_ID")
-    protected RoleEntity role;
-
-    public ClientEntity getClient() {
-        return client;
-    }
-
-    public void setClient(ClientEntity client) {
-        this.client = client;
-    }
-
-    public RoleEntity getRole() {
-        return role;
-    }
-
-    public void setRole(RoleEntity role) {
-        this.role = role;
-    }
-
-    public static class Key implements Serializable {
-
-        protected ClientEntity client;
-
-        protected RoleEntity role;
-
-        public Key() {
-        }
-
-        public Key(ClientEntity client, RoleEntity role) {
-            this.client = client;
-            this.role = role;
-        }
-
-        public ClientEntity getClient() {
-            return client;
-        }
-
-        public RoleEntity getRole() {
-            return role;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
-            if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = client != null ? client.getId().hashCode() : 0;
-            result = 31 * result + (role != null ? role.getId().hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="hasScope", query="select m from ScopeMappingEntity m where m.client = :client and m.role = :role"),
+        @NamedQuery(name="clientScopeMappings", query="select m from ScopeMappingEntity m where m.client = :client"),
+        @NamedQuery(name="clientScopeMappingIds", query="select m.role.id from ScopeMappingEntity m where m.client = :client"),
+        @NamedQuery(name="deleteScopeMappingByRole", query="delete from ScopeMappingEntity where role = :role"),
+        @NamedQuery(name="deleteScopeMappingByClient", query="delete from ScopeMappingEntity where client = :client")
+})
+@Table(name="SCOPE_MAPPING")
+@Entity
+@IdClass(ScopeMappingEntity.Key.class)
+public class ScopeMappingEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_ID")
+    protected ClientEntity client;
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name="ROLE_ID")
+    protected RoleEntity role;
+
+    public ClientEntity getClient() {
+        return client;
+    }
+
+    public void setClient(ClientEntity client) {
+        this.client = client;
+    }
+
+    public RoleEntity getRole() {
+        return role;
+    }
+
+    public void setRole(RoleEntity role) {
+        this.role = role;
+    }
+
+    public static class Key implements Serializable {
+
+        protected ClientEntity client;
+
+        protected RoleEntity role;
+
+        public Key() {
+        }
+
+        public Key(ClientEntity client, RoleEntity role) {
+            this.client = client;
+            this.role = role;
+        }
+
+        public ClientEntity getClient() {
+            return client;
+        }
+
+        public RoleEntity getRole() {
+            return role;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
+            if (role != null ? !role.getId().equals(key.role != null ? key.role.getId() : null) : key.role != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = client != null ? client.getId().hashCode() : 0;
+            result = 31 * result + (role != null ? role.getId().hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
index 51352b4..430c796 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
@@ -1,76 +1,76 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="deleteUserAttributesByRealm", query="delete from  UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId)"),
-        @NamedQuery(name="deleteUserAttributesByRealmAndLink", query="delete from  UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
-})
-@Table(name="USER_ATTRIBUTE")
-@Entity
-public class UserAttributeEntity {
-
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "USER_ID")
-    protected UserEntity user;
-
-    @Column(name = "NAME")
-    protected String name;
-    @Column(name = "VALUE")
-    protected String value;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="deleteUserAttributesByRealm", query="delete from  UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId)"),
+        @NamedQuery(name="deleteUserAttributesByRealmAndLink", query="delete from  UserAttributeEntity attr where attr.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
+})
+@Table(name="USER_ATTRIBUTE")
+@Entity
+public class UserAttributeEntity {
+
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "USER_ID")
+    protected UserEntity user;
+
+    @Column(name = "NAME")
+    protected String name;
+    @Column(name = "VALUE")
+    protected String value;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index 443c8eb..5e0769a 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -1,217 +1,217 @@
-package org.keycloak.models.jpa.entities;
-
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="getAllUsersByRealm", query="select u from UserEntity u where u.realmId = :realmId order by u.username"),
-        @NamedQuery(name="searchForUser", query="select u from UserEntity u where u.realmId = :realmId and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search ) order by u.username"),
-        @NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realmId = :realmId"),
-        @NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realmId = :realmId"),
-        @NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realmId = :realmId"),
-        @NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realmId = :realmId"),
-        @NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realmId = :realmId"),
-        @NamedQuery(name="getRealmUserCount", query="select count(u) from UserEntity u where u.realmId = :realmId"),
-        @NamedQuery(name="deleteUsersByRealm", query="delete from UserEntity u where u.realmId = :realmId"),
-        @NamedQuery(name="deleteUsersByRealmAndLink", query="delete from UserEntity u where u.realmId = :realmId and u.federationLink=:link")
-})
-@Entity
-@Table(name="USER_ENTITY", uniqueConstraints = {
-        @UniqueConstraint(columnNames = { "REALM_ID", "USERNAME" }),
-        @UniqueConstraint(columnNames = { "REALM_ID", "EMAIL_CONSTRAINT" })
-})
-public class UserEntity {
-    @Id
-    @Column(name="ID", length = 36)
-    protected String id;
-
-    @Column(name = "USERNAME")
-    protected String username;
-    @Column(name = "FIRST_NAME")
-    protected String firstName;
-    @Column(name = "CREATED_TIMESTAMP")
-    protected Long createdTimestamp;
-    @Column(name = "LAST_NAME")
-    protected String lastName;
-    @Column(name = "EMAIL")
-    protected String email;
-    @Column(name = "ENABLED")
-    protected boolean enabled;
-    @Column(name = "TOTP")
-    protected boolean totp;
-    @Column(name = "EMAIL_VERIFIED")
-    protected boolean emailVerified;
-
-    // Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
-    @Column(name = "EMAIL_CONSTRAINT")
-    protected String emailConstraint = KeycloakModelUtils.generateId();
-
-    @Column(name = "REALM_ID")
-    protected String realmId;
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
-    protected Collection<UserAttributeEntity> attributes = new ArrayList<UserAttributeEntity>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
-    protected Collection<UserRequiredActionEntity> requiredActions = new ArrayList<UserRequiredActionEntity>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
-    protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
-
-    @Column(name="federation_link")
-    protected String federationLink;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public Long getCreatedTimestamp() {
-        return createdTimestamp;
-    }
-
-    public void setCreatedTimestamp(Long timestamp) {
-        createdTimestamp = timestamp;
-    }
-
-    public String getFirstName() {
-        return firstName;
-    }
-
-    public void setFirstName(String firstName) {
-        this.firstName = firstName;
-    }
-
-    public String getLastName() {
-        return lastName;
-    }
-
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-        this.emailConstraint = email != null ? email : KeycloakModelUtils.generateId();
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getEmailConstraint() {
-        return emailConstraint;
-    }
-
-    public void setEmailConstraint(String emailConstraint) {
-        this.emailConstraint = emailConstraint;
-    }
-
-    public boolean isTotp() {
-        return totp;
-    }
-
-    public void setTotp(boolean totp) {
-        this.totp = totp;
-    }
-
-    public boolean isEmailVerified() {
-        return emailVerified;
-    }
-
-    public void setEmailVerified(boolean emailVerified) {
-        this.emailVerified = emailVerified;
-    }
-
-    public Collection<UserAttributeEntity> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Collection<UserAttributeEntity> attributes) {
-        this.attributes = attributes;
-    }
-
-    public Collection<UserRequiredActionEntity> getRequiredActions() {
-        return requiredActions;
-    }
-
-    public void setRequiredActions(Collection<UserRequiredActionEntity> requiredActions) {
-        this.requiredActions = requiredActions;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public Collection<CredentialEntity> getCredentials() {
-        return credentials;
-    }
-
-    public void setCredentials(Collection<CredentialEntity> credentials) {
-        this.credentials = credentials;
-    }
-
-    public String getFederationLink() {
-        return federationLink;
-    }
-
-    public void setFederationLink(String federationLink) {
-        this.federationLink = federationLink;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        UserEntity that = (UserEntity) o;
-
-        if (!id.equals(that.id)) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="getAllUsersByRealm", query="select u from UserEntity u where u.realmId = :realmId order by u.username"),
+        @NamedQuery(name="searchForUser", query="select u from UserEntity u where u.realmId = :realmId and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search ) order by u.username"),
+        @NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realmId = :realmId"),
+        @NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realmId = :realmId"),
+        @NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realmId = :realmId"),
+        @NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realmId = :realmId"),
+        @NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realmId = :realmId"),
+        @NamedQuery(name="getRealmUserCount", query="select count(u) from UserEntity u where u.realmId = :realmId"),
+        @NamedQuery(name="deleteUsersByRealm", query="delete from UserEntity u where u.realmId = :realmId"),
+        @NamedQuery(name="deleteUsersByRealmAndLink", query="delete from UserEntity u where u.realmId = :realmId and u.federationLink=:link")
+})
+@Entity
+@Table(name="USER_ENTITY", uniqueConstraints = {
+        @UniqueConstraint(columnNames = { "REALM_ID", "USERNAME" }),
+        @UniqueConstraint(columnNames = { "REALM_ID", "EMAIL_CONSTRAINT" })
+})
+public class UserEntity {
+    @Id
+    @Column(name="ID", length = 36)
+    protected String id;
+
+    @Column(name = "USERNAME")
+    protected String username;
+    @Column(name = "FIRST_NAME")
+    protected String firstName;
+    @Column(name = "CREATED_TIMESTAMP")
+    protected Long createdTimestamp;
+    @Column(name = "LAST_NAME")
+    protected String lastName;
+    @Column(name = "EMAIL")
+    protected String email;
+    @Column(name = "ENABLED")
+    protected boolean enabled;
+    @Column(name = "TOTP")
+    protected boolean totp;
+    @Column(name = "EMAIL_VERIFIED")
+    protected boolean emailVerified;
+
+    // Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
+    @Column(name = "EMAIL_CONSTRAINT")
+    protected String emailConstraint = KeycloakModelUtils.generateId();
+
+    @Column(name = "REALM_ID")
+    protected String realmId;
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
+    protected Collection<UserAttributeEntity> attributes = new ArrayList<UserAttributeEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
+    protected Collection<UserRequiredActionEntity> requiredActions = new ArrayList<UserRequiredActionEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="user")
+    protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
+
+    @Column(name="federation_link")
+    protected String federationLink;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public Long getCreatedTimestamp() {
+        return createdTimestamp;
+    }
+
+    public void setCreatedTimestamp(Long timestamp) {
+        createdTimestamp = timestamp;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+        this.emailConstraint = email != null ? email : KeycloakModelUtils.generateId();
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getEmailConstraint() {
+        return emailConstraint;
+    }
+
+    public void setEmailConstraint(String emailConstraint) {
+        this.emailConstraint = emailConstraint;
+    }
+
+    public boolean isTotp() {
+        return totp;
+    }
+
+    public void setTotp(boolean totp) {
+        this.totp = totp;
+    }
+
+    public boolean isEmailVerified() {
+        return emailVerified;
+    }
+
+    public void setEmailVerified(boolean emailVerified) {
+        this.emailVerified = emailVerified;
+    }
+
+    public Collection<UserAttributeEntity> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Collection<UserAttributeEntity> attributes) {
+        this.attributes = attributes;
+    }
+
+    public Collection<UserRequiredActionEntity> getRequiredActions() {
+        return requiredActions;
+    }
+
+    public void setRequiredActions(Collection<UserRequiredActionEntity> requiredActions) {
+        this.requiredActions = requiredActions;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public Collection<CredentialEntity> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(Collection<CredentialEntity> credentials) {
+        this.credentials = credentials;
+    }
+
+    public String getFederationLink() {
+        return federationLink;
+    }
+
+    public void setFederationLink(String federationLink) {
+        this.federationLink = federationLink;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        UserEntity that = (UserEntity) o;
+
+        if (!id.equals(that.id)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRequiredActionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRequiredActionEntity.java
index a583815..6cab06d 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRequiredActionEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRequiredActionEntity.java
@@ -1,98 +1,98 @@
-package org.keycloak.models.jpa.entities;
-
-import org.keycloak.models.UserModel;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="deleteUserRequiredActionsByRealm", query="delete from UserRequiredActionEntity action where action.user IN (select u from UserEntity u where u.realmId=:realmId)"),
-        @NamedQuery(name="deleteUserRequiredActionsByRealmAndLink", query="delete from UserRequiredActionEntity action where action.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
-})
-@Entity
-@Table(name="USER_REQUIRED_ACTION")
-@IdClass(UserRequiredActionEntity.Key.class)
-public class UserRequiredActionEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name="USER_ID")
-    protected UserEntity user;
-
-    @Id
-    @Column(name="REQUIRED_ACTION")
-    protected String action;
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-    public static class Key implements Serializable {
-
-        protected UserEntity user;
-
-        protected String action;
-
-        public Key() {
-        }
-
-        public Key(UserEntity user, String action) {
-            this.user = user;
-            this.action = action;
-        }
-
-        public UserEntity getUser() {
-            return user;
-        }
-
-        public String getAction() {
-            return action;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (action != key.action) return false;
-            if (user != null ? !user.getId().equals(key.user != null ? key.user.getId() : null) : key.user != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = user != null ? user.getId().hashCode() : 0;
-            result = 31 * result + (action != null ? action.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.jpa.entities;
+
+import org.keycloak.models.UserModel;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="deleteUserRequiredActionsByRealm", query="delete from UserRequiredActionEntity action where action.user IN (select u from UserEntity u where u.realmId=:realmId)"),
+        @NamedQuery(name="deleteUserRequiredActionsByRealmAndLink", query="delete from UserRequiredActionEntity action where action.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
+})
+@Entity
+@Table(name="USER_REQUIRED_ACTION")
+@IdClass(UserRequiredActionEntity.Key.class)
+public class UserRequiredActionEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name="USER_ID")
+    protected UserEntity user;
+
+    @Id
+    @Column(name="REQUIRED_ACTION")
+    protected String action;
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    public static class Key implements Serializable {
+
+        protected UserEntity user;
+
+        protected String action;
+
+        public Key() {
+        }
+
+        public Key(UserEntity user, String action) {
+            this.user = user;
+            this.action = action;
+        }
+
+        public UserEntity getUser() {
+            return user;
+        }
+
+        public String getAction() {
+            return action;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (action != key.action) return false;
+            if (user != null ? !user.getId().equals(key.user != null ? key.user.getId() : null) : key.user != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = user != null ? user.getId().hashCode() : 0;
+            result = 31 * result + (action != null ? action.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
index aa4f681..1ce81e8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserRoleMappingEntity.java
@@ -1,102 +1,102 @@
-package org.keycloak.models.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name="userHasRole", query="select m from UserRoleMappingEntity m where m.user = :user and m.roleId = :roleId"),
-        @NamedQuery(name="userRoleMappings", query="select m from UserRoleMappingEntity m where m.user = :user"),
-        @NamedQuery(name="userRoleMappingIds", query="select m.roleId from UserRoleMappingEntity m where m.user = :user"),
-        @NamedQuery(name="deleteUserRoleMappingsByRealm", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId)"),
-        @NamedQuery(name="deleteUserRoleMappingsByRealmAndLink", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
-        @NamedQuery(name="deleteUserRoleMappingsByRole", query="delete from UserRoleMappingEntity m where m.roleId = :roleId"),
-        @NamedQuery(name="deleteUserRoleMappingsByUser", query="delete from UserRoleMappingEntity m where m.user = :user")
-
-})
-@Table(name="USER_ROLE_MAPPING")
-@Entity
-@IdClass(UserRoleMappingEntity.Key.class)
-public class UserRoleMappingEntity  {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name="USER_ID")
-    protected UserEntity user;
-
-    @Id
-    @Column(name = "ROLE_ID")
-    protected String roleId;
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    public void setUser(UserEntity user) {
-        this.user = user;
-    }
-
-    public String getRoleId() {
-        return roleId;
-    }
-
-    public void setRoleId(String roleId) {
-        this.roleId = roleId;
-    }
-
-
-    public static class Key implements Serializable {
-
-        protected UserEntity user;
-
-        protected String roleId;
-
-        public Key() {
-        }
-
-        public Key(UserEntity user, String roleId) {
-            this.user = user;
-            this.roleId = roleId;
-        }
-
-        public UserEntity getUser() {
-            return user;
-        }
-
-        public String getRoleId() {
-            return roleId;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (!roleId.equals(key.roleId)) return false;
-            if (!user.equals(key.user)) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = user.hashCode();
-            result = 31 * result + roleId.hashCode();
-            return result;
-        }
-    }
-}
+package org.keycloak.models.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name="userHasRole", query="select m from UserRoleMappingEntity m where m.user = :user and m.roleId = :roleId"),
+        @NamedQuery(name="userRoleMappings", query="select m from UserRoleMappingEntity m where m.user = :user"),
+        @NamedQuery(name="userRoleMappingIds", query="select m.roleId from UserRoleMappingEntity m where m.user = :user"),
+        @NamedQuery(name="deleteUserRoleMappingsByRealm", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId)"),
+        @NamedQuery(name="deleteUserRoleMappingsByRealmAndLink", query="delete from  UserRoleMappingEntity mapping where mapping.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
+        @NamedQuery(name="deleteUserRoleMappingsByRole", query="delete from UserRoleMappingEntity m where m.roleId = :roleId"),
+        @NamedQuery(name="deleteUserRoleMappingsByUser", query="delete from UserRoleMappingEntity m where m.user = :user")
+
+})
+@Table(name="USER_ROLE_MAPPING")
+@Entity
+@IdClass(UserRoleMappingEntity.Key.class)
+public class UserRoleMappingEntity  {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name="USER_ID")
+    protected UserEntity user;
+
+    @Id
+    @Column(name = "ROLE_ID")
+    protected String roleId;
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    public void setUser(UserEntity user) {
+        this.user = user;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+
+    public static class Key implements Serializable {
+
+        protected UserEntity user;
+
+        protected String roleId;
+
+        public Key() {
+        }
+
+        public Key(UserEntity user, String roleId) {
+            this.user = user;
+            this.roleId = roleId;
+        }
+
+        public UserEntity getUser() {
+            return user;
+        }
+
+        public String getRoleId() {
+            return roleId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (!roleId.equals(key.roleId)) return false;
+            if (!user.equals(key.user)) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = user.hashCode();
+            result = 31 * result + roleId.hashCode();
+            return result;
+        }
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java
index 095b341..f19cffa 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java
@@ -1,53 +1,53 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.models.KeycloakTransaction;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaKeycloakTransaction implements KeycloakTransaction {
-
-    protected EntityManager em;
-
-    public JpaKeycloakTransaction(EntityManager em) {
-        this.em = em;
-    }
-
-    @Override
-    public void begin() {
-        em.getTransaction().begin();
-    }
-
-    @Override
-    public void commit() {
-        try {
-            em.getTransaction().commit();
-        } catch (PersistenceException e) {
-            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
-        }
-    }
-
-    @Override
-    public void rollback() {
-        em.getTransaction().rollback();
-    }
-
-    @Override
-    public void setRollbackOnly() {
-        em.getTransaction().setRollbackOnly();
-    }
-
-    @Override
-    public boolean getRollbackOnly() {
-        return  em.getTransaction().getRollbackOnly();
-    }
-
-    @Override
-    public boolean isActive() {
-        return em.getTransaction().isActive();
-    }
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.models.KeycloakTransaction;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaKeycloakTransaction implements KeycloakTransaction {
+
+    protected EntityManager em;
+
+    public JpaKeycloakTransaction(EntityManager em) {
+        this.em = em;
+    }
+
+    @Override
+    public void begin() {
+        em.getTransaction().begin();
+    }
+
+    @Override
+    public void commit() {
+        try {
+            em.getTransaction().commit();
+        } catch (PersistenceException e) {
+            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
+        }
+    }
+
+    @Override
+    public void rollback() {
+        em.getTransaction().rollback();
+    }
+
+    @Override
+    public void setRollbackOnly() {
+        em.getTransaction().setRollbackOnly();
+    }
+
+    @Override
+    public boolean getRollbackOnly() {
+        return  em.getTransaction().getRollbackOnly();
+    }
+
+    @Override
+    public boolean isActive() {
+        return em.getTransaction().isActive();
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index 758531a..b9229bb 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -1,129 +1,129 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.jpa.entities.ClientEntity;
-import org.keycloak.models.jpa.entities.RealmEntity;
-import org.keycloak.models.jpa.entities.RoleEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaRealmProvider implements RealmProvider {
-    private final KeycloakSession session;
-    protected EntityManager em;
-
-
-    public JpaRealmProvider(KeycloakSession session, EntityManager em) {
-        this.session = session;
-        this.em = em;
-    }
-
-    @Override
-    public MigrationModel getMigrationModel() {
-        return new MigrationModelAdapter(em);
-    }
-
-    @Override
-    public RealmModel createRealm(String name) {
-        return createRealm(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RealmModel createRealm(String id, String name) {
-        RealmEntity realm = new RealmEntity();
-        realm.setName(name);
-        realm.setId(id);
-        em.persist(realm);
-        em.flush();
-        final RealmModel model = new RealmAdapter(session, em, realm);
-        session.getKeycloakSessionFactory().publish(new RealmModel.RealmCreationEvent() {
-            @Override
-            public RealmModel getCreatedRealm() {
-                return model;
-            }
-        });
-        return model;
-    }
-
-    @Override
-    public RealmModel getRealm(String id) {
-        RealmEntity realm = em.find(RealmEntity.class, id);
-        if (realm == null) return null;
-        return new RealmAdapter(session, em, realm);
-    }
-
-    @Override
-    public List<RealmModel> getRealms() {
-        TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
-        List<RealmEntity> entities = query.getResultList();
-        List<RealmModel> realms = new ArrayList<RealmModel>();
-        for (RealmEntity entity : entities) {
-            realms.add(new RealmAdapter(session, em, entity));
-        }
-        return realms;
-    }
-
-    @Override
-    public RealmModel getRealmByName(String name) {
-        TypedQuery<RealmEntity> query = em.createNamedQuery("getRealmByName", RealmEntity.class);
-        query.setParameter("name", name);
-        List<RealmEntity> entities = query.getResultList();
-        if (entities.size() == 0) return null;
-        if (entities.size() > 1) throw new IllegalStateException("Should not be more than one realm with same name");
-        RealmEntity realm = query.getResultList().get(0);
-        if (realm == null) return null;
-        return new RealmAdapter(session, em, realm);
-    }
-
-    @Override
-    public boolean removeRealm(String id) {
-        RealmEntity realm = em.find(RealmEntity.class, id);
-        if (realm == null) {
-            return false;
-        }
-
-        RealmAdapter adapter = new RealmAdapter(session, em, realm);
-        session.users().preRemove(adapter);
-        for (ClientEntity a : new LinkedList<>(realm.getClients())) {
-            adapter.removeClient(a.getId());
-        }
-
-        em.remove(realm);
-        return true;
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public RoleModel getRoleById(String id, RealmModel realm) {
-        RoleEntity entity = em.find(RoleEntity.class, id);
-        if (entity == null) return null;
-        if (!realm.getId().equals(entity.getRealmId())) return null;
-        return new RoleAdapter(realm, em, entity);
-    }
-
-    @Override
-    public ClientModel getClientById(String id, RealmModel realm) {
-        ClientEntity app = em.find(ClientEntity.class, id);
-
-        // Check if application belongs to this realm
-        if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
-        return new ClientAdapter(realm, em, session, app);
-    }
-
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.jpa.entities.ClientEntity;
+import org.keycloak.models.jpa.entities.RealmEntity;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaRealmProvider implements RealmProvider {
+    private final KeycloakSession session;
+    protected EntityManager em;
+
+
+    public JpaRealmProvider(KeycloakSession session, EntityManager em) {
+        this.session = session;
+        this.em = em;
+    }
+
+    @Override
+    public MigrationModel getMigrationModel() {
+        return new MigrationModelAdapter(em);
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        return createRealm(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        RealmEntity realm = new RealmEntity();
+        realm.setName(name);
+        realm.setId(id);
+        em.persist(realm);
+        em.flush();
+        final RealmModel model = new RealmAdapter(session, em, realm);
+        session.getKeycloakSessionFactory().publish(new RealmModel.RealmCreationEvent() {
+            @Override
+            public RealmModel getCreatedRealm() {
+                return model;
+            }
+        });
+        return model;
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        RealmEntity realm = em.find(RealmEntity.class, id);
+        if (realm == null) return null;
+        return new RealmAdapter(session, em, realm);
+    }
+
+    @Override
+    public List<RealmModel> getRealms() {
+        TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
+        List<RealmEntity> entities = query.getResultList();
+        List<RealmModel> realms = new ArrayList<RealmModel>();
+        for (RealmEntity entity : entities) {
+            realms.add(new RealmAdapter(session, em, entity));
+        }
+        return realms;
+    }
+
+    @Override
+    public RealmModel getRealmByName(String name) {
+        TypedQuery<RealmEntity> query = em.createNamedQuery("getRealmByName", RealmEntity.class);
+        query.setParameter("name", name);
+        List<RealmEntity> entities = query.getResultList();
+        if (entities.size() == 0) return null;
+        if (entities.size() > 1) throw new IllegalStateException("Should not be more than one realm with same name");
+        RealmEntity realm = query.getResultList().get(0);
+        if (realm == null) return null;
+        return new RealmAdapter(session, em, realm);
+    }
+
+    @Override
+    public boolean removeRealm(String id) {
+        RealmEntity realm = em.find(RealmEntity.class, id);
+        if (realm == null) {
+            return false;
+        }
+
+        RealmAdapter adapter = new RealmAdapter(session, em, realm);
+        session.users().preRemove(adapter);
+        for (ClientEntity a : new LinkedList<>(realm.getClients())) {
+            adapter.removeClient(a.getId());
+        }
+
+        em.remove(realm);
+        return true;
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public RoleModel getRoleById(String id, RealmModel realm) {
+        RoleEntity entity = em.find(RoleEntity.class, id);
+        if (entity == null) return null;
+        if (!realm.getId().equals(entity.getRealmId())) return null;
+        return new RoleAdapter(realm, em, entity);
+    }
+
+    @Override
+    public ClientModel getClientById(String id, RealmModel realm) {
+        ClientEntity app = em.find(ClientEntity.class, id);
+
+        // Check if application belongs to this realm
+        if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
+        return new ClientAdapter(realm, em, session, app);
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
index 886522c..02a2a02 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProviderFactory.java
@@ -1,42 +1,42 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.Config;
-import org.keycloak.connections.jpa.JpaConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RealmProviderFactory;
-
-import javax.persistence.EntityManager;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaRealmProviderFactory implements RealmProviderFactory {
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return "jpa";
-    }
-
-    @Override
-    public RealmProvider create(KeycloakSession session) {
-        EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
-        return new JpaRealmProvider(session, em);
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.Config;
+import org.keycloak.connections.jpa.JpaConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RealmProviderFactory;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaRealmProviderFactory implements RealmProviderFactory {
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return "jpa";
+    }
+
+    @Override
+    public RealmProvider create(KeycloakSession session) {
+        EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
+        return new JpaRealmProvider(session, em);
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
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 b2915ed..03ad18f 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
@@ -1,426 +1,426 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.jpa.entities.FederatedIdentityEntity;
-import org.keycloak.models.jpa.entities.UserEntity;
-import org.keycloak.models.utils.CredentialValidation;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaUserProvider implements UserProvider {
-
-    private static final String EMAIL = "email";
-    private static final String USERNAME = "username";
-    private static final String FIRST_NAME = "firstName";
-    private static final String LAST_NAME = "lastName";
-
-    private final KeycloakSession session;
-    protected EntityManager em;
-
-    public JpaUserProvider(KeycloakSession session, EntityManager em) {
-        this.session = session;
-        this.em = em;
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
-        if (id == null) {
-            id = KeycloakModelUtils.generateId();
-        }
-
-        UserEntity entity = new UserEntity();
-        entity.setId(id);
-        entity.setCreatedTimestamp(System.currentTimeMillis());
-        entity.setUsername(username.toLowerCase());
-        entity.setRealmId(realm.getId());
-        em.persist(entity);
-        em.flush();
-        UserModel userModel = new UserAdapter(realm, em, entity);
-
-        if (addDefaultRoles) {
-            for (String r : realm.getDefaultRoles()) {
-                userModel.grantRole(realm.getRole(r));
-            }
-
-            for (ClientModel application : realm.getClients()) {
-                for (String r : application.getDefaultRoles()) {
-                    userModel.grantRole(application.getRole(r));
-                }
-            }
-        }
-        for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
-            if (r.isEnabled() && r.isDefaultAction()) {
-                userModel.addRequiredAction(r.getAlias());
-            }
-        }
-
-        return userModel;
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String username) {
-        return addUser(realm, KeycloakModelUtils.generateId(), username.toLowerCase(), true, true);
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        UserEntity userEntity = em.find(UserEntity.class, user.getId());
-        if (userEntity == null) return false;
-        removeUser(userEntity);
-        return true;
-    }
-
-    private void removeUser(UserEntity user) {
-        String id = user.getId();
-        em.createNamedQuery("deleteUserRoleMappingsByUser").setParameter("user", user).executeUpdate();
-        em.createNamedQuery("deleteFederatedIdentityByUser").setParameter("user", user).executeUpdate();
-        em.createNamedQuery("deleteUserConsentRolesByUser").setParameter("user", user).executeUpdate();
-        em.createNamedQuery("deleteUserConsentProtMappersByUser").setParameter("user", user).executeUpdate();
-        em.createNamedQuery("deleteUserConsentsByUser").setParameter("user", user).executeUpdate();
-        em.flush();
-        // not sure why i have to do a clear() here.  I was getting some messed up errors that Hibernate couldn't
-        // un-delete the UserEntity.
-        em.clear();
-        user = em.find(UserEntity.class, id);
-        if (user != null) {
-            em.remove(user);
-        }
-        em.flush();
-    }
-
-    @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel identity) {
-        FederatedIdentityEntity entity = new FederatedIdentityEntity();
-        entity.setRealmId(realm.getId());
-        entity.setIdentityProvider(identity.getIdentityProvider());
-        entity.setUserId(identity.getUserId());
-        entity.setUserName(identity.getUserName().toLowerCase());
-        entity.setToken(identity.getToken());
-        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
-        entity.setUser(userEntity);
-        em.persist(entity);
-        em.flush();
-    }
-
-    @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        FederatedIdentityEntity federatedIdentity = findFederatedIdentity(federatedUser, federatedIdentityModel.getIdentityProvider());
-
-        federatedIdentity.setToken(federatedIdentityModel.getToken());
-
-        em.persist(federatedIdentity);
-        em.flush();
-    }
-
-    @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String identityProvider) {
-        FederatedIdentityEntity entity = findFederatedIdentity(user, identityProvider);
-        if (entity != null) {
-            em.remove(entity);
-            em.flush();
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUserConsentProtMappersByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUserConsentsByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUserRoleMappingsByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUserRequiredActionsByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteFederatedIdentityByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteCredentialsByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUserAttributesByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-        num = em.createNamedQuery("deleteUsersByRealm")
-                .setParameter("realmId", realm.getId()).executeUpdate();
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
-        int num = em.createNamedQuery("deleteUserRoleMappingsByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-        num = em.createNamedQuery("deleteUserRequiredActionsByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-        num = em.createNamedQuery("deleteFederatedIdentityByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-        num = em.createNamedQuery("deleteCredentialsByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-        num = em.createNamedQuery("deleteUserAttributesByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-        num = em.createNamedQuery("deleteUsersByRealmAndLink")
-                .setParameter("realmId", realm.getId())
-                .setParameter("link", link.getId())
-                .executeUpdate();
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        em.createNamedQuery("deleteUserConsentRolesByRole").setParameter("roleId", role.getId()).executeUpdate();
-        em.createNamedQuery("deleteUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, ClientModel client) {
-        em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
-    }
-
-    @Override
-    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
-        em.createNamedQuery("deleteUserConsentProtMappersByProtocolMapper")
-                .setParameter("protocolMapperId", protocolMapper.getId())
-                .executeUpdate();
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
-        query.setParameter("id", id);
-        query.setParameter("realmId", realm.getId());
-        List<UserEntity> entities = query.getResultList();
-        if (entities.size() == 0) return null;
-        return new UserAdapter(realm, em, entities.get(0));
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
-        query.setParameter("username", username.toLowerCase());
-        query.setParameter("realmId", realm.getId());
-        List<UserEntity> results = query.getResultList();
-        if (results.size() == 0) return null;
-        return new UserAdapter(realm, em, results.get(0));
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
-        query.setParameter("email", email.toLowerCase());
-        query.setParameter("realmId", realm.getId());
-        List<UserEntity> results = query.getResultList();
-        return results.isEmpty() ? null : new UserAdapter(realm, em, results.get(0));
-    }
-
-     @Override
-    public void close() {
-    }
-
-    @Override
-    public UserModel getUserByFederatedIdentity(FederatedIdentityModel identity, RealmModel realm) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("findUserByFederatedIdentityAndRealm", UserEntity.class);
-        query.setParameter("realmId", realm.getId());
-        query.setParameter("identityProvider", identity.getIdentityProvider());
-        query.setParameter("userId", identity.getUserId());
-        List<UserEntity> results = query.getResultList();
-        if (results.isEmpty()) {
-            return null;
-        } else if (results.size() > 1) {
-            throw new IllegalStateException("More results found for identityProvider=" + identity.getIdentityProvider() +
-                    ", userId=" + identity.getUserId() + ", results=" + results);
-        } else {
-            UserEntity user = results.get(0);
-            return new UserAdapter(realm, em, user);
-        }
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return getUsers(realm, -1, -1);
-    }
-
-    @Override
-    public int getUsersCount(RealmModel realm) {
-        // TODO: named query?
-        Object count = em.createNamedQuery("getRealmUserCount")
-                .setParameter("realmId", realm.getId())
-                .getSingleResult();
-        return ((Number)count).intValue();
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getAllUsersByRealm", UserEntity.class);
-        query.setParameter("realmId", realm.getId());
-        if (firstResult != -1) {
-            query.setFirstResult(firstResult);
-        }
-        if (maxResults != -1) {
-            query.setMaxResults(maxResults);
-        }
-        List<UserEntity> results = query.getResultList();
-        List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
-        return users;
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return searchForUser(search, realm, -1, -1);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("searchForUser", UserEntity.class);
-        query.setParameter("realmId", realm.getId());
-        query.setParameter("search", "%" + search.toLowerCase() + "%");
-        if (firstResult != -1) {
-            query.setFirstResult(firstResult);
-        }
-        if (maxResults != -1) {
-            query.setMaxResults(maxResults);
-        }
-        List<UserEntity> results = query.getResultList();
-        List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
-        return users;
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return searchForUserByAttributes(attributes, realm, -1, -1);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
-        StringBuilder builder = new StringBuilder("select u from UserEntity u where u.realmId = :realmId");
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            String attribute = null;
-            String parameterName = null;
-            if (entry.getKey().equals(UserModel.USERNAME)) {
-                attribute = "lower(u.username)";
-                parameterName = JpaUserProvider.USERNAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
-                attribute = "lower(u.firstName)";
-                parameterName = JpaUserProvider.FIRST_NAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
-                attribute = "lower(u.lastName)";
-                parameterName = JpaUserProvider.LAST_NAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
-                attribute = "lower(u.email)";
-                parameterName = JpaUserProvider.EMAIL;
-            }
-            if (attribute == null) continue;
-            builder.append(" and ");
-            builder.append(attribute).append(" like :").append(parameterName);
-        }
-        builder.append(" order by u.username");
-        String q = builder.toString();
-        TypedQuery<UserEntity> query = em.createQuery(q, UserEntity.class);
-        query.setParameter("realmId", realm.getId());
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            String parameterName = null;
-            if (entry.getKey().equals(UserModel.USERNAME)) {
-                parameterName = JpaUserProvider.USERNAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
-                parameterName = JpaUserProvider.FIRST_NAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
-                parameterName = JpaUserProvider.LAST_NAME;
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
-                parameterName = JpaUserProvider.EMAIL;
-            }
-            if (parameterName == null) continue;
-            query.setParameter(parameterName, "%" + entry.getValue().toLowerCase() + "%");
-        }
-        if (firstResult != -1) {
-            query.setFirstResult(firstResult);
-        }
-        if (maxResults != -1) {
-            query.setMaxResults(maxResults);
-        }
-        List<UserEntity> results = query.getResultList();
-        List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
-        return users;
-    }
-
-    private FederatedIdentityEntity findFederatedIdentity(UserModel user, String identityProvider) {
-        TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUserAndProvider", FederatedIdentityEntity.class);
-        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
-        query.setParameter("user", userEntity);
-        query.setParameter("identityProvider", identityProvider);
-        List<FederatedIdentityEntity> results = query.getResultList();
-        return results.size() > 0 ? results.get(0) : null;
-    }
-
-
-    @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
-        TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUser", FederatedIdentityEntity.class);
-        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
-        query.setParameter("user", userEntity);
-        List<FederatedIdentityEntity> results = query.getResultList();
-        Set<FederatedIdentityModel> set = new HashSet<FederatedIdentityModel>();
-        for (FederatedIdentityEntity entity : results) {
-            set.add(new FederatedIdentityModel(entity.getIdentityProvider(), entity.getUserId(), entity.getUserName(), entity.getToken()));
-        }
-        return set;
-    }
-
-    @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String identityProvider, RealmModel realm) {
-        FederatedIdentityEntity entity = findFederatedIdentity(user, identityProvider);
-        return (entity != null) ? new FederatedIdentityModel(entity.getIdentityProvider(), entity.getUserId(), entity.getUserName(), entity.getToken()) : null;
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        return CredentialValidation.validCredentials(realm, user, input);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return CredentialValidation.validCredentials(realm, user, input);
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
-        // Not supported yet
-        return null;
-    }
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.jpa.entities.FederatedIdentityEntity;
+import org.keycloak.models.jpa.entities.UserEntity;
+import org.keycloak.models.utils.CredentialValidation;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaUserProvider implements UserProvider {
+
+    private static final String EMAIL = "email";
+    private static final String USERNAME = "username";
+    private static final String FIRST_NAME = "firstName";
+    private static final String LAST_NAME = "lastName";
+
+    private final KeycloakSession session;
+    protected EntityManager em;
+
+    public JpaUserProvider(KeycloakSession session, EntityManager em) {
+        this.session = session;
+        this.em = em;
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+        if (id == null) {
+            id = KeycloakModelUtils.generateId();
+        }
+
+        UserEntity entity = new UserEntity();
+        entity.setId(id);
+        entity.setCreatedTimestamp(System.currentTimeMillis());
+        entity.setUsername(username.toLowerCase());
+        entity.setRealmId(realm.getId());
+        em.persist(entity);
+        em.flush();
+        UserModel userModel = new UserAdapter(realm, em, entity);
+
+        if (addDefaultRoles) {
+            for (String r : realm.getDefaultRoles()) {
+                userModel.grantRole(realm.getRole(r));
+            }
+
+            for (ClientModel application : realm.getClients()) {
+                for (String r : application.getDefaultRoles()) {
+                    userModel.grantRole(application.getRole(r));
+                }
+            }
+        }
+        for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
+            if (r.isEnabled() && r.isDefaultAction()) {
+                userModel.addRequiredAction(r.getAlias());
+            }
+        }
+
+        return userModel;
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String username) {
+        return addUser(realm, KeycloakModelUtils.generateId(), username.toLowerCase(), true, true);
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        UserEntity userEntity = em.find(UserEntity.class, user.getId());
+        if (userEntity == null) return false;
+        removeUser(userEntity);
+        return true;
+    }
+
+    private void removeUser(UserEntity user) {
+        String id = user.getId();
+        em.createNamedQuery("deleteUserRoleMappingsByUser").setParameter("user", user).executeUpdate();
+        em.createNamedQuery("deleteFederatedIdentityByUser").setParameter("user", user).executeUpdate();
+        em.createNamedQuery("deleteUserConsentRolesByUser").setParameter("user", user).executeUpdate();
+        em.createNamedQuery("deleteUserConsentProtMappersByUser").setParameter("user", user).executeUpdate();
+        em.createNamedQuery("deleteUserConsentsByUser").setParameter("user", user).executeUpdate();
+        em.flush();
+        // not sure why i have to do a clear() here.  I was getting some messed up errors that Hibernate couldn't
+        // un-delete the UserEntity.
+        em.clear();
+        user = em.find(UserEntity.class, id);
+        if (user != null) {
+            em.remove(user);
+        }
+        em.flush();
+    }
+
+    @Override
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel identity) {
+        FederatedIdentityEntity entity = new FederatedIdentityEntity();
+        entity.setRealmId(realm.getId());
+        entity.setIdentityProvider(identity.getIdentityProvider());
+        entity.setUserId(identity.getUserId());
+        entity.setUserName(identity.getUserName().toLowerCase());
+        entity.setToken(identity.getToken());
+        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
+        entity.setUser(userEntity);
+        em.persist(entity);
+        em.flush();
+    }
+
+    @Override
+    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+        FederatedIdentityEntity federatedIdentity = findFederatedIdentity(federatedUser, federatedIdentityModel.getIdentityProvider());
+
+        federatedIdentity.setToken(federatedIdentityModel.getToken());
+
+        em.persist(federatedIdentity);
+        em.flush();
+    }
+
+    @Override
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String identityProvider) {
+        FederatedIdentityEntity entity = findFederatedIdentity(user, identityProvider);
+        if (entity != null) {
+            em.remove(entity);
+            em.flush();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUserConsentProtMappersByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUserConsentsByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUserRoleMappingsByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUserRequiredActionsByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteFederatedIdentityByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteCredentialsByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUserAttributesByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+        num = em.createNamedQuery("deleteUsersByRealm")
+                .setParameter("realmId", realm.getId()).executeUpdate();
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
+        int num = em.createNamedQuery("deleteUserRoleMappingsByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+        num = em.createNamedQuery("deleteUserRequiredActionsByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+        num = em.createNamedQuery("deleteFederatedIdentityByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+        num = em.createNamedQuery("deleteCredentialsByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+        num = em.createNamedQuery("deleteUserAttributesByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+        num = em.createNamedQuery("deleteUsersByRealmAndLink")
+                .setParameter("realmId", realm.getId())
+                .setParameter("link", link.getId())
+                .executeUpdate();
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        em.createNamedQuery("deleteUserConsentRolesByRole").setParameter("roleId", role.getId()).executeUpdate();
+        em.createNamedQuery("deleteUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, ClientModel client) {
+        em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
+        em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
+        em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
+    }
+
+    @Override
+    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
+        em.createNamedQuery("deleteUserConsentProtMappersByProtocolMapper")
+                .setParameter("protocolMapperId", protocolMapper.getId())
+                .executeUpdate();
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
+        query.setParameter("id", id);
+        query.setParameter("realmId", realm.getId());
+        List<UserEntity> entities = query.getResultList();
+        if (entities.size() == 0) return null;
+        return new UserAdapter(realm, em, entities.get(0));
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
+        query.setParameter("username", username.toLowerCase());
+        query.setParameter("realmId", realm.getId());
+        List<UserEntity> results = query.getResultList();
+        if (results.size() == 0) return null;
+        return new UserAdapter(realm, em, results.get(0));
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
+        query.setParameter("email", email.toLowerCase());
+        query.setParameter("realmId", realm.getId());
+        List<UserEntity> results = query.getResultList();
+        return results.isEmpty() ? null : new UserAdapter(realm, em, results.get(0));
+    }
+
+     @Override
+    public void close() {
+    }
+
+    @Override
+    public UserModel getUserByFederatedIdentity(FederatedIdentityModel identity, RealmModel realm) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("findUserByFederatedIdentityAndRealm", UserEntity.class);
+        query.setParameter("realmId", realm.getId());
+        query.setParameter("identityProvider", identity.getIdentityProvider());
+        query.setParameter("userId", identity.getUserId());
+        List<UserEntity> results = query.getResultList();
+        if (results.isEmpty()) {
+            return null;
+        } else if (results.size() > 1) {
+            throw new IllegalStateException("More results found for identityProvider=" + identity.getIdentityProvider() +
+                    ", userId=" + identity.getUserId() + ", results=" + results);
+        } else {
+            UserEntity user = results.get(0);
+            return new UserAdapter(realm, em, user);
+        }
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getUsers(realm, -1, -1);
+    }
+
+    @Override
+    public int getUsersCount(RealmModel realm) {
+        // TODO: named query?
+        Object count = em.createNamedQuery("getRealmUserCount")
+                .setParameter("realmId", realm.getId())
+                .getSingleResult();
+        return ((Number)count).intValue();
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getAllUsersByRealm", UserEntity.class);
+        query.setParameter("realmId", realm.getId());
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResults != -1) {
+            query.setMaxResults(maxResults);
+        }
+        List<UserEntity> results = query.getResultList();
+        List<UserModel> users = new ArrayList<UserModel>();
+        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
+        return users;
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return searchForUser(search, realm, -1, -1);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("searchForUser", UserEntity.class);
+        query.setParameter("realmId", realm.getId());
+        query.setParameter("search", "%" + search.toLowerCase() + "%");
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResults != -1) {
+            query.setMaxResults(maxResults);
+        }
+        List<UserEntity> results = query.getResultList();
+        List<UserModel> users = new ArrayList<UserModel>();
+        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
+        return users;
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return searchForUserByAttributes(attributes, realm, -1, -1);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
+        StringBuilder builder = new StringBuilder("select u from UserEntity u where u.realmId = :realmId");
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            String attribute = null;
+            String parameterName = null;
+            if (entry.getKey().equals(UserModel.USERNAME)) {
+                attribute = "lower(u.username)";
+                parameterName = JpaUserProvider.USERNAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
+                attribute = "lower(u.firstName)";
+                parameterName = JpaUserProvider.FIRST_NAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
+                attribute = "lower(u.lastName)";
+                parameterName = JpaUserProvider.LAST_NAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
+                attribute = "lower(u.email)";
+                parameterName = JpaUserProvider.EMAIL;
+            }
+            if (attribute == null) continue;
+            builder.append(" and ");
+            builder.append(attribute).append(" like :").append(parameterName);
+        }
+        builder.append(" order by u.username");
+        String q = builder.toString();
+        TypedQuery<UserEntity> query = em.createQuery(q, UserEntity.class);
+        query.setParameter("realmId", realm.getId());
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            String parameterName = null;
+            if (entry.getKey().equals(UserModel.USERNAME)) {
+                parameterName = JpaUserProvider.USERNAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
+                parameterName = JpaUserProvider.FIRST_NAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
+                parameterName = JpaUserProvider.LAST_NAME;
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
+                parameterName = JpaUserProvider.EMAIL;
+            }
+            if (parameterName == null) continue;
+            query.setParameter(parameterName, "%" + entry.getValue().toLowerCase() + "%");
+        }
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResults != -1) {
+            query.setMaxResults(maxResults);
+        }
+        List<UserEntity> results = query.getResultList();
+        List<UserModel> users = new ArrayList<UserModel>();
+        for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
+        return users;
+    }
+
+    private FederatedIdentityEntity findFederatedIdentity(UserModel user, String identityProvider) {
+        TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUserAndProvider", FederatedIdentityEntity.class);
+        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
+        query.setParameter("user", userEntity);
+        query.setParameter("identityProvider", identityProvider);
+        List<FederatedIdentityEntity> results = query.getResultList();
+        return results.size() > 0 ? results.get(0) : null;
+    }
+
+
+    @Override
+    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
+        TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUser", FederatedIdentityEntity.class);
+        UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
+        query.setParameter("user", userEntity);
+        List<FederatedIdentityEntity> results = query.getResultList();
+        Set<FederatedIdentityModel> set = new HashSet<FederatedIdentityModel>();
+        for (FederatedIdentityEntity entity : results) {
+            set.add(new FederatedIdentityModel(entity.getIdentityProvider(), entity.getUserId(), entity.getUserName(), entity.getToken()));
+        }
+        return set;
+    }
+
+    @Override
+    public FederatedIdentityModel getFederatedIdentity(UserModel user, String identityProvider, RealmModel realm) {
+        FederatedIdentityEntity entity = findFederatedIdentity(user, identityProvider);
+        return (entity != null) ? new FederatedIdentityModel(entity.getIdentityProvider(), entity.getUserId(), entity.getUserName(), entity.getToken()) : null;
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        return CredentialValidation.validCredentials(realm, user, input);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return CredentialValidation.validCredentials(realm, user, input);
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
+        // Not supported yet
+        return null;
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java
index b7d7cf3..d19f295 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java
@@ -1,42 +1,42 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.Config;
-import org.keycloak.connections.jpa.JpaConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.UserProviderFactory;
-
-import javax.persistence.EntityManager;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaUserProviderFactory implements UserProviderFactory {
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return "jpa";
-    }
-
-    @Override
-    public UserProvider create(KeycloakSession session) {
-        EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
-        return new JpaUserProvider(session, em);
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.Config;
+import org.keycloak.connections.jpa.JpaConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.UserProviderFactory;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaUserProviderFactory implements UserProviderFactory {
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return "jpa";
+    }
+
+    @Override
+    public UserProvider create(KeycloakSession session) {
+        EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
+        return new JpaUserProvider(session, em);
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/MigrationModelAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/MigrationModelAdapter.java
index 034e141..9fcaab8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/MigrationModelAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/MigrationModelAdapter.java
@@ -1,42 +1,42 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.jpa.entities.MigrationModelEntity;
-import org.keycloak.util.Time;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class MigrationModelAdapter implements MigrationModel {
-    protected EntityManager em;
-
-    public MigrationModelAdapter(EntityManager em) {
-        this.em = em;
-    }
-
-    @Override
-    public String getStoredVersion() {
-        MigrationModelEntity entity = em.find(MigrationModelEntity.class, MigrationModelEntity.SINGLETON_ID);
-        if (entity == null) return null;
-        return entity.getVersion();
-    }
-
-    @Override
-    public void setStoredVersion(String version) {
-        MigrationModelEntity entity = em.find(MigrationModelEntity.class, MigrationModelEntity.SINGLETON_ID);
-        if (entity == null) {
-            entity = new MigrationModelEntity();
-            entity.setId(MigrationModelEntity.SINGLETON_ID);
-            entity.setVersion(version);
-            em.persist(entity);
-        } else {
-            entity.setVersion(version);
-            em.flush();
-        }
-    }
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.jpa.entities.MigrationModelEntity;
+import org.keycloak.util.Time;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrationModelAdapter implements MigrationModel {
+    protected EntityManager em;
+
+    public MigrationModelAdapter(EntityManager em) {
+        this.em = em;
+    }
+
+    @Override
+    public String getStoredVersion() {
+        MigrationModelEntity entity = em.find(MigrationModelEntity.class, MigrationModelEntity.SINGLETON_ID);
+        if (entity == null) return null;
+        return entity.getVersion();
+    }
+
+    @Override
+    public void setStoredVersion(String version) {
+        MigrationModelEntity entity = em.find(MigrationModelEntity.class, MigrationModelEntity.SINGLETON_ID);
+        if (entity == null) {
+            entity = new MigrationModelEntity();
+            entity.setId(MigrationModelEntity.SINGLETON_ID);
+            entity.setVersion(version);
+            em.persist(entity);
+        } else {
+            entity.setVersion(version);
+            em.flush();
+        }
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 5a0d159..51148f0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1,1838 +1,1838 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationMapperEventImpl;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProviderCreationEventImpl;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.jpa.entities.AuthenticationExecutionEntity;
-import org.keycloak.models.jpa.entities.AuthenticationFlowEntity;
-import org.keycloak.models.jpa.entities.AuthenticatorConfigEntity;
-import org.keycloak.models.jpa.entities.ClientEntity;
-import org.keycloak.models.jpa.entities.IdentityProviderEntity;
-import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
-import org.keycloak.models.jpa.entities.RealmAttributeEntity;
-import org.keycloak.models.jpa.entities.RealmEntity;
-import org.keycloak.models.jpa.entities.RequiredActionProviderEntity;
-import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
-import org.keycloak.models.jpa.entities.RoleEntity;
-import org.keycloak.models.jpa.entities.UserFederationMapperEntity;
-import org.keycloak.models.jpa.entities.UserFederationProviderEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmAdapter implements RealmModel {
-    protected RealmEntity realm;
-    protected EntityManager em;
-    protected volatile transient PublicKey publicKey;
-    protected volatile transient PrivateKey privateKey;
-    protected volatile transient X509Certificate certificate;
-    protected volatile transient Key codeSecretKey;
-    protected KeycloakSession session;
-    private PasswordPolicy passwordPolicy;
-
-    public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) {
-        this.session = session;
-        this.em = em;
-        this.realm = realm;
-    }
-
-    public RealmEntity getEntity() {
-        return realm;
-    }
-
-    @Override
-    public String getId() {
-        return realm.getId();
-    }
-
-    @Override
-    public String getName() {
-        return realm.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        realm.setName(name);
-        em.flush();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return realm.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        realm.setEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public SslRequired getSslRequired() {
-        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
-    }
-
-    @Override
-    public void setSslRequired(SslRequired sslRequired) {
-        realm.setSslRequired(sslRequired.name());
-        em.flush();
-    }
-
-    @Override
-    public boolean isRegistrationAllowed() {
-        return realm.isRegistrationAllowed();
-    }
-
-    @Override
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        realm.setRegistrationAllowed(registrationAllowed);
-        em.flush();
-    }
-
-    @Override
-    public boolean isRegistrationEmailAsUsername() {
-        return realm.isRegistrationEmailAsUsername();
-    }
-
-    @Override
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
-        em.flush();
-    }
-
-    @Override
-    public boolean isRememberMe() {
-        return realm.isRememberMe();
-    }
-
-    @Override
-    public void setRememberMe(boolean rememberMe) {
-        realm.setRememberMe(rememberMe);
-        em.flush();
-    }
-
-    public void setAttribute(String name, String value) {
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                attr.setValue(value);
-                return;
-            }
-        }
-        RealmAttributeEntity attr = new RealmAttributeEntity();
-        attr.setName(name);
-        attr.setValue(value);
-        attr.setRealm(realm);
-        em.persist(attr);
-        realm.getAttributes().add(attr);
-    }
-
-    public void setAttribute(String name, Boolean value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void setAttribute(String name, Integer value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void setAttribute(String name, Long value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void removeAttribute(String name) {
-        Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator();
-        while (it.hasNext()) {
-            RealmAttributeEntity attr = it.next();
-            if (attr.getName().equals(name)) {
-                it.remove();
-                em.remove(attr);
-            }
-        }
-    }
-
-    public String getAttribute(String name) {
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                return attr.getValue();
-            }
-        }
-        return null;
-    }
-
-    public Integer getAttribute(String name, Integer defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Integer.parseInt(v) : defaultValue;
-
-    }
-
-    public Long getAttribute(String name, Long defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Long.parseLong(v) : defaultValue;
-
-    }
-
-    public Boolean getAttribute(String name, Boolean defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Boolean.parseBoolean(v) : defaultValue;
-
-    }
-
-    public Map<String, String> getAttributes() {
-        // should always return a copy
-        Map<String, String> result = new HashMap<String, String>();
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            result.put(attr.getName(), attr.getValue());
-        }
-        return result;
-    }
-    @Override
-    public boolean isBruteForceProtected() {
-        return getAttribute("bruteForceProtected", false);
-    }
-
-    @Override
-    public void setBruteForceProtected(boolean value) {
-        setAttribute("bruteForceProtected", value);
-    }
-
-    @Override
-    public int getMaxFailureWaitSeconds() {
-        return getAttribute("maxFailureWaitSeconds", 0);
-    }
-
-    @Override
-    public void setMaxFailureWaitSeconds(int val) {
-        setAttribute("maxFailureWaitSeconds", val);
-    }
-
-    @Override
-    public int getWaitIncrementSeconds() {
-        return getAttribute("waitIncrementSeconds", 0);
-    }
-
-    @Override
-    public void setWaitIncrementSeconds(int val) {
-        setAttribute("waitIncrementSeconds", val);
-    }
-
-    @Override
-    public long getQuickLoginCheckMilliSeconds() {
-        return getAttribute("quickLoginCheckMilliSeconds", 0l);
-    }
-
-    @Override
-    public void setQuickLoginCheckMilliSeconds(long val) {
-        setAttribute("quickLoginCheckMilliSeconds", val);
-    }
-
-    @Override
-    public int getMinimumQuickLoginWaitSeconds() {
-        return getAttribute("minimumQuickLoginWaitSeconds", 0);
-    }
-
-    @Override
-    public void setMinimumQuickLoginWaitSeconds(int val) {
-        setAttribute("minimumQuickLoginWaitSeconds", val);
-    }
-
-    @Override
-    public int getMaxDeltaTimeSeconds() {
-        return getAttribute("maxDeltaTimeSeconds", 0);
-    }
-
-    @Override
-    public void setMaxDeltaTimeSeconds(int val) {
-        setAttribute("maxDeltaTimeSeconds", val);
-    }
-
-    @Override
-    public int getFailureFactor() {
-        return getAttribute("failureFactor", 0);
-    }
-
-    @Override
-    public void setFailureFactor(int failureFactor) {
-        setAttribute("failureFactor", failureFactor);
-    }
-
-    @Override
-    public boolean isVerifyEmail() {
-        return realm.isVerifyEmail();
-    }
-
-    @Override
-    public void setVerifyEmail(boolean verifyEmail) {
-        realm.setVerifyEmail(verifyEmail);
-        em.flush();
-    }
-
-    @Override
-    public boolean isResetPasswordAllowed() {
-        return realm.isResetPasswordAllowed();
-    }
-
-    @Override
-    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
-        realm.setResetPasswordAllowed(resetPasswordAllowed);
-        em.flush();
-    }
-
-    @Override
-    public boolean isEditUsernameAllowed() {
-        return realm.isEditUsernameAllowed();
-    }
-
-    @Override
-    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
-        realm.setEditUsernameAllowed(editUsernameAllowed);
-        em.flush();
-    }
-
-    @Override
-    public int getNotBefore() {
-        return realm.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        realm.setNotBefore(notBefore);
-    }
-
-    @Override
-    public int getAccessTokenLifespan() {
-        return realm.getAccessTokenLifespan();
-    }
-
-    @Override
-    public void setAccessTokenLifespan(int tokenLifespan) {
-        realm.setAccessTokenLifespan(tokenLifespan);
-        em.flush();
-    }
-
-    @Override
-    public int getSsoSessionIdleTimeout() {
-        return realm.getSsoSessionIdleTimeout();
-    }
-
-    @Override
-    public void setSsoSessionIdleTimeout(int seconds) {
-        realm.setSsoSessionIdleTimeout(seconds);
-    }
-
-    @Override
-    public int getSsoSessionMaxLifespan() {
-        return realm.getSsoSessionMaxLifespan();
-    }
-
-    @Override
-    public void setSsoSessionMaxLifespan(int seconds) {
-        realm.setSsoSessionMaxLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessCodeLifespan() {
-        return realm.getAccessCodeLifespan();
-    }
-
-    @Override
-    public void setAccessCodeLifespan(int accessCodeLifespan) {
-        realm.setAccessCodeLifespan(accessCodeLifespan);
-        em.flush();
-    }
-
-    @Override
-    public int getAccessCodeLifespanUserAction() {
-        return realm.getAccessCodeLifespanUserAction();
-    }
-
-    @Override
-    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
-        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
-        em.flush();
-    }
-
-    @Override
-    public int getAccessCodeLifespanLogin() {
-        return realm.getAccessCodeLifespanLogin();
-    }
-
-    @Override
-    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
-        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
-        em.flush();
-    }
-
-    @Override
-    public String getPublicKeyPem() {
-        return realm.getPublicKeyPem();
-    }
-
-    @Override
-    public void setPublicKeyPem(String publicKeyPem) {
-        realm.setPublicKeyPem(publicKeyPem);
-        em.flush();
-    }
-
-    @Override
-    public X509Certificate getCertificate() {
-        if (certificate != null) return certificate;
-        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
-        return certificate;
-    }
-
-    @Override
-    public void setCertificate(X509Certificate certificate) {
-        this.certificate = certificate;
-        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
-        setCertificatePem(certificatePem);
-
-    }
-
-    @Override
-    public String getCertificatePem() {
-        return realm.getCertificatePem();
-    }
-
-    @Override
-    public void setCertificatePem(String certificate) {
-        realm.setCertificatePem(certificate);
-
-    }
-
-    @Override
-    public String getPrivateKeyPem() {
-        return realm.getPrivateKeyPem();
-    }
-
-    @Override
-    public void setPrivateKeyPem(String privateKeyPem) {
-        realm.setPrivateKeyPem(privateKeyPem);
-        em.flush();
-    }
-
-    @Override
-    public PublicKey getPublicKey() {
-        if (publicKey != null) return publicKey;
-        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
-        return publicKey;
-    }
-
-    @Override
-    public void setPublicKey(PublicKey publicKey) {
-        this.publicKey = publicKey;
-        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
-        setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public PrivateKey getPrivateKey() {
-        if (privateKey != null) return privateKey;
-        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
-        return privateKey;
-    }
-
-    @Override
-    public void setPrivateKey(PrivateKey privateKey) {
-        this.privateKey = privateKey;
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-        setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public String getCodeSecret() {
-        return realm.getCodeSecret();
-    }
-
-    @Override
-    public Key getCodeSecretKey() {
-        if (codeSecretKey == null) {
-            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
-        }
-        return codeSecretKey;
-    }
-
-    @Override
-    public void setCodeSecret(String codeSecret) {
-        realm.setCodeSecret(codeSecret);
-    }
-
-    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
-        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
-        if (model == null) {
-            throw new RuntimeException("Unknown credential type " + type);
-        }
-        return model;
-    }
-
-    @Override
-    public void addRequiredCredential(String type) {
-        RequiredCredentialModel model = initRequiredCredentialModel(type);
-        addRequiredCredential(model);
-        em.flush();
-    }
-
-    public void addRequiredCredential(RequiredCredentialModel model) {
-        RequiredCredentialEntity entity = new RequiredCredentialEntity();
-        entity.setRealm(realm);
-        entity.setInput(model.isInput());
-        entity.setSecret(model.isSecret());
-        entity.setType(model.getType());
-        entity.setFormLabel(model.getFormLabel());
-        em.persist(entity);
-        realm.getRequiredCredentials().add(entity);
-        em.flush();
-    }
-
-    @Override
-    public void updateRequiredCredentials(Set<String> creds) {
-        Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
-        if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
-
-        Set<String> already = new HashSet<String>();
-        List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
-        for (RequiredCredentialEntity rel : relationships) {
-            if (!creds.contains(rel.getType())) {
-                remove.add(rel);
-            } else {
-                already.add(rel.getType());
-            }
-        }
-        for (RequiredCredentialEntity entity : remove) {
-            relationships.remove(entity);
-            em.remove(entity);
-        }
-        for (String cred : creds) {
-            if (!already.contains(cred)) {
-                addRequiredCredential(cred);
-            }
-        }
-        em.flush();
-    }
-
-
-    @Override
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-        List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
-        Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
-        if (entities == null) return requiredCredentialModels;
-        for (RequiredCredentialEntity entity : entities) {
-            RequiredCredentialModel model = new RequiredCredentialModel();
-            model.setFormLabel(entity.getFormLabel());
-            model.setType(entity.getType());
-            model.setSecret(entity.isSecret());
-            model.setInput(entity.isInput());
-            requiredCredentialModels.add(model);
-        }
-        return requiredCredentialModels;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-
-    @Override
-    public List<String> getDefaultRoles() {
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        List<String> roles = new ArrayList<String>();
-        if (entities == null) return roles;
-        for (RoleEntity entity : entities) {
-            roles.add(entity.getName());
-        }
-        return roles;
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            role = addRole(name);
-        }
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        for (RoleEntity entity : entities) {
-            if (entity.getId().equals(role.getId())) {
-                return;
-            }
-        }
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        entities.add(roleEntity);
-        em.flush();
-    }
-
-    public static boolean contains(String str, String[] array) {
-        for (String s : array) {
-            if (str.equals(s)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        Set<String> already = new HashSet<String>();
-        List<RoleEntity> remove = new ArrayList<RoleEntity>();
-        for (RoleEntity rel : entities) {
-            if (!contains(rel.getName(), defaultRoles)) {
-                remove.add(rel);
-            } else {
-                already.add(rel.getName());
-            }
-        }
-        for (RoleEntity entity : remove) {
-            entities.remove(entity);
-        }
-        em.flush();
-        for (String roleName : defaultRoles) {
-            if (!already.contains(roleName)) {
-                addDefaultRole(roleName);
-            }
-        }
-        em.flush();
-    }
-
-    @Override
-    public Map<String, ClientModel> getClientNameMap() {
-        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
-        for (ClientModel app : getClients()) {
-            map.put(app.getClientId(), app);
-        }
-        return map;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<ClientModel> getClients() {
-        List<ClientModel> list = new ArrayList<ClientModel>();
-        if (realm.getClients() == null) return list;
-        for (ClientEntity entity : realm.getClients()) {
-            list.add(new ClientAdapter(this, em, session, entity));
-        }
-        return list;
-    }
-
-    @Override
-    public ClientModel addClient(String name) {
-        return this.addClient(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public ClientModel addClient(String id, String clientId) {
-        ClientEntity entity = new ClientEntity();
-        entity.setId(id);
-        entity.setClientId(clientId);
-        entity.setEnabled(true);
-        entity.setRealm(realm);
-        realm.getClients().add(entity);
-        em.persist(entity);
-        em.flush();
-        final ClientModel resource = new ClientAdapter(this, em, session, entity);
-        em.flush();
-        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
-            @Override
-            public ClientModel getCreatedClient() {
-                return resource;
-            }
-        });
-        return resource;
-    }
-
-    @Override
-    public boolean removeClient(String id) {
-        if (id == null) return false;
-        ClientModel client = getClientById(id);
-        if (client == null) return false;
-
-        session.users().preRemove(this, client);
-
-        for (RoleModel role : client.getRoles()) {
-            client.removeRole(role);
-        }
-
-        ClientEntity clientEntity = null;
-        Iterator<ClientEntity> it = realm.getClients().iterator();
-        while (it.hasNext()) {
-            ClientEntity ae = it.next();
-            if (ae.getId().equals(id)) {
-                clientEntity = ae;
-                it.remove();
-                break;
-            }
-        }
-        for (ClientEntity a : realm.getClients()) {
-            if (a.getId().equals(id)) {
-                clientEntity = a;
-            }
-        }
-        if (client == null) {
-            return false;
-        }
-        em.remove(clientEntity);
-        em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
-        em.flush();
-
-        return true;
-    }
-
-    @Override
-    public ClientModel getClientById(String id) {
-        return session.realms().getClientById(id, this);
-    }
-
-    @Override
-    public ClientModel getClientByClientId(String clientId) {
-        return getClientNameMap().get(clientId);
-    }
-
-    private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
-
-    @Override
-    public Map<String, String> getBrowserSecurityHeaders() {
-        Map<String, String> attributes = getAttributes();
-        Map<String, String> headers = new HashMap<String, String>();
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) {
-                headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue());
-            }
-        }
-        return headers;
-    }
-
-    @Override
-    public void setBrowserSecurityHeaders(Map<String, String> headers) {
-        for (Map.Entry<String, String> entry : headers.entrySet()) {
-            setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
-    public Map<String, String> getSmtpConfig() {
-        return realm.getSmtpConfig();
-    }
-
-    @Override
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        realm.setSmtpConfig(smtpConfig);
-        em.flush();
-    }
-
-    @Override
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
-        List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
-        for (UserFederationProviderEntity entity : entities) {
-            copy.add(entity);
-
-        }
-        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
-
-            @Override
-            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
-                return o1.getPriority() - o2.getPriority();
-            }
-
-        });
-        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
-        for (UserFederationProviderEntity entity : copy) {
-            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-        }
-
-        return result;
-    }
-
-    @Override
-    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
-        KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
-
-        String id = KeycloakModelUtils.generateId();
-        UserFederationProviderEntity entity = new UserFederationProviderEntity();
-        entity.setId(id);
-        entity.setRealm(realm);
-        entity.setProviderName(providerName);
-        entity.setConfig(config);
-        entity.setPriority(priority);
-        if (displayName == null) {
-            displayName = id;
-        }
-        entity.setDisplayName(displayName);
-        entity.setFullSyncPeriod(fullSyncPeriod);
-        entity.setChangedSyncPeriod(changedSyncPeriod);
-        entity.setLastSync(lastSync);
-        em.persist(entity);
-        realm.getUserFederationProviders().add(entity);
-        em.flush();
-        UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
-
-        session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
-
-        return providerModel;
-    }
-
-    @Override
-    public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(provider.getId())) {
-
-                session.users().preRemove(this, provider);
-                removeFederationMappersForProvider(provider.getId());
-
-                it.remove();
-                em.remove(entity);
-                return;
-            }
-        }
-    }
-
-    private void removeFederationMappersForProvider(String federationProviderId) {
-        Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
-        for (UserFederationMapperEntity mapper : mappers) {
-            realm.getUserFederationMappers().remove(mapper);
-            em.remove(mapper);
-        }
-    }
-
-    @Override
-    public void updateUserFederationProvider(UserFederationProviderModel model) {
-        KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
-
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(model.getId())) {
-                String displayName = model.getDisplayName();
-                if (displayName != null) {
-                    entity.setDisplayName(model.getDisplayName());
-                }
-                entity.setConfig(model.getConfig());
-                entity.setPriority(model.getPriority());
-                entity.setProviderName(model.getProviderName());
-                entity.setPriority(model.getPriority());
-                entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                entity.setLastSync(model.getLastSync());
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
-        for (UserFederationProviderModel currentProvider : providers) {
-            KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
-        }
-
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            boolean found = false;
-            for (UserFederationProviderModel model : providers) {
-                if (entity.getId().equals(model.getId())) {
-                    entity.setConfig(model.getConfig());
-                    entity.setPriority(model.getPriority());
-                    entity.setProviderName(model.getProviderName());
-                    String displayName = model.getDisplayName();
-                    if (displayName != null) {
-                        entity.setDisplayName(displayName);
-                    }
-                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                    entity.setLastSync(model.getLastSync());
-                    found = true;
-                    break;
-                }
-
-            }
-            if (found) continue;
-            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-            removeFederationMappersForProvider(entity.getId());
-
-            it.remove();
-            em.remove(entity);
-        }
-
-        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
-        for (UserFederationProviderModel model : providers) {
-            boolean found = false;
-            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
-                if (entity.getId().equals(model.getId())) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) add.add(model);
-        }
-
-        for (UserFederationProviderModel model : add) {
-            UserFederationProviderEntity entity = new UserFederationProviderEntity();
-            if (model.getId() != null) {
-                entity.setId(model.getId());
-            } else {
-                String id = KeycloakModelUtils.generateId();
-                entity.setId(id);
-                model.setId(id);
-            }
-            entity.setConfig(model.getConfig());
-            entity.setPriority(model.getPriority());
-            entity.setProviderName(model.getProviderName());
-            entity.setPriority(model.getPriority());
-            String displayName = model.getDisplayName();
-            if (displayName == null) {
-                displayName = entity.getId();
-            }
-            entity.setDisplayName(displayName);
-            entity.setFullSyncPeriod(model.getFullSyncPeriod());
-            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-            entity.setLastSync(model.getLastSync());
-            em.persist(entity);
-            realm.getUserFederationProviders().add(entity);
-
-            session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
-        }
-    }
-
-    protected UserFederationProviderEntity getUserFederationProviderEntityById(String federationProviderId) {
-        for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
-            if (entity.getId().equals(federationProviderId)) {
-                return entity;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public RoleModel getRole(String name) {
-        TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class);
-        query.setParameter("name", name);
-        query.setParameter("realm", realm);
-        List<RoleEntity> roles = query.getResultList();
-        if (roles.size() == 0) return null;
-        return new RoleAdapter(this, em, roles.get(0));
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        return this.addRole(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        RoleEntity entity = new RoleEntity();
-        entity.setId(id);
-        entity.setName(name);
-        entity.setRealm(realm);
-        entity.setRealmId(realm.getId());
-        realm.getRoles().add(entity);
-        em.persist(entity);
-        em.flush();
-        return new RoleAdapter(this, em, entity);
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        if (role == null) {
-            return false;
-        }
-        if (!role.getContainer().equals(this)) return false;
-        session.users().preRemove(this, role);
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        realm.getRoles().remove(roleEntity);
-        realm.getDefaultRoles().remove(roleEntity);
-
-        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
-        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
-
-        em.remove(roleEntity);
-
-        return true;
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        Set<RoleModel> list = new HashSet<RoleModel>();
-        Collection<RoleEntity> roles = realm.getRoles();
-        if (roles == null) return list;
-        for (RoleEntity entity : roles) {
-            list.add(new RoleAdapter(this, em, entity));
-        }
-        return list;
-    }
-
-    @Override
-    public RoleModel getRoleById(String id) {
-        return session.realms().getRoleById(id, this);
-    }
-
-    @Override
-    public boolean removeRoleById(String id) {
-        RoleModel role = getRoleById(id);
-        if (role == null) return false;
-        return role.getContainer().removeRole(role);
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        if (passwordPolicy == null) {
-            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
-        }
-        return passwordPolicy;
-    }
-
-    @Override
-    public void setPasswordPolicy(PasswordPolicy policy) {
-        this.passwordPolicy = policy;
-        realm.setPasswordPolicy(policy.toString());
-        em.flush();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RealmModel)) return false;
-
-        RealmModel that = (RealmModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public String getLoginTheme() {
-        return realm.getLoginTheme();
-    }
-
-    @Override
-    public void setLoginTheme(String name) {
-        realm.setLoginTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getAccountTheme() {
-        return realm.getAccountTheme();
-    }
-
-    @Override
-    public void setAccountTheme(String name) {
-        realm.setAccountTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getAdminTheme() {
-        return realm.getAdminTheme();
-    }
-
-    @Override
-    public void setAdminTheme(String name) {
-        realm.setAdminTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getEmailTheme() {
-        return realm.getEmailTheme();
-    }
-
-    @Override
-    public void setEmailTheme(String name) {
-        realm.setEmailTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public boolean isEventsEnabled() {
-        return realm.isEventsEnabled();
-    }
-
-    @Override
-    public void setEventsEnabled(boolean enabled) {
-        realm.setEventsEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public long getEventsExpiration() {
-        return realm.getEventsExpiration();
-    }
-
-    @Override
-    public void setEventsExpiration(long expiration) {
-        realm.setEventsExpiration(expiration);
-        em.flush();
-    }
-
-    @Override
-    public Set<String> getEventsListeners() {
-        return realm.getEventsListeners();
-    }
-
-    @Override
-    public void setEventsListeners(Set<String> listeners) {
-        realm.setEventsListeners(listeners);
-        em.flush();
-    }
-    
-    @Override
-    public Set<String> getEnabledEventTypes() {
-        return realm.getEnabledEventTypes();
-    }
-
-    @Override
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        realm.setEnabledEventTypes(enabledEventTypes);
-        em.flush();
-    }
-    
-    @Override
-    public boolean isAdminEventsEnabled() {
-        return realm.isAdminEventsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsEnabled(boolean enabled) {
-        realm.setAdminEventsEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public boolean isAdminEventsDetailsEnabled() {
-        return realm.isAdminEventsDetailsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsDetailsEnabled(boolean enabled) {
-        realm.setAdminEventsDetailsEnabled(enabled);
-        em.flush();
-    }
-    
-    @Override
-    public ClientModel getMasterAdminClient() {
-        return new ClientAdapter(this, em, session, realm.getMasterAdminClient());
-    }
-
-    @Override
-    public void setMasterAdminClient(ClientModel client) {
-        ClientEntity appEntity = client !=null ? em.getReference(ClientEntity.class, client.getId()) : null;
-        realm.setMasterAdminClient(appEntity);
-        em.flush();
-    }
-
-    @Override
-    public List<IdentityProviderModel> getIdentityProviders() {
-        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
-
-        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
-            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
-
-            identityProviderModel.setProviderId(entity.getProviderId());
-            identityProviderModel.setAlias(entity.getAlias());
-            identityProviderModel.setInternalId(entity.getInternalId());
-            identityProviderModel.setConfig(entity.getConfig());
-            identityProviderModel.setEnabled(entity.isEnabled());
-            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
-            identityProviderModel.setTrustEmail(entity.isTrustEmail());
-            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
-            identityProviderModel.setStoreToken(entity.isStoreToken());
-            identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
-
-            identityProviders.add(identityProviderModel);
-        }
-
-        return identityProviders;
-    }
-
-    @Override
-    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
-            if (identityProviderModel.getAlias().equals(alias)) {
-                return identityProviderModel;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void addIdentityProvider(IdentityProviderModel identityProvider) {
-        IdentityProviderEntity entity = new IdentityProviderEntity();
-
-        entity.setInternalId(KeycloakModelUtils.generateId());
-        entity.setAlias(identityProvider.getAlias());
-        entity.setProviderId(identityProvider.getProviderId());
-        entity.setEnabled(identityProvider.isEnabled());
-        entity.setStoreToken(identityProvider.isStoreToken());
-        entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
-        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
-        entity.setTrustEmail(identityProvider.isTrustEmail());
-        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-        entity.setConfig(identityProvider.getConfig());
-
-        realm.addIdentityProvider(entity);
-
-        em.persist(entity);
-        em.flush();
-    }
-
-    @Override
-    public void removeIdentityProviderByAlias(String alias) {
-        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
-            if (entity.getAlias().equals(alias)) {
-                em.remove(entity);
-                em.flush();
-            }
-        }
-    }
-
-    @Override
-    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
-        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
-            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
-                entity.setAlias(identityProvider.getAlias());
-                entity.setEnabled(identityProvider.isEnabled());
-                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
-                entity.setTrustEmail(identityProvider.isTrustEmail());
-                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-                entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
-                entity.setStoreToken(identityProvider.isStoreToken());
-                entity.setConfig(identityProvider.getConfig());
-            }
-        }
-
-        em.flush();
-    }
-
-    @Override
-    public boolean isIdentityFederationEnabled() {
-        return !this.realm.getIdentityProviders().isEmpty();
-    }
-
-    @Override
-    public boolean isInternationalizationEnabled() {
-        return realm.isInternationalizationEnabled();
-    }
-
-    @Override
-    public void setInternationalizationEnabled(boolean enabled) {
-        realm.setInternationalizationEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public Set<String> getSupportedLocales() {
-        return realm.getSupportedLocales();
-    }
-
-    @Override
-    public void setSupportedLocales(Set<String> locales) {
-        realm.setSupportedLocales(locales);
-        em.flush();
-    }
-
-    @Override
-    public String getDefaultLocale() {
-        return realm.getDefaultLocale();
-    }
-
-    @Override
-    public void setDefaultLocale(String locale) {
-        realm.setDefaultLocale(locale);
-        em.flush();
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            IdentityProviderMapperModel mapping = entityToModel(entity);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
-                continue;
-            }
-            IdentityProviderMapperModel mapping = entityToModel(entity);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
-        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
-            throw new RuntimeException("identity provider mapper name must be unique per identity provider");
-        }
-        String id = KeycloakModelUtils.generateId();
-        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
-        entity.setRealm(this.realm);
-        entity.setConfig(model.getConfig());
-
-        em.persist(entity);
-        this.realm.getIdentityProviderMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
-        if (toDelete != null) {
-            this.realm.getIdentityProviderMappers().remove(toDelete);
-            em.remove(toDelete);
-        }
-
-    }
-
-    @Override
-    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
-        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapping.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        }
-        em.flush();
-
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
-        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappers() {
-        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
-        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
-            UserFederationMapperModel mapper = entityToModel(entity);
-            mappers.add(mapper);
-        }
-        return mappers;
-    }
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
-        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
-        Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
-        for (UserFederationMapperEntity entity : mapperEntities) {
-            UserFederationMapperModel mapper = entityToModel(entity);
-            mappers.add(mapper);
-        }
-        return mappers;
-    }
-
-    @Override
-    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
-        if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
-            throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
-        }
-        String id = KeycloakModelUtils.generateId();
-        UserFederationMapperEntity entity = new UserFederationMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setFederationProvider(getUserFederationProviderEntityById(model.getFederationProviderId()));
-        entity.setFederationMapperType(model.getFederationMapperType());
-        entity.setRealm(this.realm);
-        entity.setConfig(model.getConfig());
-
-        em.persist(entity);
-        this.realm.getUserFederationMappers().add(entity);
-        UserFederationMapperModel mapperModel = entityToModel(entity);
-
-        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
-
-        return mapperModel;
-    }
-
-    @Override
-    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
-        UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
-        if (toDelete != null) {
-            this.realm.getUserFederationMappers().remove(toDelete);
-            em.remove(toDelete);
-        }
-    }
-
-    protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
-        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
-        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
-            if (federationProviderId.equals(entity.getFederationProvider().getId()) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
-        Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
-        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
-            if (federationProviderId.equals(entity.getFederationProvider().getId())) {
-                mappers.add(entity);
-            }
-        }
-        return mappers;
-    }
-
-    @Override
-    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
-        entity.setFederationProvider(getUserFederationProviderEntityById(mapper.getFederationProviderId()));
-        entity.setFederationMapperType(mapper.getFederationMapperType());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapper.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapper.getConfig());
-        }
-        em.flush();
-
-        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperById(String id) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
-        UserFederationMapperModel mapper = new UserFederationMapperModel();
-        mapper.setId(entity.getId());
-        mapper.setName(entity.getName());
-        mapper.setFederationProviderId(entity.getFederationProvider().getId());
-        mapper.setFederationMapperType(entity.getFederationMapperType());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapper.setConfig(config);
-        return mapper;
-    }
-
-    @Override
-    public List<AuthenticationFlowModel> getAuthenticationFlows() {
-        TypedQuery<AuthenticationFlowEntity> query = em.createNamedQuery("getAuthenticationFlowsByRealm", AuthenticationFlowEntity.class);
-        query.setParameter("realm", realm);
-        List<AuthenticationFlowEntity> flows = query.getResultList();
-        if (flows.size() == 0) return Collections.EMPTY_LIST;
-        List<AuthenticationFlowModel> models = new LinkedList<>();
-        for (AuthenticationFlowEntity entity : flows) {
-            AuthenticationFlowModel model = entityToModel(entity);
-            models.add(model);
-        }
-        return models;
-    }
-
-    @Override
-    public AuthenticationFlowModel getFlowByAlias(String alias) {
-        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
-            if (flow.getAlias().equals(alias)) {
-                return flow;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
-        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
-            if (config.getAlias().equals(alias)) {
-                return config;
-            }
-        }
-        return null;
-    }
-
-    protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
-        AuthenticationFlowModel model = new AuthenticationFlowModel();
-        model.setId(entity.getId());
-        model.setAlias(entity.getAlias());
-        model.setProviderId(entity.getProviderId());
-        model.setDescription(entity.getDescription());
-        model.setBuiltIn(entity.isBuiltIn());
-        model.setTopLevel(entity.isTopLevel());
-        return model;
-    }
-
-    @Override
-    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
-        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
-        if (entity == null) return;
-        em.remove(entity);
-        em.flush();
-    }
-
-    @Override
-    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
-        if (entity == null) return;
-        entity.setAlias(model.getAlias());
-        entity.setDescription(model.getDescription());
-        entity.setProviderId(model.getProviderId());
-        entity.setBuiltIn(model.isBuiltIn());
-        entity.setTopLevel(model.isTopLevel());
-
-    }
-
-    @Override
-    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        entity.setId(id);
-        entity.setAlias(model.getAlias());
-        entity.setDescription(model.getDescription());
-        entity.setProviderId(model.getProviderId());
-        entity.setBuiltIn(model.isBuiltIn());
-        entity.setTopLevel(model.isTopLevel());
-        entity.setRealm(realm);
-        realm.getAuthenticationFlows().add(entity);
-        em.persist(entity);
-        em.flush();
-        model.setId(entity.getId());
-        return model;
-    }
-
-    @Override
-    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
-        TypedQuery<AuthenticationExecutionEntity> query = em.createNamedQuery("getAuthenticationExecutionsByFlow", AuthenticationExecutionEntity.class);
-        AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
-        query.setParameter("realm", realm);
-        query.setParameter("parentFlow", flow);
-        List<AuthenticationExecutionEntity> queryResult = query.getResultList();
-        List<AuthenticationExecutionModel> executions = new LinkedList<>();
-        for (AuthenticationExecutionEntity entity : queryResult) {
-            AuthenticationExecutionModel model = entityToModel(entity);
-            executions.add(model);
-        }
-        Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
-        return executions;
-    }
-
-    public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
-        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
-        model.setId(entity.getId());
-        model.setUserSetupAllowed(entity.isUserSetupAllowed());
-        model.setRequirement(entity.getRequirement());
-        model.setPriority(entity.getPriority());
-        model.setAuthenticator(entity.getAuthenticator());
-        model.setFlowId(entity.getFlowId());
-        model.setParentFlow(entity.getParentFlow().getId());
-        model.setAutheticatorFlow(entity.isAutheticatorFlow());
-        model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
-        return model;
-    }
-
-    @Override
-    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
-        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        entity.setId(id);
-        entity.setAuthenticator(model.getAuthenticator());
-        entity.setPriority(model.getPriority());
-        entity.setFlowId(model.getFlowId());
-        entity.setRequirement(model.getRequirement());
-        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
-        AuthenticationFlowEntity flow = em.find(AuthenticationFlowEntity.class, model.getParentFlow());
-        entity.setParentFlow(flow);
-        flow.getExecutions().add(entity);
-        entity.setRealm(realm);
-        entity.setUserSetupAllowed(model.isUserSetupAllowed());
-        entity.setAutheticatorFlow(model.isAutheticatorFlow());
-        em.persist(entity);
-        em.flush();
-        model.setId(entity.getId());
-        return model;
-
-    }
-
-    @Override
-    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
-        if (entity == null) return;
-        entity.setAutheticatorFlow(model.isAutheticatorFlow());
-        entity.setAuthenticator(model.getAuthenticator());
-        entity.setPriority(model.getPriority());
-        entity.setRequirement(model.getRequirement());
-        entity.setUserSetupAllowed(model.isUserSetupAllowed());
-        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
-        entity.setFlowId(model.getFlowId());
-        em.flush();
-    }
-
-    @Override
-    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
-        if (entity == null) return;
-        em.remove(entity);
-        em.flush();
-
-    }
-
-    @Override
-    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        auth.setId(id);
-        auth.setAlias(model.getAlias());
-        auth.setRealm(realm);
-        auth.setConfig(model.getConfig());
-        realm.getAuthenticatorConfigs().add(auth);
-        em.persist(auth);
-        em.flush();
-        model.setId(auth.getId());
-        return model;
-    }
-
-    @Override
-    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId());
-        if (entity == null) return;
-        em.remove(entity);
-        em.flush();
-
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
-        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    public AuthenticatorConfigModel entityToModel(AuthenticatorConfigEntity entity) {
-        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
-        model.setId(entity.getId());
-        model.setAlias(entity.getAlias());
-        Map<String, String> config = new HashMap<>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        model.setConfig(config);
-        return model;
-    }
-
-    @Override
-    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId());
-        if (entity == null) return;
-        entity.setAlias(model.getAlias());
-        if (entity.getConfig() == null) {
-            entity.setConfig(model.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(model.getConfig());
-        }
-        em.flush();
-
-    }
-
-    @Override
-    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
-        List<AuthenticatorConfigModel> authenticators = new LinkedList<>();
-        for (AuthenticatorConfigEntity entity : realm.getAuthenticatorConfigs()) {
-            authenticators.add(entityToModel(entity));
-        }
-        return authenticators;
-    }
-
-    @Override
-    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity auth = new RequiredActionProviderEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        auth.setId(id);
-        auth.setAlias(model.getAlias());
-        auth.setName(model.getName());
-        auth.setRealm(realm);
-        auth.setProviderId(model.getProviderId());
-        auth.setConfig(model.getConfig());
-        auth.setEnabled(model.isEnabled());
-        auth.setDefaultAction(model.isDefaultAction());
-        realm.getRequiredActionProviders().add(auth);
-        em.persist(auth);
-        em.flush();
-        model.setId(auth.getId());
-        return model;
-    }
-
-    @Override
-    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId());
-        if (entity == null) return;
-        em.remove(entity);
-        em.flush();
-
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
-        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    public RequiredActionProviderModel entityToModel(RequiredActionProviderEntity entity) {
-        RequiredActionProviderModel model = new RequiredActionProviderModel();
-        model.setId(entity.getId());
-        model.setProviderId(entity.getProviderId());
-        model.setAlias(entity.getAlias());
-        model.setEnabled(entity.isEnabled());
-        model.setDefaultAction(entity.isDefaultAction());
-        model.setName(entity.getName());
-        Map<String, String> config = new HashMap<>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        model.setConfig(config);
-        return model;
-    }
-
-    @Override
-    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId());
-        if (entity == null) return;
-        entity.setAlias(model.getAlias());
-        entity.setProviderId(model.getProviderId());
-        entity.setEnabled(model.isEnabled());
-        entity.setDefaultAction(model.isDefaultAction());
-        entity.setName(model.getName());
-        if (entity.getConfig() == null) {
-            entity.setConfig(model.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(model.getConfig());
-        }
-        em.flush();
-
-    }
-
-    @Override
-    public List<RequiredActionProviderModel> getRequiredActionProviders() {
-        List<RequiredActionProviderModel> actions = new LinkedList<>();
-        for (RequiredActionProviderEntity entity : realm.getRequiredActionProviders()) {
-            actions.add(entityToModel(entity));
-        }
-        return actions;
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
-        for (RequiredActionProviderModel action : getRequiredActionProviders()) {
-            if (action.getAlias().equals(alias)) return action;
-        }
-        return null;
-    }
+package org.keycloak.models.jpa;
+
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperEventImpl;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderCreationEventImpl;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.jpa.entities.AuthenticationExecutionEntity;
+import org.keycloak.models.jpa.entities.AuthenticationFlowEntity;
+import org.keycloak.models.jpa.entities.AuthenticatorConfigEntity;
+import org.keycloak.models.jpa.entities.ClientEntity;
+import org.keycloak.models.jpa.entities.IdentityProviderEntity;
+import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
+import org.keycloak.models.jpa.entities.RealmAttributeEntity;
+import org.keycloak.models.jpa.entities.RealmEntity;
+import org.keycloak.models.jpa.entities.RequiredActionProviderEntity;
+import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.jpa.entities.UserFederationMapperEntity;
+import org.keycloak.models.jpa.entities.UserFederationProviderEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmAdapter implements RealmModel {
+    protected RealmEntity realm;
+    protected EntityManager em;
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+    protected volatile transient X509Certificate certificate;
+    protected volatile transient Key codeSecretKey;
+    protected KeycloakSession session;
+    private PasswordPolicy passwordPolicy;
+
+    public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) {
+        this.session = session;
+        this.em = em;
+        this.realm = realm;
+    }
+
+    public RealmEntity getEntity() {
+        return realm;
+    }
+
+    @Override
+    public String getId() {
+        return realm.getId();
+    }
+
+    @Override
+    public String getName() {
+        return realm.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        realm.setName(name);
+        em.flush();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return realm.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        realm.setEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public SslRequired getSslRequired() {
+        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
+    }
+
+    @Override
+    public void setSslRequired(SslRequired sslRequired) {
+        realm.setSslRequired(sslRequired.name());
+        em.flush();
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        realm.setRegistrationAllowed(registrationAllowed);
+        em.flush();
+    }
+
+    @Override
+    public boolean isRegistrationEmailAsUsername() {
+        return realm.isRegistrationEmailAsUsername();
+    }
+
+    @Override
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
+        em.flush();
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+        em.flush();
+    }
+
+    public void setAttribute(String name, String value) {
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                attr.setValue(value);
+                return;
+            }
+        }
+        RealmAttributeEntity attr = new RealmAttributeEntity();
+        attr.setName(name);
+        attr.setValue(value);
+        attr.setRealm(realm);
+        em.persist(attr);
+        realm.getAttributes().add(attr);
+    }
+
+    public void setAttribute(String name, Boolean value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void setAttribute(String name, Integer value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void setAttribute(String name, Long value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void removeAttribute(String name) {
+        Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator();
+        while (it.hasNext()) {
+            RealmAttributeEntity attr = it.next();
+            if (attr.getName().equals(name)) {
+                it.remove();
+                em.remove(attr);
+            }
+        }
+    }
+
+    public String getAttribute(String name) {
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                return attr.getValue();
+            }
+        }
+        return null;
+    }
+
+    public Integer getAttribute(String name, Integer defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Integer.parseInt(v) : defaultValue;
+
+    }
+
+    public Long getAttribute(String name, Long defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Long.parseLong(v) : defaultValue;
+
+    }
+
+    public Boolean getAttribute(String name, Boolean defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Boolean.parseBoolean(v) : defaultValue;
+
+    }
+
+    public Map<String, String> getAttributes() {
+        // should always return a copy
+        Map<String, String> result = new HashMap<String, String>();
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            result.put(attr.getName(), attr.getValue());
+        }
+        return result;
+    }
+    @Override
+    public boolean isBruteForceProtected() {
+        return getAttribute("bruteForceProtected", false);
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        setAttribute("bruteForceProtected", value);
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        return getAttribute("maxFailureWaitSeconds", 0);
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        setAttribute("maxFailureWaitSeconds", val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return getAttribute("waitIncrementSeconds", 0);
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        setAttribute("waitIncrementSeconds", val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return getAttribute("quickLoginCheckMilliSeconds", 0l);
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        setAttribute("quickLoginCheckMilliSeconds", val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return getAttribute("minimumQuickLoginWaitSeconds", 0);
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        setAttribute("minimumQuickLoginWaitSeconds", val);
+    }
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return getAttribute("maxDeltaTimeSeconds", 0);
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        setAttribute("maxDeltaTimeSeconds", val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return getAttribute("failureFactor", 0);
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        setAttribute("failureFactor", failureFactor);
+    }
+
+    @Override
+    public boolean isVerifyEmail() {
+        return realm.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        realm.setVerifyEmail(verifyEmail);
+        em.flush();
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        return realm.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
+        realm.setResetPasswordAllowed(resetPasswordAllowed);
+        em.flush();
+    }
+
+    @Override
+    public boolean isEditUsernameAllowed() {
+        return realm.isEditUsernameAllowed();
+    }
+
+    @Override
+    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+        realm.setEditUsernameAllowed(editUsernameAllowed);
+        em.flush();
+    }
+
+    @Override
+    public int getNotBefore() {
+        return realm.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        realm.setNotBefore(notBefore);
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+        em.flush();
+    }
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        return realm.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        realm.setSsoSessionIdleTimeout(seconds);
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        return realm.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        realm.setSsoSessionMaxLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        return realm.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        realm.setAccessCodeLifespan(accessCodeLifespan);
+        em.flush();
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        return realm.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
+        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
+        em.flush();
+    }
+
+    @Override
+    public int getAccessCodeLifespanLogin() {
+        return realm.getAccessCodeLifespanLogin();
+    }
+
+    @Override
+    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
+        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
+        em.flush();
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        return realm.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        realm.setPublicKeyPem(publicKeyPem);
+        em.flush();
+    }
+
+    @Override
+    public X509Certificate getCertificate() {
+        if (certificate != null) return certificate;
+        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
+        return certificate;
+    }
+
+    @Override
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
+        setCertificatePem(certificatePem);
+
+    }
+
+    @Override
+    public String getCertificatePem() {
+        return realm.getCertificatePem();
+    }
+
+    @Override
+    public void setCertificatePem(String certificate) {
+        realm.setCertificatePem(certificate);
+
+    }
+
+    @Override
+    public String getPrivateKeyPem() {
+        return realm.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        realm.setPrivateKeyPem(privateKeyPem);
+        em.flush();
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public String getCodeSecret() {
+        return realm.getCodeSecret();
+    }
+
+    @Override
+    public Key getCodeSecretKey() {
+        if (codeSecretKey == null) {
+            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
+        }
+        return codeSecretKey;
+    }
+
+    @Override
+    public void setCodeSecret(String codeSecret) {
+        realm.setCodeSecret(codeSecret);
+    }
+
+    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
+        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
+        if (model == null) {
+            throw new RuntimeException("Unknown credential type " + type);
+        }
+        return model;
+    }
+
+    @Override
+    public void addRequiredCredential(String type) {
+        RequiredCredentialModel model = initRequiredCredentialModel(type);
+        addRequiredCredential(model);
+        em.flush();
+    }
+
+    public void addRequiredCredential(RequiredCredentialModel model) {
+        RequiredCredentialEntity entity = new RequiredCredentialEntity();
+        entity.setRealm(realm);
+        entity.setInput(model.isInput());
+        entity.setSecret(model.isSecret());
+        entity.setType(model.getType());
+        entity.setFormLabel(model.getFormLabel());
+        em.persist(entity);
+        realm.getRequiredCredentials().add(entity);
+        em.flush();
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
+        if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
+
+        Set<String> already = new HashSet<String>();
+        List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
+        for (RequiredCredentialEntity rel : relationships) {
+            if (!creds.contains(rel.getType())) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getType());
+            }
+        }
+        for (RequiredCredentialEntity entity : remove) {
+            relationships.remove(entity);
+            em.remove(entity);
+        }
+        for (String cred : creds) {
+            if (!already.contains(cred)) {
+                addRequiredCredential(cred);
+            }
+        }
+        em.flush();
+    }
+
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
+        Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
+        if (entities == null) return requiredCredentialModels;
+        for (RequiredCredentialEntity entity : entities) {
+            RequiredCredentialModel model = new RequiredCredentialModel();
+            model.setFormLabel(entity.getFormLabel());
+            model.setType(entity.getType());
+            model.setSecret(entity.isSecret());
+            model.setInput(entity.isInput());
+            requiredCredentialModels.add(model);
+        }
+        return requiredCredentialModels;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+
+    @Override
+    public List<String> getDefaultRoles() {
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        List<String> roles = new ArrayList<String>();
+        if (entities == null) return roles;
+        for (RoleEntity entity : entities) {
+            roles.add(entity.getName());
+        }
+        return roles;
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            role = addRole(name);
+        }
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        for (RoleEntity entity : entities) {
+            if (entity.getId().equals(role.getId())) {
+                return;
+            }
+        }
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        entities.add(roleEntity);
+        em.flush();
+    }
+
+    public static boolean contains(String str, String[] array) {
+        for (String s : array) {
+            if (str.equals(s)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        Set<String> already = new HashSet<String>();
+        List<RoleEntity> remove = new ArrayList<RoleEntity>();
+        for (RoleEntity rel : entities) {
+            if (!contains(rel.getName(), defaultRoles)) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getName());
+            }
+        }
+        for (RoleEntity entity : remove) {
+            entities.remove(entity);
+        }
+        em.flush();
+        for (String roleName : defaultRoles) {
+            if (!already.contains(roleName)) {
+                addDefaultRole(roleName);
+            }
+        }
+        em.flush();
+    }
+
+    @Override
+    public Map<String, ClientModel> getClientNameMap() {
+        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
+        for (ClientModel app : getClients()) {
+            map.put(app.getClientId(), app);
+        }
+        return map;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<ClientModel> getClients() {
+        List<ClientModel> list = new ArrayList<ClientModel>();
+        if (realm.getClients() == null) return list;
+        for (ClientEntity entity : realm.getClients()) {
+            list.add(new ClientAdapter(this, em, session, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public ClientModel addClient(String name) {
+        return this.addClient(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public ClientModel addClient(String id, String clientId) {
+        ClientEntity entity = new ClientEntity();
+        entity.setId(id);
+        entity.setClientId(clientId);
+        entity.setEnabled(true);
+        entity.setRealm(realm);
+        realm.getClients().add(entity);
+        em.persist(entity);
+        em.flush();
+        final ClientModel resource = new ClientAdapter(this, em, session, entity);
+        em.flush();
+        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
+            @Override
+            public ClientModel getCreatedClient() {
+                return resource;
+            }
+        });
+        return resource;
+    }
+
+    @Override
+    public boolean removeClient(String id) {
+        if (id == null) return false;
+        ClientModel client = getClientById(id);
+        if (client == null) return false;
+
+        session.users().preRemove(this, client);
+
+        for (RoleModel role : client.getRoles()) {
+            client.removeRole(role);
+        }
+
+        ClientEntity clientEntity = null;
+        Iterator<ClientEntity> it = realm.getClients().iterator();
+        while (it.hasNext()) {
+            ClientEntity ae = it.next();
+            if (ae.getId().equals(id)) {
+                clientEntity = ae;
+                it.remove();
+                break;
+            }
+        }
+        for (ClientEntity a : realm.getClients()) {
+            if (a.getId().equals(id)) {
+                clientEntity = a;
+            }
+        }
+        if (client == null) {
+            return false;
+        }
+        em.remove(clientEntity);
+        em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
+        em.flush();
+
+        return true;
+    }
+
+    @Override
+    public ClientModel getClientById(String id) {
+        return session.realms().getClientById(id, this);
+    }
+
+    @Override
+    public ClientModel getClientByClientId(String clientId) {
+        return getClientNameMap().get(clientId);
+    }
+
+    private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
+
+    @Override
+    public Map<String, String> getBrowserSecurityHeaders() {
+        Map<String, String> attributes = getAttributes();
+        Map<String, String> headers = new HashMap<String, String>();
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) {
+                headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue());
+            }
+        }
+        return headers;
+    }
+
+    @Override
+    public void setBrowserSecurityHeaders(Map<String, String> headers) {
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        return realm.getSmtpConfig();
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        realm.setSmtpConfig(smtpConfig);
+        em.flush();
+    }
+
+    @Override
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
+        List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
+        for (UserFederationProviderEntity entity : entities) {
+            copy.add(entity);
+
+        }
+        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
+
+            @Override
+            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
+                return o1.getPriority() - o2.getPriority();
+            }
+
+        });
+        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
+        for (UserFederationProviderEntity entity : copy) {
+            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+        }
+
+        return result;
+    }
+
+    @Override
+    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
+        KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
+
+        String id = KeycloakModelUtils.generateId();
+        UserFederationProviderEntity entity = new UserFederationProviderEntity();
+        entity.setId(id);
+        entity.setRealm(realm);
+        entity.setProviderName(providerName);
+        entity.setConfig(config);
+        entity.setPriority(priority);
+        if (displayName == null) {
+            displayName = id;
+        }
+        entity.setDisplayName(displayName);
+        entity.setFullSyncPeriod(fullSyncPeriod);
+        entity.setChangedSyncPeriod(changedSyncPeriod);
+        entity.setLastSync(lastSync);
+        em.persist(entity);
+        realm.getUserFederationProviders().add(entity);
+        em.flush();
+        UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+
+        session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
+
+        return providerModel;
+    }
+
+    @Override
+    public void removeUserFederationProvider(UserFederationProviderModel provider) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(provider.getId())) {
+
+                session.users().preRemove(this, provider);
+                removeFederationMappersForProvider(provider.getId());
+
+                it.remove();
+                em.remove(entity);
+                return;
+            }
+        }
+    }
+
+    private void removeFederationMappersForProvider(String federationProviderId) {
+        Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+        for (UserFederationMapperEntity mapper : mappers) {
+            realm.getUserFederationMappers().remove(mapper);
+            em.remove(mapper);
+        }
+    }
+
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
+
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                String displayName = model.getDisplayName();
+                if (displayName != null) {
+                    entity.setDisplayName(model.getDisplayName());
+                }
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+                entity.setProviderName(model.getProviderName());
+                entity.setPriority(model.getPriority());
+                entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                entity.setLastSync(model.getLastSync());
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
+        for (UserFederationProviderModel currentProvider : providers) {
+            KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
+        }
+
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            boolean found = false;
+            for (UserFederationProviderModel model : providers) {
+                if (entity.getId().equals(model.getId())) {
+                    entity.setConfig(model.getConfig());
+                    entity.setPriority(model.getPriority());
+                    entity.setProviderName(model.getProviderName());
+                    String displayName = model.getDisplayName();
+                    if (displayName != null) {
+                        entity.setDisplayName(displayName);
+                    }
+                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                    entity.setLastSync(model.getLastSync());
+                    found = true;
+                    break;
+                }
+
+            }
+            if (found) continue;
+            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+            removeFederationMappersForProvider(entity.getId());
+
+            it.remove();
+            em.remove(entity);
+        }
+
+        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
+        for (UserFederationProviderModel model : providers) {
+            boolean found = false;
+            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
+                if (entity.getId().equals(model.getId())) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) add.add(model);
+        }
+
+        for (UserFederationProviderModel model : add) {
+            UserFederationProviderEntity entity = new UserFederationProviderEntity();
+            if (model.getId() != null) {
+                entity.setId(model.getId());
+            } else {
+                String id = KeycloakModelUtils.generateId();
+                entity.setId(id);
+                model.setId(id);
+            }
+            entity.setConfig(model.getConfig());
+            entity.setPriority(model.getPriority());
+            entity.setProviderName(model.getProviderName());
+            entity.setPriority(model.getPriority());
+            String displayName = model.getDisplayName();
+            if (displayName == null) {
+                displayName = entity.getId();
+            }
+            entity.setDisplayName(displayName);
+            entity.setFullSyncPeriod(model.getFullSyncPeriod());
+            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+            entity.setLastSync(model.getLastSync());
+            em.persist(entity);
+            realm.getUserFederationProviders().add(entity);
+
+            session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
+        }
+    }
+
+    protected UserFederationProviderEntity getUserFederationProviderEntityById(String federationProviderId) {
+        for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
+            if (entity.getId().equals(federationProviderId)) {
+                return entity;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("realm", realm);
+        List<RoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(this, em, roles.get(0));
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        RoleEntity entity = new RoleEntity();
+        entity.setId(id);
+        entity.setName(name);
+        entity.setRealm(realm);
+        entity.setRealmId(realm.getId());
+        realm.getRoles().add(entity);
+        em.persist(entity);
+        em.flush();
+        return new RoleAdapter(this, em, entity);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        if (role == null) {
+            return false;
+        }
+        if (!role.getContainer().equals(this)) return false;
+        session.users().preRemove(this, role);
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        realm.getRoles().remove(roleEntity);
+        realm.getDefaultRoles().remove(roleEntity);
+
+        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
+        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
+
+        em.remove(roleEntity);
+
+        return true;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        Set<RoleModel> list = new HashSet<RoleModel>();
+        Collection<RoleEntity> roles = realm.getRoles();
+        if (roles == null) return list;
+        for (RoleEntity entity : roles) {
+            list.add(new RoleAdapter(this, em, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        return session.realms().getRoleById(id, this);
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        RoleModel role = getRoleById(id);
+        if (role == null) return false;
+        return role.getContainer().removeRole(role);
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (passwordPolicy == null) {
+            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
+        }
+        return passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        this.passwordPolicy = policy;
+        realm.setPasswordPolicy(policy.toString());
+        em.flush();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public String getLoginTheme() {
+        return realm.getLoginTheme();
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        realm.setLoginTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getAccountTheme() {
+        return realm.getAccountTheme();
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        realm.setAccountTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getAdminTheme() {
+        return realm.getAdminTheme();
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        realm.setAdminTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public boolean isEventsEnabled() {
+        return realm.isEventsEnabled();
+    }
+
+    @Override
+    public void setEventsEnabled(boolean enabled) {
+        realm.setEventsEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public long getEventsExpiration() {
+        return realm.getEventsExpiration();
+    }
+
+    @Override
+    public void setEventsExpiration(long expiration) {
+        realm.setEventsExpiration(expiration);
+        em.flush();
+    }
+
+    @Override
+    public Set<String> getEventsListeners() {
+        return realm.getEventsListeners();
+    }
+
+    @Override
+    public void setEventsListeners(Set<String> listeners) {
+        realm.setEventsListeners(listeners);
+        em.flush();
+    }
+    
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return realm.getEnabledEventTypes();
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        realm.setEnabledEventTypes(enabledEventTypes);
+        em.flush();
+    }
+    
+    @Override
+    public boolean isAdminEventsEnabled() {
+        return realm.isAdminEventsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsEnabled(boolean enabled) {
+        realm.setAdminEventsEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public boolean isAdminEventsDetailsEnabled() {
+        return realm.isAdminEventsDetailsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsDetailsEnabled(boolean enabled) {
+        realm.setAdminEventsDetailsEnabled(enabled);
+        em.flush();
+    }
+    
+    @Override
+    public ClientModel getMasterAdminClient() {
+        return new ClientAdapter(this, em, session, realm.getMasterAdminClient());
+    }
+
+    @Override
+    public void setMasterAdminClient(ClientModel client) {
+        ClientEntity appEntity = client !=null ? em.getReference(ClientEntity.class, client.getId()) : null;
+        realm.setMasterAdminClient(appEntity);
+        em.flush();
+    }
+
+    @Override
+    public List<IdentityProviderModel> getIdentityProviders() {
+        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
+
+        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
+            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
+
+            identityProviderModel.setProviderId(entity.getProviderId());
+            identityProviderModel.setAlias(entity.getAlias());
+            identityProviderModel.setInternalId(entity.getInternalId());
+            identityProviderModel.setConfig(entity.getConfig());
+            identityProviderModel.setEnabled(entity.isEnabled());
+            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
+            identityProviderModel.setTrustEmail(entity.isTrustEmail());
+            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
+            identityProviderModel.setStoreToken(entity.isStoreToken());
+            identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
+
+            identityProviders.add(identityProviderModel);
+        }
+
+        return identityProviders;
+    }
+
+    @Override
+    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
+            if (identityProviderModel.getAlias().equals(alias)) {
+                return identityProviderModel;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void addIdentityProvider(IdentityProviderModel identityProvider) {
+        IdentityProviderEntity entity = new IdentityProviderEntity();
+
+        entity.setInternalId(KeycloakModelUtils.generateId());
+        entity.setAlias(identityProvider.getAlias());
+        entity.setProviderId(identityProvider.getProviderId());
+        entity.setEnabled(identityProvider.isEnabled());
+        entity.setStoreToken(identityProvider.isStoreToken());
+        entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
+        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+        entity.setTrustEmail(identityProvider.isTrustEmail());
+        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+        entity.setConfig(identityProvider.getConfig());
+
+        realm.addIdentityProvider(entity);
+
+        em.persist(entity);
+        em.flush();
+    }
+
+    @Override
+    public void removeIdentityProviderByAlias(String alias) {
+        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
+            if (entity.getAlias().equals(alias)) {
+                em.remove(entity);
+                em.flush();
+            }
+        }
+    }
+
+    @Override
+    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
+        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
+            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
+                entity.setAlias(identityProvider.getAlias());
+                entity.setEnabled(identityProvider.isEnabled());
+                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+                entity.setTrustEmail(identityProvider.isTrustEmail());
+                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+                entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
+                entity.setStoreToken(identityProvider.isStoreToken());
+                entity.setConfig(identityProvider.getConfig());
+            }
+        }
+
+        em.flush();
+    }
+
+    @Override
+    public boolean isIdentityFederationEnabled() {
+        return !this.realm.getIdentityProviders().isEmpty();
+    }
+
+    @Override
+    public boolean isInternationalizationEnabled() {
+        return realm.isInternationalizationEnabled();
+    }
+
+    @Override
+    public void setInternationalizationEnabled(boolean enabled) {
+        realm.setInternationalizationEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public Set<String> getSupportedLocales() {
+        return realm.getSupportedLocales();
+    }
+
+    @Override
+    public void setSupportedLocales(Set<String> locales) {
+        realm.setSupportedLocales(locales);
+        em.flush();
+    }
+
+    @Override
+    public String getDefaultLocale() {
+        return realm.getDefaultLocale();
+    }
+
+    @Override
+    public void setDefaultLocale(String locale) {
+        realm.setDefaultLocale(locale);
+        em.flush();
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            IdentityProviderMapperModel mapping = entityToModel(entity);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
+                continue;
+            }
+            IdentityProviderMapperModel mapping = entityToModel(entity);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
+        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
+            throw new RuntimeException("identity provider mapper name must be unique per identity provider");
+        }
+        String id = KeycloakModelUtils.generateId();
+        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
+        entity.setRealm(this.realm);
+        entity.setConfig(model.getConfig());
+
+        em.persist(entity);
+        this.realm.getIdentityProviderMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
+        if (toDelete != null) {
+            this.realm.getIdentityProviderMappers().remove(toDelete);
+            em.remove(toDelete);
+        }
+
+    }
+
+    @Override
+    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
+        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapping.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        }
+        em.flush();
+
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
+        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappers() {
+        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
+        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
+            UserFederationMapperModel mapper = entityToModel(entity);
+            mappers.add(mapper);
+        }
+        return mappers;
+    }
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
+        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
+        Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+        for (UserFederationMapperEntity entity : mapperEntities) {
+            UserFederationMapperModel mapper = entityToModel(entity);
+            mappers.add(mapper);
+        }
+        return mappers;
+    }
+
+    @Override
+    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
+        if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
+            throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
+        }
+        String id = KeycloakModelUtils.generateId();
+        UserFederationMapperEntity entity = new UserFederationMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setFederationProvider(getUserFederationProviderEntityById(model.getFederationProviderId()));
+        entity.setFederationMapperType(model.getFederationMapperType());
+        entity.setRealm(this.realm);
+        entity.setConfig(model.getConfig());
+
+        em.persist(entity);
+        this.realm.getUserFederationMappers().add(entity);
+        UserFederationMapperModel mapperModel = entityToModel(entity);
+
+        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
+
+        return mapperModel;
+    }
+
+    @Override
+    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
+        UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
+        if (toDelete != null) {
+            this.realm.getUserFederationMappers().remove(toDelete);
+            em.remove(toDelete);
+        }
+    }
+
+    protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
+        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
+        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
+            if (federationProviderId.equals(entity.getFederationProvider().getId()) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
+        Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
+        for (UserFederationMapperEntity entity : this.realm.getUserFederationMappers()) {
+            if (federationProviderId.equals(entity.getFederationProvider().getId())) {
+                mappers.add(entity);
+            }
+        }
+        return mappers;
+    }
+
+    @Override
+    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
+        entity.setFederationProvider(getUserFederationProviderEntityById(mapper.getFederationProviderId()));
+        entity.setFederationMapperType(mapper.getFederationMapperType());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapper.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapper.getConfig());
+        }
+        em.flush();
+
+        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperById(String id) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
+        UserFederationMapperModel mapper = new UserFederationMapperModel();
+        mapper.setId(entity.getId());
+        mapper.setName(entity.getName());
+        mapper.setFederationProviderId(entity.getFederationProvider().getId());
+        mapper.setFederationMapperType(entity.getFederationMapperType());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapper.setConfig(config);
+        return mapper;
+    }
+
+    @Override
+    public List<AuthenticationFlowModel> getAuthenticationFlows() {
+        TypedQuery<AuthenticationFlowEntity> query = em.createNamedQuery("getAuthenticationFlowsByRealm", AuthenticationFlowEntity.class);
+        query.setParameter("realm", realm);
+        List<AuthenticationFlowEntity> flows = query.getResultList();
+        if (flows.size() == 0) return Collections.EMPTY_LIST;
+        List<AuthenticationFlowModel> models = new LinkedList<>();
+        for (AuthenticationFlowEntity entity : flows) {
+            AuthenticationFlowModel model = entityToModel(entity);
+            models.add(model);
+        }
+        return models;
+    }
+
+    @Override
+    public AuthenticationFlowModel getFlowByAlias(String alias) {
+        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
+            if (flow.getAlias().equals(alias)) {
+                return flow;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
+        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
+            if (config.getAlias().equals(alias)) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+    protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
+        AuthenticationFlowModel model = new AuthenticationFlowModel();
+        model.setId(entity.getId());
+        model.setAlias(entity.getAlias());
+        model.setProviderId(entity.getProviderId());
+        model.setDescription(entity.getDescription());
+        model.setBuiltIn(entity.isBuiltIn());
+        model.setTopLevel(entity.isTopLevel());
+        return model;
+    }
+
+    @Override
+    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
+        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
+        if (entity == null) return;
+        em.remove(entity);
+        em.flush();
+    }
+
+    @Override
+    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
+        if (entity == null) return;
+        entity.setAlias(model.getAlias());
+        entity.setDescription(model.getDescription());
+        entity.setProviderId(model.getProviderId());
+        entity.setBuiltIn(model.isBuiltIn());
+        entity.setTopLevel(model.isTopLevel());
+
+    }
+
+    @Override
+    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        entity.setId(id);
+        entity.setAlias(model.getAlias());
+        entity.setDescription(model.getDescription());
+        entity.setProviderId(model.getProviderId());
+        entity.setBuiltIn(model.isBuiltIn());
+        entity.setTopLevel(model.isTopLevel());
+        entity.setRealm(realm);
+        realm.getAuthenticationFlows().add(entity);
+        em.persist(entity);
+        em.flush();
+        model.setId(entity.getId());
+        return model;
+    }
+
+    @Override
+    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
+        TypedQuery<AuthenticationExecutionEntity> query = em.createNamedQuery("getAuthenticationExecutionsByFlow", AuthenticationExecutionEntity.class);
+        AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
+        query.setParameter("realm", realm);
+        query.setParameter("parentFlow", flow);
+        List<AuthenticationExecutionEntity> queryResult = query.getResultList();
+        List<AuthenticationExecutionModel> executions = new LinkedList<>();
+        for (AuthenticationExecutionEntity entity : queryResult) {
+            AuthenticationExecutionModel model = entityToModel(entity);
+            executions.add(model);
+        }
+        Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
+        return executions;
+    }
+
+    public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
+        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
+        model.setId(entity.getId());
+        model.setUserSetupAllowed(entity.isUserSetupAllowed());
+        model.setRequirement(entity.getRequirement());
+        model.setPriority(entity.getPriority());
+        model.setAuthenticator(entity.getAuthenticator());
+        model.setFlowId(entity.getFlowId());
+        model.setParentFlow(entity.getParentFlow().getId());
+        model.setAutheticatorFlow(entity.isAutheticatorFlow());
+        model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
+        return model;
+    }
+
+    @Override
+    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
+        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        entity.setId(id);
+        entity.setAuthenticator(model.getAuthenticator());
+        entity.setPriority(model.getPriority());
+        entity.setFlowId(model.getFlowId());
+        entity.setRequirement(model.getRequirement());
+        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
+        AuthenticationFlowEntity flow = em.find(AuthenticationFlowEntity.class, model.getParentFlow());
+        entity.setParentFlow(flow);
+        flow.getExecutions().add(entity);
+        entity.setRealm(realm);
+        entity.setUserSetupAllowed(model.isUserSetupAllowed());
+        entity.setAutheticatorFlow(model.isAutheticatorFlow());
+        em.persist(entity);
+        em.flush();
+        model.setId(entity.getId());
+        return model;
+
+    }
+
+    @Override
+    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
+        if (entity == null) return;
+        entity.setAutheticatorFlow(model.isAutheticatorFlow());
+        entity.setAuthenticator(model.getAuthenticator());
+        entity.setPriority(model.getPriority());
+        entity.setRequirement(model.getRequirement());
+        entity.setUserSetupAllowed(model.isUserSetupAllowed());
+        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
+        entity.setFlowId(model.getFlowId());
+        em.flush();
+    }
+
+    @Override
+    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
+        if (entity == null) return;
+        em.remove(entity);
+        em.flush();
+
+    }
+
+    @Override
+    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        auth.setId(id);
+        auth.setAlias(model.getAlias());
+        auth.setRealm(realm);
+        auth.setConfig(model.getConfig());
+        realm.getAuthenticatorConfigs().add(auth);
+        em.persist(auth);
+        em.flush();
+        model.setId(auth.getId());
+        return model;
+    }
+
+    @Override
+    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId());
+        if (entity == null) return;
+        em.remove(entity);
+        em.flush();
+
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
+        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    public AuthenticatorConfigModel entityToModel(AuthenticatorConfigEntity entity) {
+        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
+        model.setId(entity.getId());
+        model.setAlias(entity.getAlias());
+        Map<String, String> config = new HashMap<>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        model.setConfig(config);
+        return model;
+    }
+
+    @Override
+    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId());
+        if (entity == null) return;
+        entity.setAlias(model.getAlias());
+        if (entity.getConfig() == null) {
+            entity.setConfig(model.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(model.getConfig());
+        }
+        em.flush();
+
+    }
+
+    @Override
+    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
+        List<AuthenticatorConfigModel> authenticators = new LinkedList<>();
+        for (AuthenticatorConfigEntity entity : realm.getAuthenticatorConfigs()) {
+            authenticators.add(entityToModel(entity));
+        }
+        return authenticators;
+    }
+
+    @Override
+    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity auth = new RequiredActionProviderEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        auth.setId(id);
+        auth.setAlias(model.getAlias());
+        auth.setName(model.getName());
+        auth.setRealm(realm);
+        auth.setProviderId(model.getProviderId());
+        auth.setConfig(model.getConfig());
+        auth.setEnabled(model.isEnabled());
+        auth.setDefaultAction(model.isDefaultAction());
+        realm.getRequiredActionProviders().add(auth);
+        em.persist(auth);
+        em.flush();
+        model.setId(auth.getId());
+        return model;
+    }
+
+    @Override
+    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId());
+        if (entity == null) return;
+        em.remove(entity);
+        em.flush();
+
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
+        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    public RequiredActionProviderModel entityToModel(RequiredActionProviderEntity entity) {
+        RequiredActionProviderModel model = new RequiredActionProviderModel();
+        model.setId(entity.getId());
+        model.setProviderId(entity.getProviderId());
+        model.setAlias(entity.getAlias());
+        model.setEnabled(entity.isEnabled());
+        model.setDefaultAction(entity.isDefaultAction());
+        model.setName(entity.getName());
+        Map<String, String> config = new HashMap<>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        model.setConfig(config);
+        return model;
+    }
+
+    @Override
+    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId());
+        if (entity == null) return;
+        entity.setAlias(model.getAlias());
+        entity.setProviderId(model.getProviderId());
+        entity.setEnabled(model.isEnabled());
+        entity.setDefaultAction(model.isDefaultAction());
+        entity.setName(model.getName());
+        if (entity.getConfig() == null) {
+            entity.setConfig(model.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(model.getConfig());
+        }
+        em.flush();
+
+    }
+
+    @Override
+    public List<RequiredActionProviderModel> getRequiredActionProviders() {
+        List<RequiredActionProviderModel> actions = new LinkedList<>();
+        for (RequiredActionProviderEntity entity : realm.getRequiredActionProviders()) {
+            actions.add(entityToModel(entity));
+        }
+        return actions;
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
+        for (RequiredActionProviderModel action : getRequiredActionProviders()) {
+            if (action.getAlias().equals(alias)) return action;
+        }
+        return null;
+    }
 }
\ No newline at end of file
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index 4a8e258..4ab8d33 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -1,135 +1,135 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.jpa.entities.RoleEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleAdapter implements RoleModel {
-    protected RoleEntity role;
-    protected EntityManager em;
-    protected RealmModel realm;
-
-    public RoleAdapter(RealmModel realm, EntityManager em, RoleEntity role) {
-        this.em = em;
-        this.realm = realm;
-        this.role = role;
-    }
-
-    public RoleEntity getRole() {
-        return role;
-    }
-
-    public void setRole(RoleEntity role) {
-        this.role = role;
-    }
-
-    @Override
-    public String getName() {
-        return role.getName();
-    }
-
-    @Override
-    public String getDescription() {
-        return role.getDescription();
-    }
-
-    @Override
-    public void setDescription(String description) {
-        role.setDescription(description);
-    }
-
-    @Override
-    public String getId() {
-        return role.getId();
-    }
-
-    @Override
-    public void setName(String name) {
-        role.setName(name);
-    }
-
-    @Override
-    public boolean isComposite() {
-        return getComposites().size() > 0;
-    }
-
-    @Override
-    public void addCompositeRole(RoleModel role) {
-        RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
-        for (RoleEntity composite : getRole().getCompositeRoles()) {
-            if (composite.equals(entity)) return;
-        }
-        getRole().getCompositeRoles().add(entity);
-        em.flush();
-    }
-
-    @Override
-    public void removeCompositeRole(RoleModel role) {
-        RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
-        Iterator<RoleEntity> it = getRole().getCompositeRoles().iterator();
-        while (it.hasNext()) {
-            if (it.next().equals(entity)) it.remove();
-        }
-    }
-
-    @Override
-    public Set<RoleModel> getComposites() {
-        Set<RoleModel> set = new HashSet<RoleModel>();
-
-        for (RoleEntity composite : getRole().getCompositeRoles()) {
-           set.add(new RoleAdapter(realm, em, composite));
-        }
-        return set;
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        if (this.equals(role)) return true;
-        if (!isComposite()) return false;
-
-        Set<RoleModel> visited = new HashSet<RoleModel>();
-        return KeycloakModelUtils.searchFor(role, this, visited);
-    }
-
-    @Override
-    public RoleContainerModel getContainer() {
-        if (role.isClientRole()) {
-            return realm.getClientById(role.getClient().getId());
-
-        } else {
-            return realm;
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RoleModel)) return false;
-
-        RoleModel that = (RoleModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    public static RoleEntity toRoleEntity(RoleModel model, EntityManager em) {
-        if (model instanceof RoleAdapter) {
-            return ((RoleAdapter)model).getRole();
-        }
-        return em.getReference(RoleEntity.class, model.getId());
-    }
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleAdapter implements RoleModel {
+    protected RoleEntity role;
+    protected EntityManager em;
+    protected RealmModel realm;
+
+    public RoleAdapter(RealmModel realm, EntityManager em, RoleEntity role) {
+        this.em = em;
+        this.realm = realm;
+        this.role = role;
+    }
+
+    public RoleEntity getRole() {
+        return role;
+    }
+
+    public void setRole(RoleEntity role) {
+        this.role = role;
+    }
+
+    @Override
+    public String getName() {
+        return role.getName();
+    }
+
+    @Override
+    public String getDescription() {
+        return role.getDescription();
+    }
+
+    @Override
+    public void setDescription(String description) {
+        role.setDescription(description);
+    }
+
+    @Override
+    public String getId() {
+        return role.getId();
+    }
+
+    @Override
+    public void setName(String name) {
+        role.setName(name);
+    }
+
+    @Override
+    public boolean isComposite() {
+        return getComposites().size() > 0;
+    }
+
+    @Override
+    public void addCompositeRole(RoleModel role) {
+        RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
+        for (RoleEntity composite : getRole().getCompositeRoles()) {
+            if (composite.equals(entity)) return;
+        }
+        getRole().getCompositeRoles().add(entity);
+        em.flush();
+    }
+
+    @Override
+    public void removeCompositeRole(RoleModel role) {
+        RoleEntity entity = RoleAdapter.toRoleEntity(role, em);
+        Iterator<RoleEntity> it = getRole().getCompositeRoles().iterator();
+        while (it.hasNext()) {
+            if (it.next().equals(entity)) it.remove();
+        }
+    }
+
+    @Override
+    public Set<RoleModel> getComposites() {
+        Set<RoleModel> set = new HashSet<RoleModel>();
+
+        for (RoleEntity composite : getRole().getCompositeRoles()) {
+           set.add(new RoleAdapter(realm, em, composite));
+        }
+        return set;
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        if (this.equals(role)) return true;
+        if (!isComposite()) return false;
+
+        Set<RoleModel> visited = new HashSet<RoleModel>();
+        return KeycloakModelUtils.searchFor(role, this, visited);
+    }
+
+    @Override
+    public RoleContainerModel getContainer() {
+        if (role.isClientRole()) {
+            return realm.getClientById(role.getClient().getId());
+
+        } else {
+            return realm;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RoleModel)) return false;
+
+        RoleModel that = (RoleModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    public static RoleEntity toRoleEntity(RoleModel model, EntityManager em) {
+        if (model instanceof RoleAdapter) {
+            return ((RoleAdapter)model).getRole();
+        }
+        return em.getReference(RoleEntity.class, model.getId());
+    }
+}
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 c8d7fd1..0e10110 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
@@ -1,718 +1,718 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.jpa.entities.CredentialEntity;
-import org.keycloak.models.jpa.entities.UserConsentEntity;
-import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
-import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
-import org.keycloak.models.jpa.entities.UserAttributeEntity;
-import org.keycloak.models.jpa.entities.UserEntity;
-import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
-import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
-import org.keycloak.util.MultivaluedHashMap;
-import org.keycloak.util.Time;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAdapter implements UserModel {
-
-    protected UserEntity user;
-    protected EntityManager em;
-    protected RealmModel realm;
-
-    public UserAdapter(RealmModel realm, EntityManager em, UserEntity user) {
-        this.em = em;
-        this.user = user;
-        this.realm = realm;
-    }
-
-    public UserEntity getUser() {
-        return user;
-    }
-
-    @Override
-    public String getId() {
-        return user.getId();
-    }
-
-    @Override
-    public String getUsername() {
-        return user.getUsername();
-    }
-
-    @Override
-    public void setUsername(String username) {
-        user.setUsername(username);
-    }
-
-    @Override
-    public Long getCreatedTimestamp() {
-        return user.getCreatedTimestamp();
-    }
-
-    @Override
-    public void setCreatedTimestamp(Long timestamp) {
-        user.setCreatedTimestamp(timestamp);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return user.isEnabled();
-    }
-
-    @Override
-    public boolean isTotp() {
-        return user.isTotp();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        user.setEnabled(enabled);
-    }
-
-    @Override
-    public void setSingleAttribute(String name, String value) {
-        boolean found = false;
-        List<UserAttributeEntity> toRemove = new ArrayList<>();
-        for (UserAttributeEntity attr : user.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                if (!found) {
-                    attr.setValue(value);
-                    found = true;
-                } else {
-                    toRemove.add(attr);
-                }
-            }
-        }
-
-        for (UserAttributeEntity attr : toRemove) {
-            em.remove(attr);
-            user.getAttributes().remove(attr);
-        }
-
-        if (found) {
-            return;
-        }
-
-        persistAttributeValue(name, value);
-    }
-
-    @Override
-    public void setAttribute(String name, List<String> values) {
-        // Remove all existing
-        removeAttribute(name);
-
-        // Put all new
-        for (String value : values) {
-            persistAttributeValue(name, value);
-        }
-    }
-
-    private void persistAttributeValue(String name, String value) {
-        UserAttributeEntity attr = new UserAttributeEntity();
-        attr.setId(KeycloakModelUtils.generateId());
-        attr.setName(name);
-        attr.setValue(value);
-        attr.setUser(user);
-        em.persist(attr);
-        user.getAttributes().add(attr);
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        Iterator<UserAttributeEntity> it = user.getAttributes().iterator();
-        while (it.hasNext()) {
-            UserAttributeEntity attr = it.next();
-            if (attr.getName().equals(name)) {
-                it.remove();
-                em.remove(attr);
-            }
-        }
-    }
-
-    @Override
-    public String getFirstAttribute(String name) {
-        for (UserAttributeEntity attr : user.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                return attr.getValue();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public List<String> getAttribute(String name) {
-        List<String> result = new ArrayList<>();
-        for (UserAttributeEntity attr : user.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                result.add(attr.getValue());
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public Map<String, List<String>> getAttributes() {
-        MultivaluedHashMap<String, String> result = new MultivaluedHashMap<>();
-        for (UserAttributeEntity attr : user.getAttributes()) {
-            result.add(attr.getName(), attr.getValue());
-        }
-        return result;
-    }
-
-    @Override
-    public Set<String> getRequiredActions() {
-        Set<String> result = new HashSet<>();
-        for (UserRequiredActionEntity attr : user.getRequiredActions()) {
-            result.add(attr.getAction());
-        }
-        return result;
-    }
-
-    @Override
-    public void addRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        addRequiredAction(actionName);
-    }
-
-    @Override
-    public void addRequiredAction(String actionName) {
-        for (UserRequiredActionEntity attr : user.getRequiredActions()) {
-            if (attr.getAction().equals(actionName)) {
-                return;
-            }
-        }
-        UserRequiredActionEntity attr = new UserRequiredActionEntity();
-        attr.setAction(actionName);
-        attr.setUser(user);
-        em.persist(attr);
-        user.getRequiredActions().add(attr);
-    }
-
-    @Override
-    public void removeRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        removeRequiredAction(actionName);
-    }
-
-    @Override
-    public void removeRequiredAction(String actionName) {
-        Iterator<UserRequiredActionEntity> it = user.getRequiredActions().iterator();
-        while (it.hasNext()) {
-            UserRequiredActionEntity attr = it.next();
-            if (attr.getAction().equals(actionName)) {
-                it.remove();
-                em.remove(attr);
-            }
-        }
-    }
-
-    @Override
-    public String getFirstName() {
-        return user.getFirstName();
-    }
-
-    @Override
-    public void setFirstName(String firstName) {
-        user.setFirstName(firstName);
-    }
-
-    @Override
-    public String getLastName() {
-        return user.getLastName();
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        user.setLastName(lastName);
-    }
-
-    @Override
-    public String getEmail() {
-        return user.getEmail();
-    }
-
-    @Override
-    public void setEmail(String email) {
-        user.setEmail(email);
-    }
-
-    @Override
-    public boolean isEmailVerified() {
-        return user.isEmailVerified();
-    }
-
-    @Override
-    public void setEmailVerified(boolean verified) {
-        user.setEmailVerified(verified);
-    }
-
-    @Override
-    public void setTotp(boolean totp) {
-        user.setTotp(totp);
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            updatePasswordCredential(cred);
-        } else {
-            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-            if (credentialEntity == null) {
-                credentialEntity = setCredentials(user, cred);
-                credentialEntity.setValue(cred.getValue());
-                em.persist(credentialEntity);
-                user.getCredentials().add(credentialEntity);
-            } else {
-                credentialEntity.setValue(cred.getValue());
-            }
-        }
-        em.flush();
-    }
-
-    private void updatePasswordCredential(UserCredentialModel cred) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = setCredentials(user, cred);
-            setValue(credentialEntity, cred);
-            em.persist(credentialEntity);
-            user.getCredentials().add(credentialEntity);
-        } else {
-            
-            int expiredPasswordsPolicyValue = -1;
-            PasswordPolicy policy = realm.getPasswordPolicy();
-            if(policy != null) {
-                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
-            }
-
-            if (expiredPasswordsPolicyValue != -1) {
-                user.getCredentials().remove(credentialEntity);
-                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
-                user.getCredentials().add(credentialEntity);
-
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
-                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
-                }
-
-                credentialEntity = setCredentials(user, cred);
-                setValue(credentialEntity, cred);
-                em.persist(credentialEntity);
-                user.getCredentials().add(credentialEntity);
-            } else {
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities != null && credentialEntities.size() > 0) {
-                    user.getCredentials().removeAll(credentialEntities);
-                }
-                setValue(credentialEntity, cred);
-            }
-        }
-    }
-    
-    private CredentialEntity setCredentials(UserEntity user, UserCredentialModel cred) {
-        CredentialEntity credentialEntity = new CredentialEntity();
-        credentialEntity.setId(KeycloakModelUtils.generateId());
-        credentialEntity.setType(cred.getType());
-        credentialEntity.setDevice(cred.getDevice());
-        credentialEntity.setUser(user);
-        return credentialEntity;
-    }
-
-    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
-        byte[] salt = getSalt();
-        int hashIterations = 1;
-        PasswordPolicy policy = realm.getPasswordPolicy();
-        if (policy != null) {
-            hashIterations = policy.getHashIterations();
-            if (hashIterations == -1)
-                hashIterations = 1;
-        }
-        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
-        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
-        credentialEntity.setSalt(salt);
-        credentialEntity.setHashIterations(hashIterations);
-    }
-
-    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                return entity;
-            }
-        }
-
-        return null;
-    }
-
-    private List<CredentialEntity> getCredentialEntities(UserEntity userEntity, String credType) {
-        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                credentialEntities.add(entity);
-            }
-        }
-
-        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
-        // Orders from most recent to least recent
-        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
-            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
-                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
-                    return -1;
-                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-        });
-        return credentialEntities;
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly() {
-        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
-        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
-
-        if (credentials != null) {
-            for (CredentialEntity credEntity : credentials) {
-                UserCredentialValueModel credModel = new UserCredentialValueModel();
-                credModel.setType(credEntity.getType());
-                credModel.setDevice(credEntity.getDevice());
-                credModel.setValue(credEntity.getValue());
-                credModel.setCreatedDate(credEntity.getCreatedDate());
-                credModel.setSalt(credEntity.getSalt());
-                credModel.setHashIterations(credEntity.getHashIterations());
-
-                result.add(credModel);
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setId(KeycloakModelUtils.generateId());
-            credentialEntity.setType(credModel.getType());
-            credentialEntity.setCreatedDate(credModel.getCreatedDate());
-            credentialEntity.setUser(user);
-            em.persist(credentialEntity);
-            user.getCredentials().add(credentialEntity);
-        }
-
-        credentialEntity.setValue(credModel.getValue());
-        credentialEntity.setSalt(credModel.getSalt());
-        credentialEntity.setDevice(credModel.getDevice());
-        credentialEntity.setHashIterations(credModel.getHashIterations());
-
-        em.flush();
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
-    }
-
-    protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) {
-        TypedQuery<UserRoleMappingEntity> query = em.createNamedQuery("userHasRole", UserRoleMappingEntity.class);
-        query.setParameter("user", getUser());
-        query.setParameter("roleId", role.getId());
-        return query;
-    }
-
-    @Override
-    public void grantRole(RoleModel role) {
-        if (hasRole(role)) return;
-        UserRoleMappingEntity entity = new UserRoleMappingEntity();
-        entity.setUser(getUser());
-        entity.setRoleId(role.getId());
-        em.persist(entity);
-        em.flush();
-        em.detach(entity);
-    }
-
-    @Override
-    public Set<RoleModel> getRealmRoleMappings() {
-        Set<RoleModel> roleMappings = getRoleMappings();
-
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof RealmModel) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-
-    @Override
-    public Set<RoleModel> getRoleMappings() {
-        // we query ids only as the role might be cached and following the @ManyToOne will result in a load
-        // even if we're getting just the id.
-        TypedQuery<String> query = em.createNamedQuery("userRoleMappingIds", String.class);
-        query.setParameter("user", getUser());
-        List<String> ids = query.getResultList();
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String roleId : ids) {
-            RoleModel roleById = realm.getRoleById(roleId);
-            if (roleById == null) continue;
-            roles.add(roleById);
-        }
-        return roles;
-    }
-
-    @Override
-    public void deleteRoleMapping(RoleModel role) {
-        if (user == null || role == null) return;
-
-        TypedQuery<UserRoleMappingEntity> query = getUserRoleMappingEntityTypedQuery(role);
-        List<UserRoleMappingEntity> results = query.getResultList();
-        if (results.size() == 0) return;
-        for (UserRoleMappingEntity entity : results) {
-            em.remove(entity);
-        }
-        em.flush();
-    }
-
-    @Override
-    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        Set<RoleModel> roleMappings = getRoleMappings();
-
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (RoleModel role : roleMappings) {
-            RoleContainerModel container = role.getContainer();
-            if (container instanceof ClientModel) {
-                ClientModel appModel = (ClientModel)container;
-                if (appModel.getId().equals(app.getId())) {
-                   roles.add(role);
-                }
-            }
-        }
-        return roles;
-    }
-
-    @Override
-    public String getFederationLink() {
-        return user.getFederationLink();
-    }
-
-    @Override
-    public void setFederationLink(String link) {
-        user.setFederationLink(link);
-    }
-
-    @Override
-    public void addConsent(UserConsentModel consent) {
-        String clientId = consent.getClient().getId();
-
-        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
-        if (consentEntity != null) {
-            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
-        }
-
-        consentEntity = new UserConsentEntity();
-        consentEntity.setId(KeycloakModelUtils.generateId());
-        consentEntity.setUser(user);
-        consentEntity.setClientId(clientId);
-        em.persist(consentEntity);
-        em.flush();
-
-        updateGrantedConsentEntity(consentEntity, consent);
-    }
-
-    @Override
-    public UserConsentModel getConsentByClient(String clientId) {
-        UserConsentEntity entity = getGrantedConsentEntity(clientId);
-        return toConsentModel(entity);
-    }
-
-    @Override
-    public List<UserConsentModel> getConsents() {
-        TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
-        query.setParameter("userId", getId());
-        List<UserConsentEntity> results = query.getResultList();
-
-        List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
-        for (UserConsentEntity entity : results) {
-            UserConsentModel model = toConsentModel(entity);
-            consents.add(model);
-        }
-        return consents;
-    }
-
-    @Override
-    public void updateConsent(UserConsentModel consent) {
-        String clientId = consent.getClient().getId();
-
-        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
-        if (consentEntity == null) {
-            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
-        }
-
-        updateGrantedConsentEntity(consentEntity, consent);
-    }
-
-    @Override
-    public boolean revokeConsentForClient(String clientId) {
-        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
-        if (consentEntity == null) return false;
-
-        em.remove(consentEntity);
-        em.flush();
-        return true;
-    }
-
-
-    private UserConsentEntity getGrantedConsentEntity(String clientId) {
-        TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
-        query.setParameter("userId", getId());
-        query.setParameter("clientId", clientId);
-        List<UserConsentEntity> results = query.getResultList();
-        if (results.size() > 1) {
-            throw new ModelException("More results found for user [" + getUsername() + "] and client [" + clientId + "]");
-        } else if (results.size() == 1) {
-            return results.get(0);
-        } else {
-            return null;
-        }
-    }
-
-    private UserConsentModel toConsentModel(UserConsentEntity entity) {
-        if (entity == null) {
-            return null;
-        }
-
-        ClientModel client = realm.getClientById(entity.getClientId());
-        if (client == null) {
-            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
-        }
-        UserConsentModel model = new UserConsentModel(client);
-
-        Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
-        if (grantedRoleEntities != null) {
-            for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
-                RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
-                if (grantedRoleModel != null) {
-                    model.addGrantedRole(grantedRoleModel);
-                }
-            }
-        }
-
-        Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
-        if (grantedProtocolMapperEntities != null) {
-            for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
-                ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
-                model.addGrantedProtocolMapper(protocolMapper );
-            }
-        }
-
-        return model;
-    }
-
-    // Update roles and protocolMappers to given consentEntity from the consentModel
-    private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
-        Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
-        Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
-
-        for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
-            UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
-            grantedProtocolMapperEntity.setUserConsent(consentEntity);
-            grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
-
-            // Check if it's already there
-            if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
-                em.persist(grantedProtocolMapperEntity);
-                em.flush();
-                grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
-            } else {
-                mappersToRemove.remove(grantedProtocolMapperEntity);
-            }
-        }
-        // Those mappers were no longer on consentModel and will be removed
-        for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
-            grantedProtocolMapperEntities.remove(toRemove);
-            em.remove(toRemove);
-        }
-
-        Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
-        Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
-        for (RoleModel role : consentModel.getGrantedRoles()) {
-            UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
-            consentRoleEntity.setUserConsent(consentEntity);
-            consentRoleEntity.setRoleId(role.getId());
-
-            // Check if it's already there
-            if (!grantedRoleEntities.contains(consentRoleEntity)) {
-                em.persist(consentRoleEntity);
-                em.flush();
-                grantedRoleEntities.add(consentRoleEntity);
-            } else {
-                rolesToRemove.remove(consentRoleEntity);
-            }
-        }
-        // Those roles were no longer on consentModel and will be removed
-        for (UserConsentRoleEntity toRemove : rolesToRemove) {
-            grantedRoleEntities.remove(toRemove);
-            em.remove(toRemove);
-        }
-
-        em.flush();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof UserModel)) return false;
-
-        UserModel that = (UserModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-
-
-}
+package org.keycloak.models.jpa;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.jpa.entities.CredentialEntity;
+import org.keycloak.models.jpa.entities.UserConsentEntity;
+import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
+import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
+import org.keycloak.models.jpa.entities.UserAttributeEntity;
+import org.keycloak.models.jpa.entities.UserEntity;
+import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
+import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
+import org.keycloak.util.MultivaluedHashMap;
+import org.keycloak.util.Time;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAdapter implements UserModel {
+
+    protected UserEntity user;
+    protected EntityManager em;
+    protected RealmModel realm;
+
+    public UserAdapter(RealmModel realm, EntityManager em, UserEntity user) {
+        this.em = em;
+        this.user = user;
+        this.realm = realm;
+    }
+
+    public UserEntity getUser() {
+        return user;
+    }
+
+    @Override
+    public String getId() {
+        return user.getId();
+    }
+
+    @Override
+    public String getUsername() {
+        return user.getUsername();
+    }
+
+    @Override
+    public void setUsername(String username) {
+        user.setUsername(username);
+    }
+
+    @Override
+    public Long getCreatedTimestamp() {
+        return user.getCreatedTimestamp();
+    }
+
+    @Override
+    public void setCreatedTimestamp(Long timestamp) {
+        user.setCreatedTimestamp(timestamp);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return user.isEnabled();
+    }
+
+    @Override
+    public boolean isTotp() {
+        return user.isTotp();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        user.setEnabled(enabled);
+    }
+
+    @Override
+    public void setSingleAttribute(String name, String value) {
+        boolean found = false;
+        List<UserAttributeEntity> toRemove = new ArrayList<>();
+        for (UserAttributeEntity attr : user.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                if (!found) {
+                    attr.setValue(value);
+                    found = true;
+                } else {
+                    toRemove.add(attr);
+                }
+            }
+        }
+
+        for (UserAttributeEntity attr : toRemove) {
+            em.remove(attr);
+            user.getAttributes().remove(attr);
+        }
+
+        if (found) {
+            return;
+        }
+
+        persistAttributeValue(name, value);
+    }
+
+    @Override
+    public void setAttribute(String name, List<String> values) {
+        // Remove all existing
+        removeAttribute(name);
+
+        // Put all new
+        for (String value : values) {
+            persistAttributeValue(name, value);
+        }
+    }
+
+    private void persistAttributeValue(String name, String value) {
+        UserAttributeEntity attr = new UserAttributeEntity();
+        attr.setId(KeycloakModelUtils.generateId());
+        attr.setName(name);
+        attr.setValue(value);
+        attr.setUser(user);
+        em.persist(attr);
+        user.getAttributes().add(attr);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        Iterator<UserAttributeEntity> it = user.getAttributes().iterator();
+        while (it.hasNext()) {
+            UserAttributeEntity attr = it.next();
+            if (attr.getName().equals(name)) {
+                it.remove();
+                em.remove(attr);
+            }
+        }
+    }
+
+    @Override
+    public String getFirstAttribute(String name) {
+        for (UserAttributeEntity attr : user.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                return attr.getValue();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public List<String> getAttribute(String name) {
+        List<String> result = new ArrayList<>();
+        for (UserAttributeEntity attr : user.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                result.add(attr.getValue());
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Map<String, List<String>> getAttributes() {
+        MultivaluedHashMap<String, String> result = new MultivaluedHashMap<>();
+        for (UserAttributeEntity attr : user.getAttributes()) {
+            result.add(attr.getName(), attr.getValue());
+        }
+        return result;
+    }
+
+    @Override
+    public Set<String> getRequiredActions() {
+        Set<String> result = new HashSet<>();
+        for (UserRequiredActionEntity attr : user.getRequiredActions()) {
+            result.add(attr.getAction());
+        }
+        return result;
+    }
+
+    @Override
+    public void addRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        addRequiredAction(actionName);
+    }
+
+    @Override
+    public void addRequiredAction(String actionName) {
+        for (UserRequiredActionEntity attr : user.getRequiredActions()) {
+            if (attr.getAction().equals(actionName)) {
+                return;
+            }
+        }
+        UserRequiredActionEntity attr = new UserRequiredActionEntity();
+        attr.setAction(actionName);
+        attr.setUser(user);
+        em.persist(attr);
+        user.getRequiredActions().add(attr);
+    }
+
+    @Override
+    public void removeRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        removeRequiredAction(actionName);
+    }
+
+    @Override
+    public void removeRequiredAction(String actionName) {
+        Iterator<UserRequiredActionEntity> it = user.getRequiredActions().iterator();
+        while (it.hasNext()) {
+            UserRequiredActionEntity attr = it.next();
+            if (attr.getAction().equals(actionName)) {
+                it.remove();
+                em.remove(attr);
+            }
+        }
+    }
+
+    @Override
+    public String getFirstName() {
+        return user.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        user.setFirstName(firstName);
+    }
+
+    @Override
+    public String getLastName() {
+        return user.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        user.setLastName(lastName);
+    }
+
+    @Override
+    public String getEmail() {
+        return user.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        user.setEmail(email);
+    }
+
+    @Override
+    public boolean isEmailVerified() {
+        return user.isEmailVerified();
+    }
+
+    @Override
+    public void setEmailVerified(boolean verified) {
+        user.setEmailVerified(verified);
+    }
+
+    @Override
+    public void setTotp(boolean totp) {
+        user.setTotp(totp);
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            updatePasswordCredential(cred);
+        } else {
+            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+            if (credentialEntity == null) {
+                credentialEntity = setCredentials(user, cred);
+                credentialEntity.setValue(cred.getValue());
+                em.persist(credentialEntity);
+                user.getCredentials().add(credentialEntity);
+            } else {
+                credentialEntity.setValue(cred.getValue());
+            }
+        }
+        em.flush();
+    }
+
+    private void updatePasswordCredential(UserCredentialModel cred) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = setCredentials(user, cred);
+            setValue(credentialEntity, cred);
+            em.persist(credentialEntity);
+            user.getCredentials().add(credentialEntity);
+        } else {
+            
+            int expiredPasswordsPolicyValue = -1;
+            PasswordPolicy policy = realm.getPasswordPolicy();
+            if(policy != null) {
+                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
+            }
+
+            if (expiredPasswordsPolicyValue != -1) {
+                user.getCredentials().remove(credentialEntity);
+                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
+                user.getCredentials().add(credentialEntity);
+
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
+                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
+                }
+
+                credentialEntity = setCredentials(user, cred);
+                setValue(credentialEntity, cred);
+                em.persist(credentialEntity);
+                user.getCredentials().add(credentialEntity);
+            } else {
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities != null && credentialEntities.size() > 0) {
+                    user.getCredentials().removeAll(credentialEntities);
+                }
+                setValue(credentialEntity, cred);
+            }
+        }
+    }
+    
+    private CredentialEntity setCredentials(UserEntity user, UserCredentialModel cred) {
+        CredentialEntity credentialEntity = new CredentialEntity();
+        credentialEntity.setId(KeycloakModelUtils.generateId());
+        credentialEntity.setType(cred.getType());
+        credentialEntity.setDevice(cred.getDevice());
+        credentialEntity.setUser(user);
+        return credentialEntity;
+    }
+
+    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
+        byte[] salt = getSalt();
+        int hashIterations = 1;
+        PasswordPolicy policy = realm.getPasswordPolicy();
+        if (policy != null) {
+            hashIterations = policy.getHashIterations();
+            if (hashIterations == -1)
+                hashIterations = 1;
+        }
+        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
+        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
+        credentialEntity.setSalt(salt);
+        credentialEntity.setHashIterations(hashIterations);
+    }
+
+    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                return entity;
+            }
+        }
+
+        return null;
+    }
+
+    private List<CredentialEntity> getCredentialEntities(UserEntity userEntity, String credType) {
+        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                credentialEntities.add(entity);
+            }
+        }
+
+        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
+        // Orders from most recent to least recent
+        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
+            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
+                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
+                    return -1;
+                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+        return credentialEntities;
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
+        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
+
+        if (credentials != null) {
+            for (CredentialEntity credEntity : credentials) {
+                UserCredentialValueModel credModel = new UserCredentialValueModel();
+                credModel.setType(credEntity.getType());
+                credModel.setDevice(credEntity.getDevice());
+                credModel.setValue(credEntity.getValue());
+                credModel.setCreatedDate(credEntity.getCreatedDate());
+                credModel.setSalt(credEntity.getSalt());
+                credModel.setHashIterations(credEntity.getHashIterations());
+
+                result.add(credModel);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setId(KeycloakModelUtils.generateId());
+            credentialEntity.setType(credModel.getType());
+            credentialEntity.setCreatedDate(credModel.getCreatedDate());
+            credentialEntity.setUser(user);
+            em.persist(credentialEntity);
+            user.getCredentials().add(credentialEntity);
+        }
+
+        credentialEntity.setValue(credModel.getValue());
+        credentialEntity.setSalt(credModel.getSalt());
+        credentialEntity.setDevice(credModel.getDevice());
+        credentialEntity.setHashIterations(credModel.getHashIterations());
+
+        em.flush();
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        Set<RoleModel> roles = getRoleMappings();
+        return KeycloakModelUtils.hasRole(roles, role);
+    }
+
+    protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) {
+        TypedQuery<UserRoleMappingEntity> query = em.createNamedQuery("userHasRole", UserRoleMappingEntity.class);
+        query.setParameter("user", getUser());
+        query.setParameter("roleId", role.getId());
+        return query;
+    }
+
+    @Override
+    public void grantRole(RoleModel role) {
+        if (hasRole(role)) return;
+        UserRoleMappingEntity entity = new UserRoleMappingEntity();
+        entity.setUser(getUser());
+        entity.setRoleId(role.getId());
+        em.persist(entity);
+        em.flush();
+        em.detach(entity);
+    }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings() {
+        Set<RoleModel> roleMappings = getRoleMappings();
+
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+
+    @Override
+    public Set<RoleModel> getRoleMappings() {
+        // we query ids only as the role might be cached and following the @ManyToOne will result in a load
+        // even if we're getting just the id.
+        TypedQuery<String> query = em.createNamedQuery("userRoleMappingIds", String.class);
+        query.setParameter("user", getUser());
+        List<String> ids = query.getResultList();
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String roleId : ids) {
+            RoleModel roleById = realm.getRoleById(roleId);
+            if (roleById == null) continue;
+            roles.add(roleById);
+        }
+        return roles;
+    }
+
+    @Override
+    public void deleteRoleMapping(RoleModel role) {
+        if (user == null || role == null) return;
+
+        TypedQuery<UserRoleMappingEntity> query = getUserRoleMappingEntityTypedQuery(role);
+        List<UserRoleMappingEntity> results = query.getResultList();
+        if (results.size() == 0) return;
+        for (UserRoleMappingEntity entity : results) {
+            em.remove(entity);
+        }
+        em.flush();
+    }
+
+    @Override
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        Set<RoleModel> roleMappings = getRoleMappings();
+
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof ClientModel) {
+                ClientModel appModel = (ClientModel)container;
+                if (appModel.getId().equals(app.getId())) {
+                   roles.add(role);
+                }
+            }
+        }
+        return roles;
+    }
+
+    @Override
+    public String getFederationLink() {
+        return user.getFederationLink();
+    }
+
+    @Override
+    public void setFederationLink(String link) {
+        user.setFederationLink(link);
+    }
+
+    @Override
+    public void addConsent(UserConsentModel consent) {
+        String clientId = consent.getClient().getId();
+
+        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+        if (consentEntity != null) {
+            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+        }
+
+        consentEntity = new UserConsentEntity();
+        consentEntity.setId(KeycloakModelUtils.generateId());
+        consentEntity.setUser(user);
+        consentEntity.setClientId(clientId);
+        em.persist(consentEntity);
+        em.flush();
+
+        updateGrantedConsentEntity(consentEntity, consent);
+    }
+
+    @Override
+    public UserConsentModel getConsentByClient(String clientId) {
+        UserConsentEntity entity = getGrantedConsentEntity(clientId);
+        return toConsentModel(entity);
+    }
+
+    @Override
+    public List<UserConsentModel> getConsents() {
+        TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
+        query.setParameter("userId", getId());
+        List<UserConsentEntity> results = query.getResultList();
+
+        List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
+        for (UserConsentEntity entity : results) {
+            UserConsentModel model = toConsentModel(entity);
+            consents.add(model);
+        }
+        return consents;
+    }
+
+    @Override
+    public void updateConsent(UserConsentModel consent) {
+        String clientId = consent.getClient().getId();
+
+        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+        if (consentEntity == null) {
+            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+        }
+
+        updateGrantedConsentEntity(consentEntity, consent);
+    }
+
+    @Override
+    public boolean revokeConsentForClient(String clientId) {
+        UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
+        if (consentEntity == null) return false;
+
+        em.remove(consentEntity);
+        em.flush();
+        return true;
+    }
+
+
+    private UserConsentEntity getGrantedConsentEntity(String clientId) {
+        TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
+        query.setParameter("userId", getId());
+        query.setParameter("clientId", clientId);
+        List<UserConsentEntity> results = query.getResultList();
+        if (results.size() > 1) {
+            throw new ModelException("More results found for user [" + getUsername() + "] and client [" + clientId + "]");
+        } else if (results.size() == 1) {
+            return results.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    private UserConsentModel toConsentModel(UserConsentEntity entity) {
+        if (entity == null) {
+            return null;
+        }
+
+        ClientModel client = realm.getClientById(entity.getClientId());
+        if (client == null) {
+            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+        }
+        UserConsentModel model = new UserConsentModel(client);
+
+        Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
+        if (grantedRoleEntities != null) {
+            for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
+                RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
+                if (grantedRoleModel != null) {
+                    model.addGrantedRole(grantedRoleModel);
+                }
+            }
+        }
+
+        Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
+        if (grantedProtocolMapperEntities != null) {
+            for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
+                ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
+                model.addGrantedProtocolMapper(protocolMapper );
+            }
+        }
+
+        return model;
+    }
+
+    // Update roles and protocolMappers to given consentEntity from the consentModel
+    private void updateGrantedConsentEntity(UserConsentEntity consentEntity, UserConsentModel consentModel) {
+        Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = consentEntity.getGrantedProtocolMappers();
+        Collection<UserConsentProtocolMapperEntity> mappersToRemove = new HashSet<UserConsentProtocolMapperEntity>(grantedProtocolMapperEntities);
+
+        for (ProtocolMapperModel protocolMapper : consentModel.getGrantedProtocolMappers()) {
+            UserConsentProtocolMapperEntity grantedProtocolMapperEntity = new UserConsentProtocolMapperEntity();
+            grantedProtocolMapperEntity.setUserConsent(consentEntity);
+            grantedProtocolMapperEntity.setProtocolMapperId(protocolMapper.getId());
+
+            // Check if it's already there
+            if (!grantedProtocolMapperEntities.contains(grantedProtocolMapperEntity)) {
+                em.persist(grantedProtocolMapperEntity);
+                em.flush();
+                grantedProtocolMapperEntities.add(grantedProtocolMapperEntity);
+            } else {
+                mappersToRemove.remove(grantedProtocolMapperEntity);
+            }
+        }
+        // Those mappers were no longer on consentModel and will be removed
+        for (UserConsentProtocolMapperEntity toRemove : mappersToRemove) {
+            grantedProtocolMapperEntities.remove(toRemove);
+            em.remove(toRemove);
+        }
+
+        Collection<UserConsentRoleEntity> grantedRoleEntities = consentEntity.getGrantedRoles();
+        Set<UserConsentRoleEntity> rolesToRemove = new HashSet<UserConsentRoleEntity>(grantedRoleEntities);
+        for (RoleModel role : consentModel.getGrantedRoles()) {
+            UserConsentRoleEntity consentRoleEntity = new UserConsentRoleEntity();
+            consentRoleEntity.setUserConsent(consentEntity);
+            consentRoleEntity.setRoleId(role.getId());
+
+            // Check if it's already there
+            if (!grantedRoleEntities.contains(consentRoleEntity)) {
+                em.persist(consentRoleEntity);
+                em.flush();
+                grantedRoleEntities.add(consentRoleEntity);
+            } else {
+                rolesToRemove.remove(consentRoleEntity);
+            }
+        }
+        // Those roles were no longer on consentModel and will be removed
+        for (UserConsentRoleEntity toRemove : rolesToRemove) {
+            grantedRoleEntities.remove(toRemove);
+            em.remove(toRemove);
+        }
+
+        em.flush();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserModel)) return false;
+
+        UserModel that = (UserModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
+
+}

model/mongo/pom.xml 106(+53 -53)

diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml
index df7f9d8..02fd862 100755
--- a/model/mongo/pom.xml
+++ b/model/mongo/pom.xml
@@ -1,54 +1,54 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-mongo</artifactId>
-    <name>Keycloak Model Mongo</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-mongo</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-mongo</artifactId>
+    <name>Keycloak Model Mongo</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-mongo</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
 </project>
\ No newline at end of file
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index b0784f5..0f50420 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -1,641 +1,641 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.entities.ProtocolMapperEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.mongo.utils.MongoModelUtils;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> implements ClientModel {
-
-    protected final MongoClientEntity clientEntity;
-    private final RealmModel realm;
-    protected  KeycloakSession session;
-
-    public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity clientEntity, MongoStoreInvocationContext invContext) {
-        super(invContext);
-        this.session = session;
-        this.realm = realm;
-        this.clientEntity = clientEntity;
-    }
-
-    @Override
-    public MongoClientEntity getMongoEntity() {
-        return clientEntity;
-    }
-
-    @Override
-    public void updateClient() {
-        updateMongoEntity();
-    }
-
-
-    @Override
-    public String getId() {
-        return getMongoEntity().getId();
-    }
-
-    @Override
-    public String getClientId() {
-        return getMongoEntity().getClientId();
-    }
-
-    @Override
-    public String getName() {
-        return getMongoEntity().getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        getMongoEntity().setName(name);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void setClientId(String clientId) {
-        getMongoEntity().setClientId(clientId);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Set<String> getWebOrigins() {
-        Set<String> result = new HashSet<String>();
-        if (getMongoEntity().getWebOrigins() != null) {
-            result.addAll(getMongoEntity().getWebOrigins());
-        }
-        return result;
-    }
-
-    @Override
-    public void setWebOrigins(Set<String> webOrigins) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(webOrigins);
-        getMongoEntity().setWebOrigins(result);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void addWebOrigin(String webOrigin) {
-        getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext);
-    }
-
-    @Override
-    public void removeWebOrigin(String webOrigin) {
-        getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext);
-    }
-
-    @Override
-    public Set<String> getRedirectUris() {
-        Set<String> result = new HashSet<String>();
-        if (getMongoEntity().getRedirectUris() != null) {
-            result.addAll(getMongoEntity().getRedirectUris());
-        }
-        return result;
-    }
-
-    @Override
-    public void setRedirectUris(Set<String> redirectUris) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(redirectUris);
-        getMongoEntity().setRedirectUris(result);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void addRedirectUri(String redirectUri) {
-        getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext);
-    }
-
-    @Override
-    public void removeRedirectUri(String redirectUri) {
-        getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return getMongoEntity().isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        getMongoEntity().setEnabled(enabled);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean validateSecret(String secret) {
-        return secret.equals(getMongoEntity().getSecret());
-    }
-
-    @Override
-    public String getSecret() {
-        return getMongoEntity().getSecret();
-    }
-
-    @Override
-    public void setSecret(String secret) {
-        getMongoEntity().setSecret(secret);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isPublicClient() {
-        return getMongoEntity().isPublicClient();
-    }
-
-    @Override
-    public void setPublicClient(boolean flag) {
-        getMongoEntity().setPublicClient(flag);
-        updateMongoEntity();
-    }
-
-
-    @Override
-    public boolean isFrontchannelLogout() {
-        return getMongoEntity().isFrontchannelLogout();
-    }
-
-    @Override
-    public void setFrontchannelLogout(boolean flag) {
-        getMongoEntity().setFrontchannelLogout(flag);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        return getMongoEntity().isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        getMongoEntity().setFullScopeAllowed(value);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public int getNotBefore() {
-        return getMongoEntity().getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        getMongoEntity().setNotBefore(notBefore);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Set<RoleModel> getScopeMappings() {
-        Set<RoleModel> result = new HashSet<RoleModel>();
-        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext);
-
-        for (MongoRoleEntity role : roles) {
-            if (realm.getId().equals(role.getRealmId())) {
-                result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
-            } else {
-                // Likely applicationRole, but we don't have this application yet
-                result.add(new RoleAdapter(session, realm, role, invocationContext));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> allScopes = getScopeMappings();
-
-        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allScopes) {
-            MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
-
-            if (realm.getId().equals(roleEntity.getRealmId())) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public void addScopeMapping(RoleModel role) {
-        getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
-    }
-
-    @Override
-    public void deleteScopeMapping(RoleModel role) {
-        getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
-    }
-
-    @Override
-    public String getProtocol() {
-        return getMongoEntity().getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        getMongoEntity().setProtocol(protocol);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        getMongoEntity().getAttributes().put(name, value);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        getMongoEntity().getAttributes().remove(name);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        return getMongoEntity().getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(getMongoEntity().getAttributes());
-        return copy;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
-        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
-            ProtocolMapperModel mapping = new ProtocolMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setProtocol(entity.getProtocol());
-            mapping.setProtocolMapper(entity.getProtocolMapper());
-            mapping.setConsentRequired(entity.isConsentRequired());
-            mapping.setConsentText(entity.getConsentText());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            result.add(mapping);
-        }
-        return result;
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        ProtocolMapperEntity entity = new ProtocolMapperEntity();
-        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
-        entity.setId(id);
-        entity.setProtocol(model.getProtocol());
-        entity.setName(model.getName());
-        entity.setProtocolMapper(model.getProtocolMapper());
-        entity.setConfig(model.getConfig());
-        entity.setConsentRequired(model.isConsentRequired());
-        entity.setConsentText(model.getConsentText());
-        getMongoEntity().getProtocolMappers().add(entity);
-        updateMongoEntity();
-        return entityToModel(entity);
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
-            if (entity.getId().equals(mapping.getId())) {
-                session.users().preRemove(this, mapping);
-
-                getMongoEntity().getProtocolMappers().remove(entity);
-                updateMongoEntity();
-                break;
-            }
-        }
-
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) {
-        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
-        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
-            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId());
-        entity.setProtocolMapper(mapping.getProtocolMapper());
-        entity.setConsentRequired(mapping.isConsentRequired());
-        entity.setConsentText(mapping.getConsentText());
-        if (entity.getConfig() != null) {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        } else {
-            entity.setConfig(mapping.getConfig());
-        }
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        ProtocolMapperEntity entity = getProtocolMapperyEntityById(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
-        ProtocolMapperModel mapping = new ProtocolMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setProtocol(entity.getProtocol());
-        mapping.setProtocolMapper(entity.getProtocolMapper());
-        mapping.setConsentRequired(entity.isConsentRequired());
-        mapping.setConsentText(entity.getConsentText());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-
-    @Override
-    public boolean isSurrogateAuthRequired() {
-        return getMongoEntity().isSurrogateAuthRequired();
-    }
-
-    @Override
-    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
-        getMongoEntity().setSurrogateAuthRequired(surrogateAuthRequired);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getManagementUrl() {
-        return getMongoEntity().getManagementUrl();
-    }
-
-    @Override
-    public void setManagementUrl(String url) {
-        getMongoEntity().setManagementUrl(url);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void setBaseUrl(String url) {
-        getMongoEntity().setBaseUrl(url);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getBaseUrl() {
-        return getMongoEntity().getBaseUrl();
-    }
-
-    @Override
-    public boolean isBearerOnly() {
-        return getMongoEntity().isBearerOnly();
-    }
-
-    @Override
-    public void setBearerOnly(boolean only) {
-        getMongoEntity().setBearerOnly(only);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isConsentRequired() {
-        return getMongoEntity().isConsentRequired();
-    }
-
-    @Override
-    public void setConsentRequired(boolean consentRequired) {
-        getMongoEntity().setConsentRequired(consentRequired);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isDirectGrantsOnly() {
-        return getMongoEntity().isDirectGrantsOnly();
-    }
-
-    @Override
-    public void setDirectGrantsOnly(boolean flag) {
-        getMongoEntity().setDirectGrantsOnly(flag);
-        updateMongoEntity();
-    }
-
-    @Override
-    public RoleAdapter getRole(String name) {
-        DBObject query = new QueryBuilder()
-                .and("name").is(name)
-                .and("clientId").is(getId())
-                .get();
-        MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
-        if (role == null) {
-            return null;
-        } else {
-            return new RoleAdapter(session, getRealm(), role, invocationContext);
-        }
-    }
-
-    @Override
-    public RoleAdapter addRole(String name) {
-        return this.addRole(null, name);
-    }
-
-    @Override
-    public RoleAdapter addRole(String id, String name) {
-        MongoRoleEntity roleEntity = new MongoRoleEntity();
-        roleEntity.setId(id);
-        roleEntity.setName(name);
-        roleEntity.setClientId(getId());
-
-        getMongoStore().insertEntity(roleEntity, invocationContext);
-
-        return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext);
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        session.users().preRemove(getRealm(), role);
-        return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        DBObject query = new QueryBuilder()
-                .and("clientId").is(getId())
-                .get();
-        List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
-
-        Set<RoleModel> result = new HashSet<RoleModel>();
-        for (MongoRoleEntity role : roles) {
-            result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
-        }
-
-        return result;
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-
-        roles = getRoles();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
-        Set<RoleModel> result = new HashSet<RoleModel>();
-        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
-
-        for (MongoRoleEntity role : roles) {
-            if (getId().equals(role.getClientId())) {
-                result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        return getMongoEntity().getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            addRole(name);
-        }
-
-        getMongoStore().pushItemToList(getMongoEntity(), "defaultRoles", name, true, invocationContext);
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        List<String> roleNames = new ArrayList<String>();
-        for (String roleName : defaultRoles) {
-            RoleModel role = getRole(roleName);
-            if (role == null) {
-                addRole(roleName);
-            }
-
-            roleNames.add(roleName);
-        }
-
-        getMongoEntity().setDefaultRoles(roleNames);
-        updateMongoEntity();
-    }
-
-    @Override
-    public int getNodeReRegistrationTimeout() {
-        return getMongoEntity().getNodeReRegistrationTimeout();
-    }
-
-    @Override
-    public void setNodeReRegistrationTimeout(int timeout) {
-        getMongoEntity().setNodeReRegistrationTimeout(timeout);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Map<String, Integer> getRegisteredNodes() {
-        return getMongoEntity().getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(getMongoEntity().getRegisteredNodes());
-    }
-
-    @Override
-    public void registerNode(String nodeHost, int registrationTime) {
-        MongoClientEntity entity = getMongoEntity();
-        if (entity.getRegisteredNodes() == null) {
-            entity.setRegisteredNodes(new HashMap<String, Integer>());
-        }
-
-        entity.getRegisteredNodes().put(nodeHost, registrationTime);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void unregisterNode(String nodeHost) {
-        MongoClientEntity entity = getMongoEntity();
-        if (entity.getRegisteredNodes() == null) return;
-
-        entity.getRegisteredNodes().remove(nodeHost);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof ClientModel)) return false;
-
-        ClientModel that = (ClientModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.entities.ProtocolMapperEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.mongo.utils.MongoModelUtils;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> implements ClientModel {
+
+    protected final MongoClientEntity clientEntity;
+    private final RealmModel realm;
+    protected  KeycloakSession session;
+
+    public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity clientEntity, MongoStoreInvocationContext invContext) {
+        super(invContext);
+        this.session = session;
+        this.realm = realm;
+        this.clientEntity = clientEntity;
+    }
+
+    @Override
+    public MongoClientEntity getMongoEntity() {
+        return clientEntity;
+    }
+
+    @Override
+    public void updateClient() {
+        updateMongoEntity();
+    }
+
+
+    @Override
+    public String getId() {
+        return getMongoEntity().getId();
+    }
+
+    @Override
+    public String getClientId() {
+        return getMongoEntity().getClientId();
+    }
+
+    @Override
+    public String getName() {
+        return getMongoEntity().getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getMongoEntity().setName(name);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        getMongoEntity().setClientId(clientId);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Set<String> getWebOrigins() {
+        Set<String> result = new HashSet<String>();
+        if (getMongoEntity().getWebOrigins() != null) {
+            result.addAll(getMongoEntity().getWebOrigins());
+        }
+        return result;
+    }
+
+    @Override
+    public void setWebOrigins(Set<String> webOrigins) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(webOrigins);
+        getMongoEntity().setWebOrigins(result);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void addWebOrigin(String webOrigin) {
+        getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext);
+    }
+
+    @Override
+    public void removeWebOrigin(String webOrigin) {
+        getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext);
+    }
+
+    @Override
+    public Set<String> getRedirectUris() {
+        Set<String> result = new HashSet<String>();
+        if (getMongoEntity().getRedirectUris() != null) {
+            result.addAll(getMongoEntity().getRedirectUris());
+        }
+        return result;
+    }
+
+    @Override
+    public void setRedirectUris(Set<String> redirectUris) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(redirectUris);
+        getMongoEntity().setRedirectUris(result);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void addRedirectUri(String redirectUri) {
+        getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext);
+    }
+
+    @Override
+    public void removeRedirectUri(String redirectUri) {
+        getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return getMongoEntity().isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        getMongoEntity().setEnabled(enabled);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean validateSecret(String secret) {
+        return secret.equals(getMongoEntity().getSecret());
+    }
+
+    @Override
+    public String getSecret() {
+        return getMongoEntity().getSecret();
+    }
+
+    @Override
+    public void setSecret(String secret) {
+        getMongoEntity().setSecret(secret);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isPublicClient() {
+        return getMongoEntity().isPublicClient();
+    }
+
+    @Override
+    public void setPublicClient(boolean flag) {
+        getMongoEntity().setPublicClient(flag);
+        updateMongoEntity();
+    }
+
+
+    @Override
+    public boolean isFrontchannelLogout() {
+        return getMongoEntity().isFrontchannelLogout();
+    }
+
+    @Override
+    public void setFrontchannelLogout(boolean flag) {
+        getMongoEntity().setFrontchannelLogout(flag);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        return getMongoEntity().isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        getMongoEntity().setFullScopeAllowed(value);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public int getNotBefore() {
+        return getMongoEntity().getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        getMongoEntity().setNotBefore(notBefore);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings() {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext);
+
+        for (MongoRoleEntity role : roles) {
+            if (realm.getId().equals(role.getRealmId())) {
+                result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
+            } else {
+                // Likely applicationRole, but we don't have this application yet
+                result.add(new RoleAdapter(session, realm, role, invocationContext));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> allScopes = getScopeMappings();
+
+        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
+
+            if (realm.getId().equals(roleEntity.getRealmId())) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void addScopeMapping(RoleModel role) {
+        getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
+    }
+
+    @Override
+    public void deleteScopeMapping(RoleModel role) {
+        getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
+    }
+
+    @Override
+    public String getProtocol() {
+        return getMongoEntity().getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        getMongoEntity().setProtocol(protocol);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        getMongoEntity().getAttributes().put(name, value);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        getMongoEntity().getAttributes().remove(name);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return getMongoEntity().getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> copy = new HashMap<String, String>();
+        copy.putAll(getMongoEntity().getAttributes());
+        return copy;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setProtocol(entity.getProtocol());
+            mapping.setProtocolMapper(entity.getProtocolMapper());
+            mapping.setConsentRequired(entity.isConsentRequired());
+            mapping.setConsentText(entity.getConsentText());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            result.add(mapping);
+        }
+        return result;
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
+        String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
+        entity.setId(id);
+        entity.setProtocol(model.getProtocol());
+        entity.setName(model.getName());
+        entity.setProtocolMapper(model.getProtocolMapper());
+        entity.setConfig(model.getConfig());
+        entity.setConsentRequired(model.isConsentRequired());
+        entity.setConsentText(model.getConsentText());
+        getMongoEntity().getProtocolMappers().add(entity);
+        updateMongoEntity();
+        return entityToModel(entity);
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getId().equals(mapping.getId())) {
+                session.users().preRemove(this, mapping);
+
+                getMongoEntity().getProtocolMappers().remove(entity);
+                updateMongoEntity();
+                break;
+            }
+        }
+
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
+        entity.setConsentRequired(mapping.isConsentRequired());
+        entity.setConsentText(mapping.getConsentText());
+        if (entity.getConfig() != null) {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        } else {
+            entity.setConfig(mapping.getConfig());
+        }
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolMapperyEntityById(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
+        mapping.setConsentRequired(entity.isConsentRequired());
+        mapping.setConsentText(entity.getConsentText());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return getMongoEntity().isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        getMongoEntity().setSurrogateAuthRequired(surrogateAuthRequired);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return getMongoEntity().getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        getMongoEntity().setManagementUrl(url);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        getMongoEntity().setBaseUrl(url);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return getMongoEntity().getBaseUrl();
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return getMongoEntity().isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        getMongoEntity().setBearerOnly(only);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return getMongoEntity().isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        getMongoEntity().setConsentRequired(consentRequired);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return getMongoEntity().isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        getMongoEntity().setDirectGrantsOnly(flag);
+        updateMongoEntity();
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        DBObject query = new QueryBuilder()
+                .and("name").is(name)
+                .and("clientId").is(getId())
+                .get();
+        MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
+        if (role == null) {
+            return null;
+        } else {
+            return new RoleAdapter(session, getRealm(), role, invocationContext);
+        }
+    }
+
+    @Override
+    public RoleAdapter addRole(String name) {
+        return this.addRole(null, name);
+    }
+
+    @Override
+    public RoleAdapter addRole(String id, String name) {
+        MongoRoleEntity roleEntity = new MongoRoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setClientId(getId());
+
+        getMongoStore().insertEntity(roleEntity, invocationContext);
+
+        return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        session.users().preRemove(getRealm(), role);
+        return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        DBObject query = new QueryBuilder()
+                .and("clientId").is(getId())
+                .get();
+        List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
+
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        for (MongoRoleEntity role : roles) {
+            result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
+        }
+
+        return result;
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
+
+        for (MongoRoleEntity role : roles) {
+            if (getId().equals(role.getClientId())) {
+                result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return getMongoEntity().getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        getMongoStore().pushItemToList(getMongoEntity(), "defaultRoles", name, true, invocationContext);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        getMongoEntity().setDefaultRoles(roleNames);
+        updateMongoEntity();
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return getMongoEntity().getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        getMongoEntity().setNodeReRegistrationTimeout(timeout);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return getMongoEntity().getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(getMongoEntity().getRegisteredNodes());
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        MongoClientEntity entity = getMongoEntity();
+        if (entity.getRegisteredNodes() == null) {
+            entity.setRegisteredNodes(new HashMap<String, Integer>());
+        }
+
+        entity.getRegisteredNodes().put(nodeHost, registrationTime);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        MongoClientEntity entity = getMongoEntity();
+        if (entity.getRegisteredNodes() == null) return;
+
+        entity.getRegisteredNodes().remove(nodeHost);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MigrationModelAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MigrationModelAdapter.java
index 3e06af6..898b0e3 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MigrationModelAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MigrationModelAdapter.java
@@ -1,57 +1,57 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.entities.ProtocolMapperEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.mongo.utils.MongoModelUtils;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MigrationModelAdapter extends AbstractMongoAdapter<MongoMigrationModelEntity> implements MigrationModel {
-
-    protected final MongoMigrationModelEntity entity;
-
-    public MigrationModelAdapter(KeycloakSession session, MongoMigrationModelEntity entity, MongoStoreInvocationContext invContext) {
-        super(invContext);
-        this.entity = entity;
-    }
-
-    @Override
-    public MongoMigrationModelEntity getMongoEntity() {
-        return entity;
-    }
-
-    @Override
-    public String getStoredVersion() {
-        return getMongoEntity().getVersion();
-    }
-
-    @Override
-    public void setStoredVersion(String version) {
-        getMongoEntity().setVersion(version);
-        updateMongoEntity();
-
-    }
-
-
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.entities.ProtocolMapperEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.mongo.utils.MongoModelUtils;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MigrationModelAdapter extends AbstractMongoAdapter<MongoMigrationModelEntity> implements MigrationModel {
+
+    protected final MongoMigrationModelEntity entity;
+
+    public MigrationModelAdapter(KeycloakSession session, MongoMigrationModelEntity entity, MongoStoreInvocationContext invContext) {
+        super(invContext);
+        this.entity = entity;
+    }
+
+    @Override
+    public MongoMigrationModelEntity getMongoEntity() {
+        return entity;
+    }
+
+    @Override
+    public String getStoredVersion() {
+        return getMongoEntity().getVersion();
+    }
+
+    @Override
+    public void setStoredVersion(String version) {
+        getMongoEntity().setVersion(version);
+        updateMongoEntity();
+
+    }
+
+
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
index 1de862c..a840261 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
@@ -1,136 +1,136 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.MongoStore;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoRealmProvider implements RealmProvider {
-
-    private final MongoStoreInvocationContext invocationContext;
-    private final KeycloakSession session;
-
-    public MongoRealmProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext) {
-        this.session = session;
-        this.invocationContext = invocationContext;
-    }
-
-    @Override
-    public void close() {
-        // TODO
-    }
-
-    @Override
-    public MigrationModel getMigrationModel() {
-        MongoMigrationModelEntity entity = getMongoStore().loadEntity(MongoMigrationModelEntity.class, MongoMigrationModelEntity.MIGRATION_MODEL_ID, invocationContext);
-        if (entity == null) {
-            entity = new MongoMigrationModelEntity();
-            getMongoStore().insertEntity(entity, invocationContext);
-        }
-        return new MigrationModelAdapter(session, entity, invocationContext);
-    }
-
-    @Override
-    public RealmModel createRealm(String name) {
-        return createRealm(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RealmModel createRealm(String id, String name) {
-        MongoRealmEntity newRealm = new MongoRealmEntity();
-        newRealm.setId(id);
-        newRealm.setName(name);
-
-        getMongoStore().insertEntity(newRealm, invocationContext);
-
-        final RealmModel model = new RealmAdapter(session, newRealm, invocationContext);
-        session.getKeycloakSessionFactory().publish(new RealmModel.RealmCreationEvent() {
-            @Override
-            public RealmModel getCreatedRealm() {
-                return model;
-            }
-        });
-        return model;
-    }
-
-    @Override
-    public RealmModel getRealm(String id) {
-        MongoRealmEntity realmEntity = getMongoStore().loadEntity(MongoRealmEntity.class, id, invocationContext);
-        return realmEntity != null ? new RealmAdapter(session, realmEntity, invocationContext) : null;
-    }
-
-    @Override
-    public List<RealmModel> getRealms() {
-        DBObject query = new BasicDBObject();
-        List<MongoRealmEntity> realms = getMongoStore().loadEntities(MongoRealmEntity.class, query, invocationContext);
-
-        List<RealmModel> results = new ArrayList<RealmModel>();
-        for (MongoRealmEntity realmEntity : realms) {
-            results.add(new RealmAdapter(session, realmEntity, invocationContext));
-        }
-        return results;
-    }
-
-    @Override
-    public RealmModel getRealmByName(String name) {
-        DBObject query = new QueryBuilder()
-                .and("name").is(name)
-                .get();
-        MongoRealmEntity realm = getMongoStore().loadSingleEntity(MongoRealmEntity.class, query, invocationContext);
-
-        if (realm == null) return null;
-        return new RealmAdapter(session, realm, invocationContext);
-    }
-
-    @Override
-    public boolean removeRealm(String id) {
-        RealmModel realm = getRealm(id);
-        if (realm == null) return false;
-        session.users().preRemove(realm);
-        return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
-    }
-
-    protected MongoStore getMongoStore() {
-        return invocationContext.getMongoStore();
-    }
-
-    @Override
-    public RoleModel getRoleById(String id, RealmModel realm) {
-        MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext);
-        if (role == null) return null;
-        if (role.getRealmId() != null && !role.getRealmId().equals(realm.getId())) return null;
-        if (role.getClientId() != null && realm.getClientById(role.getClientId()) == null) return null;
-        return new RoleAdapter(session, realm, role, null, invocationContext);
-    }
-
-    @Override
-    public ClientModel getClientById(String id, RealmModel realm) {
-        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, id, invocationContext);
-
-        // Check if application belongs to this realm
-        if (appData == null || !realm.getId().equals(appData.getRealmId())) {
-            return null;
-        }
-
-        return new ClientAdapter(session, realm, appData, invocationContext);
-    }
-
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.MongoStore;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoRealmProvider implements RealmProvider {
+
+    private final MongoStoreInvocationContext invocationContext;
+    private final KeycloakSession session;
+
+    public MongoRealmProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext) {
+        this.session = session;
+        this.invocationContext = invocationContext;
+    }
+
+    @Override
+    public void close() {
+        // TODO
+    }
+
+    @Override
+    public MigrationModel getMigrationModel() {
+        MongoMigrationModelEntity entity = getMongoStore().loadEntity(MongoMigrationModelEntity.class, MongoMigrationModelEntity.MIGRATION_MODEL_ID, invocationContext);
+        if (entity == null) {
+            entity = new MongoMigrationModelEntity();
+            getMongoStore().insertEntity(entity, invocationContext);
+        }
+        return new MigrationModelAdapter(session, entity, invocationContext);
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        return createRealm(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        MongoRealmEntity newRealm = new MongoRealmEntity();
+        newRealm.setId(id);
+        newRealm.setName(name);
+
+        getMongoStore().insertEntity(newRealm, invocationContext);
+
+        final RealmModel model = new RealmAdapter(session, newRealm, invocationContext);
+        session.getKeycloakSessionFactory().publish(new RealmModel.RealmCreationEvent() {
+            @Override
+            public RealmModel getCreatedRealm() {
+                return model;
+            }
+        });
+        return model;
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        MongoRealmEntity realmEntity = getMongoStore().loadEntity(MongoRealmEntity.class, id, invocationContext);
+        return realmEntity != null ? new RealmAdapter(session, realmEntity, invocationContext) : null;
+    }
+
+    @Override
+    public List<RealmModel> getRealms() {
+        DBObject query = new BasicDBObject();
+        List<MongoRealmEntity> realms = getMongoStore().loadEntities(MongoRealmEntity.class, query, invocationContext);
+
+        List<RealmModel> results = new ArrayList<RealmModel>();
+        for (MongoRealmEntity realmEntity : realms) {
+            results.add(new RealmAdapter(session, realmEntity, invocationContext));
+        }
+        return results;
+    }
+
+    @Override
+    public RealmModel getRealmByName(String name) {
+        DBObject query = new QueryBuilder()
+                .and("name").is(name)
+                .get();
+        MongoRealmEntity realm = getMongoStore().loadSingleEntity(MongoRealmEntity.class, query, invocationContext);
+
+        if (realm == null) return null;
+        return new RealmAdapter(session, realm, invocationContext);
+    }
+
+    @Override
+    public boolean removeRealm(String id) {
+        RealmModel realm = getRealm(id);
+        if (realm == null) return false;
+        session.users().preRemove(realm);
+        return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
+    }
+
+    protected MongoStore getMongoStore() {
+        return invocationContext.getMongoStore();
+    }
+
+    @Override
+    public RoleModel getRoleById(String id, RealmModel realm) {
+        MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext);
+        if (role == null) return null;
+        if (role.getRealmId() != null && !role.getRealmId().equals(realm.getId())) return null;
+        if (role.getClientId() != null && realm.getClientById(role.getClientId()) == null) return null;
+        return new RoleAdapter(session, realm, role, null, invocationContext);
+    }
+
+    @Override
+    public ClientModel getClientById(String id, RealmModel realm) {
+        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, id, invocationContext);
+
+        // Check if application belongs to this realm
+        if (appData == null || !realm.getId().equals(appData.getRealmId())) {
+            return null;
+        }
+
+        return new ClientAdapter(session, realm, appData, invocationContext);
+    }
+
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
index 145d598..a37bfad 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProviderFactory.java
@@ -1,45 +1,45 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.connections.mongo.MongoConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RealmProviderFactory;
-
-/**
- * KeycloakSessionFactory implementation based on MongoDB
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoRealmProviderFactory implements RealmProviderFactory {
-    protected static final Logger logger = Logger.getLogger(MongoRealmProviderFactory.class);
-
-
-    @Override
-    public String getId() {
-        return "mongo";
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public RealmProvider create(KeycloakSession session) {
-        MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
-        return new MongoRealmProvider(session, connection.getInvocationContext());
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
-
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.connections.mongo.MongoConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RealmProviderFactory;
+
+/**
+ * KeycloakSessionFactory implementation based on MongoDB
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoRealmProviderFactory implements RealmProviderFactory {
+    protected static final Logger logger = Logger.getLogger(MongoRealmProviderFactory.class);
+
+
+    @Override
+    public String getId() {
+        return "mongo";
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public RealmProvider create(KeycloakSession session) {
+        MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
+        return new MongoRealmProvider(session, connection.getInvocationContext());
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
+
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 efee051..55ac78b 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
@@ -1,421 +1,421 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-
-import org.keycloak.connections.mongo.api.MongoStore;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.entities.FederatedIdentityEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
-import org.keycloak.models.utils.CredentialValidation;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoUserProvider implements UserProvider {
-
-    private final MongoStoreInvocationContext invocationContext;
-    private final KeycloakSession session;
-
-    public MongoUserProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext) {
-        this.session = session;
-        this.invocationContext = invocationContext;
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext);
-
-        // Check that it's user from this realm
-        if (user == null || !realm.getId().equals(user.getRealmId())) {
-            return null;
-        } else {
-            return new UserAdapter(session, realm, user, invocationContext);
-        }
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        DBObject query = new QueryBuilder()
-                .and("username").is(username.toLowerCase())
-                .and("realmId").is(realm.getId())
-                .get();
-        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
-
-        if (user == null) {
-            return null;
-        } else {
-            return new UserAdapter(session, realm, user, invocationContext);
-        }
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        DBObject query = new QueryBuilder()
-                .and("email").is(email.toLowerCase())
-                .and("realmId").is(realm.getId())
-                .get();
-        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
-
-        if (user == null) {
-            return null;
-        } else {
-            return new UserAdapter(session, realm, user, invocationContext);
-        }
-    }
-
-    protected MongoStore getMongoStore() {
-        return invocationContext.getMongoStore();
-    }
-
-    @Override
-    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
-        DBObject query = new QueryBuilder()
-                .and("federatedIdentities.identityProvider").is(socialLink.getIdentityProvider())
-                .and("federatedIdentities.userId").is(socialLink.getUserId())
-                .and("realmId").is(realm.getId())
-                .get();
-        MongoUserEntity userEntity = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
-        return userEntity == null ? null : new UserAdapter(session, realm, userEntity, invocationContext);
-    }
-
-    protected List<UserModel> convertUserEntities(RealmModel realm, List<MongoUserEntity> userEntities) {
-        List<UserModel> userModels = new ArrayList<UserModel>();
-        for (MongoUserEntity user : userEntities) {
-            userModels.add(new UserAdapter(session, realm, user, invocationContext));
-        }
-        return userModels;
-    }
-
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return getUsers(realm, -1, -1);
-    }
-
-    @Override
-    public int getUsersCount(RealmModel realm) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(realm.getId())
-                .get();
-        return getMongoStore().countEntities(MongoUserEntity.class, query, invocationContext);
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(realm.getId())
-                .get();
-        DBObject sort = new BasicDBObject("username", 1);
-        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, query, sort, firstResult, maxResults, invocationContext);
-        return convertUserEntities(realm, users);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return searchForUser(search, realm, -1, -1);
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
-        search = search.trim();
-        Pattern caseInsensitivePattern = Pattern.compile("(?i:" + search + ")");
-
-        QueryBuilder nameBuilder;
-        int spaceInd = search.lastIndexOf(" ");
-
-        // Case when we have search string like "ohn Bow". Then firstName must end with "ohn" AND lastName must start with "bow" (everything case-insensitive)
-        if (spaceInd != -1) {
-            String firstName = search.substring(0, spaceInd);
-            String lastName = search.substring(spaceInd + 1);
-            Pattern firstNamePattern = Pattern.compile("(?i:" + firstName + "$)");
-            Pattern lastNamePattern = Pattern.compile("(?i:^" + lastName + ")");
-            nameBuilder = new QueryBuilder().and(
-                    new QueryBuilder().put("firstName").regex(firstNamePattern).get(),
-                    new QueryBuilder().put("lastName").regex(lastNamePattern).get()
-            );
-        } else {
-            // Case when we have search without spaces like "foo". The firstName OR lastName could be "foo" (everything case-insensitive)
-            nameBuilder = new QueryBuilder().or(
-                    new QueryBuilder().put("firstName").regex(caseInsensitivePattern).get(),
-                    new QueryBuilder().put("lastName").regex(caseInsensitivePattern).get()
-            );
-        }
-
-        QueryBuilder builder = new QueryBuilder().and(
-                new QueryBuilder().and("realmId").is(realm.getId()).get(),
-                new QueryBuilder().or(
-                        new QueryBuilder().put("username").regex(caseInsensitivePattern).get(),
-                        new QueryBuilder().put("email").regex(caseInsensitivePattern).get(),
-                        nameBuilder.get()
-
-                ).get()
-        );
-
-        DBObject sort = new BasicDBObject("username", 1);
-
-        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, builder.get(), sort, firstResult, maxResults, invocationContext);
-        return convertUserEntities(realm, users);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return searchForUserByAttributes(attributes, realm, -1, -1);
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
-        QueryBuilder queryBuilder = new QueryBuilder()
-                .and("realmId").is(realm.getId());
-
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            if (entry.getKey().equalsIgnoreCase(UserModel.USERNAME)) {
-                queryBuilder.and(UserModel.USERNAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
-                queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
-
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
-                queryBuilder.and(UserModel.LAST_NAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
-
-            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
-                queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
-            }
-        }
-
-        DBObject sort = new BasicDBObject("username", 1);
-
-        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), sort, firstResult, maxResults, invocationContext);
-        return convertUserEntities(realm, users);
-    }
-
-    @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel userModel, RealmModel realm) {
-        UserModel user = getUserById(userModel.getId(), realm);
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
-
-        if (linkEntities == null) {
-            return Collections.EMPTY_SET;
-        }
-
-        Set<FederatedIdentityModel> result = new HashSet<FederatedIdentityModel>();
-        for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
-            FederatedIdentityModel model = new FederatedIdentityModel(federatedIdentityEntity.getIdentityProvider(),
-                    federatedIdentityEntity.getUserId(), federatedIdentityEntity.getUserName(), federatedIdentityEntity.getToken());
-            result.add(model);
-        }
-        return result;
-    }
-
-    @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        user = getUserById(user.getId(), realm);
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
-
-        return federatedIdentityEntity != null ? new FederatedIdentityModel(federatedIdentityEntity.getIdentityProvider(), federatedIdentityEntity.getUserId(),
-                federatedIdentityEntity.getUserName(), federatedIdentityEntity.getToken()) : null;
-    }
-
-    @Override
-    public UserAdapter addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
-        UserAdapter userModel = addUserEntity(realm, id, username.toLowerCase());
-
-        if (addDefaultRoles) {
-            for (String r : realm.getDefaultRoles()) {
-                userModel.grantRole(realm.getRole(r));
-            }
-
-            for (ClientModel application : realm.getClients()) {
-                for (String r : application.getDefaultRoles()) {
-                    userModel.grantRole(application.getRole(r));
-                }
-            }
-        }
-
-        if (addDefaultRequiredActions) {
-            for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
-                if (r.isEnabled() && r.isDefaultAction()) {
-                    userModel.addRequiredAction(r.getAlias());
-                }
-            }
-        }
-
-
-        return userModel;
-    }
-
-    protected UserAdapter addUserEntity(RealmModel realm, String id, String username) {
-        MongoUserEntity userEntity = new MongoUserEntity();
-        userEntity.setId(id);
-        userEntity.setUsername(username);
-        userEntity.setCreatedTimestamp(System.currentTimeMillis());
-        // Compatibility with JPA model, which has user disabled by default
-        // userEntity.setEnabled(true);
-        userEntity.setRealmId(realm.getId());
-
-        getMongoStore().insertEntity(userEntity, invocationContext);
-        return new UserAdapter(session, realm, userEntity, invocationContext);
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        return getMongoStore().removeEntity(MongoUserEntity.class, user.getId(), invocationContext);
-    }
-
-
-    @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel identity) {
-        user = getUserById(user.getId(), realm);
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        FederatedIdentityEntity federatedIdentityEntity = new FederatedIdentityEntity();
-        federatedIdentityEntity.setIdentityProvider(identity.getIdentityProvider());
-        federatedIdentityEntity.setUserId(identity.getUserId());
-        federatedIdentityEntity.setUserName(identity.getUserName().toLowerCase());
-        federatedIdentityEntity.setToken(identity.getToken());
-
-        getMongoStore().pushItemToList(userEntity, "federatedIdentities", federatedIdentityEntity, true, invocationContext);
-    }
-
-    @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        federatedUser = getUserById(federatedUser.getId(), realm);
-        MongoUserEntity userEntity = ((UserAdapter) federatedUser).getUser();
-        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, federatedIdentityModel.getIdentityProvider());
-
-        federatedIdentityEntity.setToken(federatedIdentityModel.getToken());
-    }
-
-    @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel userModel, String socialProvider) {
-        UserModel user = getUserById(userModel.getId(), realm);
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
-        if (federatedIdentityEntity == null) {
-            return false;
-        }
-        return getMongoStore().pullItemFromList(userEntity, "federatedIdentities", federatedIdentityEntity, invocationContext);
-    }
-
-    private FederatedIdentityEntity findFederatedIdentityLink(MongoUserEntity userEntity, String identityProvider) {
-        List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
-        if (linkEntities == null) {
-            return null;
-        }
-
-        for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
-            if (federatedIdentityEntity.getIdentityProvider().equals(identityProvider)) {
-                return federatedIdentityEntity;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public UserModel addUser(RealmModel realm, String username) {
-        return this.addUser(realm, null, username, true, true);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(realm.getId())
-                .get();
-        getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
-        // Remove all users linked with federationProvider and their consents
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(realm.getId())
-                .and("federationLink").is(link.getId())
-                .get();
-        getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
-
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, ClientModel client) {
-        // Remove all role mappings and consents mapped to all roles of this client
-        for (RoleModel role : client.getRoles()) {
-            preRemove(realm, role);
-        }
-
-        // Finally remove all consents of this client
-        DBObject query = new QueryBuilder()
-                .and("clientId").is(client.getId())
-                .get();
-        getMongoStore().removeEntities(MongoUserConsentEntity.class, query, false, invocationContext);
-    }
-
-    @Override
-    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
-        // Remove this protocol mapper from all consents, which has it
-        DBObject query = new QueryBuilder()
-                .and("grantedProtocolMappers").is(protocolMapper.getId())
-                .get();
-        DBObject pull = new BasicDBObject("$pull", query);
-        getMongoStore().updateEntities(MongoUserConsentEntity.class, query, pull, invocationContext);
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-        // Remove this role from all users, which has it
-        DBObject query = new QueryBuilder()
-                .and("roleIds").is(role.getId())
-                .get();
-
-        DBObject pull = new BasicDBObject("$pull", query);
-        getMongoStore().updateEntities(MongoUserEntity.class, query, pull, invocationContext);
-
-        // Remove this role from all consents, which has it
-        query = new QueryBuilder()
-                .and("grantedRoles").is(role.getId())
-                .get();
-        pull = new BasicDBObject("$pull", query);
-        getMongoStore().updateEntities(MongoUserConsentEntity.class, query, pull, invocationContext);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        return CredentialValidation.validCredentials(realm, user, input);
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return CredentialValidation.validCredentials(realm, user, input);
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
-        // Not supported yet
-        return null;
-    }
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+
+import org.keycloak.connections.mongo.api.MongoStore;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.entities.FederatedIdentityEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
+import org.keycloak.models.utils.CredentialValidation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoUserProvider implements UserProvider {
+
+    private final MongoStoreInvocationContext invocationContext;
+    private final KeycloakSession session;
+
+    public MongoUserProvider(KeycloakSession session, MongoStoreInvocationContext invocationContext) {
+        this.session = session;
+        this.invocationContext = invocationContext;
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext);
+
+        // Check that it's user from this realm
+        if (user == null || !realm.getId().equals(user.getRealmId())) {
+            return null;
+        } else {
+            return new UserAdapter(session, realm, user, invocationContext);
+        }
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("username").is(username.toLowerCase())
+                .and("realmId").is(realm.getId())
+                .get();
+        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
+
+        if (user == null) {
+            return null;
+        } else {
+            return new UserAdapter(session, realm, user, invocationContext);
+        }
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("email").is(email.toLowerCase())
+                .and("realmId").is(realm.getId())
+                .get();
+        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
+
+        if (user == null) {
+            return null;
+        } else {
+            return new UserAdapter(session, realm, user, invocationContext);
+        }
+    }
+
+    protected MongoStore getMongoStore() {
+        return invocationContext.getMongoStore();
+    }
+
+    @Override
+    public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("federatedIdentities.identityProvider").is(socialLink.getIdentityProvider())
+                .and("federatedIdentities.userId").is(socialLink.getUserId())
+                .and("realmId").is(realm.getId())
+                .get();
+        MongoUserEntity userEntity = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
+        return userEntity == null ? null : new UserAdapter(session, realm, userEntity, invocationContext);
+    }
+
+    protected List<UserModel> convertUserEntities(RealmModel realm, List<MongoUserEntity> userEntities) {
+        List<UserModel> userModels = new ArrayList<UserModel>();
+        for (MongoUserEntity user : userEntities) {
+            userModels.add(new UserAdapter(session, realm, user, invocationContext));
+        }
+        return userModels;
+    }
+
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getUsers(realm, -1, -1);
+    }
+
+    @Override
+    public int getUsersCount(RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .get();
+        return getMongoStore().countEntities(MongoUserEntity.class, query, invocationContext);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .get();
+        DBObject sort = new BasicDBObject("username", 1);
+        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, query, sort, firstResult, maxResults, invocationContext);
+        return convertUserEntities(realm, users);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return searchForUser(search, realm, -1, -1);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
+        search = search.trim();
+        Pattern caseInsensitivePattern = Pattern.compile("(?i:" + search + ")");
+
+        QueryBuilder nameBuilder;
+        int spaceInd = search.lastIndexOf(" ");
+
+        // Case when we have search string like "ohn Bow". Then firstName must end with "ohn" AND lastName must start with "bow" (everything case-insensitive)
+        if (spaceInd != -1) {
+            String firstName = search.substring(0, spaceInd);
+            String lastName = search.substring(spaceInd + 1);
+            Pattern firstNamePattern = Pattern.compile("(?i:" + firstName + "$)");
+            Pattern lastNamePattern = Pattern.compile("(?i:^" + lastName + ")");
+            nameBuilder = new QueryBuilder().and(
+                    new QueryBuilder().put("firstName").regex(firstNamePattern).get(),
+                    new QueryBuilder().put("lastName").regex(lastNamePattern).get()
+            );
+        } else {
+            // Case when we have search without spaces like "foo". The firstName OR lastName could be "foo" (everything case-insensitive)
+            nameBuilder = new QueryBuilder().or(
+                    new QueryBuilder().put("firstName").regex(caseInsensitivePattern).get(),
+                    new QueryBuilder().put("lastName").regex(caseInsensitivePattern).get()
+            );
+        }
+
+        QueryBuilder builder = new QueryBuilder().and(
+                new QueryBuilder().and("realmId").is(realm.getId()).get(),
+                new QueryBuilder().or(
+                        new QueryBuilder().put("username").regex(caseInsensitivePattern).get(),
+                        new QueryBuilder().put("email").regex(caseInsensitivePattern).get(),
+                        nameBuilder.get()
+
+                ).get()
+        );
+
+        DBObject sort = new BasicDBObject("username", 1);
+
+        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, builder.get(), sort, firstResult, maxResults, invocationContext);
+        return convertUserEntities(realm, users);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return searchForUserByAttributes(attributes, realm, -1, -1);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
+        QueryBuilder queryBuilder = new QueryBuilder()
+                .and("realmId").is(realm.getId());
+
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            if (entry.getKey().equalsIgnoreCase(UserModel.USERNAME)) {
+                queryBuilder.and(UserModel.USERNAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
+                queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
+
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
+                queryBuilder.and(UserModel.LAST_NAME).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
+
+            } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
+                queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile(".*" + entry.getValue() + ".*", Pattern.CASE_INSENSITIVE));
+            }
+        }
+
+        DBObject sort = new BasicDBObject("username", 1);
+
+        List<MongoUserEntity> users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), sort, firstResult, maxResults, invocationContext);
+        return convertUserEntities(realm, users);
+    }
+
+    @Override
+    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel userModel, RealmModel realm) {
+        UserModel user = getUserById(userModel.getId(), realm);
+        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
+        List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
+
+        if (linkEntities == null) {
+            return Collections.EMPTY_SET;
+        }
+
+        Set<FederatedIdentityModel> result = new HashSet<FederatedIdentityModel>();
+        for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
+            FederatedIdentityModel model = new FederatedIdentityModel(federatedIdentityEntity.getIdentityProvider(),
+                    federatedIdentityEntity.getUserId(), federatedIdentityEntity.getUserName(), federatedIdentityEntity.getToken());
+            result.add(model);
+        }
+        return result;
+    }
+
+    @Override
+    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
+        user = getUserById(user.getId(), realm);
+        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
+        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
+
+        return federatedIdentityEntity != null ? new FederatedIdentityModel(federatedIdentityEntity.getIdentityProvider(), federatedIdentityEntity.getUserId(),
+                federatedIdentityEntity.getUserName(), federatedIdentityEntity.getToken()) : null;
+    }
+
+    @Override
+    public UserAdapter addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
+        UserAdapter userModel = addUserEntity(realm, id, username.toLowerCase());
+
+        if (addDefaultRoles) {
+            for (String r : realm.getDefaultRoles()) {
+                userModel.grantRole(realm.getRole(r));
+            }
+
+            for (ClientModel application : realm.getClients()) {
+                for (String r : application.getDefaultRoles()) {
+                    userModel.grantRole(application.getRole(r));
+                }
+            }
+        }
+
+        if (addDefaultRequiredActions) {
+            for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
+                if (r.isEnabled() && r.isDefaultAction()) {
+                    userModel.addRequiredAction(r.getAlias());
+                }
+            }
+        }
+
+
+        return userModel;
+    }
+
+    protected UserAdapter addUserEntity(RealmModel realm, String id, String username) {
+        MongoUserEntity userEntity = new MongoUserEntity();
+        userEntity.setId(id);
+        userEntity.setUsername(username);
+        userEntity.setCreatedTimestamp(System.currentTimeMillis());
+        // Compatibility with JPA model, which has user disabled by default
+        // userEntity.setEnabled(true);
+        userEntity.setRealmId(realm.getId());
+
+        getMongoStore().insertEntity(userEntity, invocationContext);
+        return new UserAdapter(session, realm, userEntity, invocationContext);
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        return getMongoStore().removeEntity(MongoUserEntity.class, user.getId(), invocationContext);
+    }
+
+
+    @Override
+    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel identity) {
+        user = getUserById(user.getId(), realm);
+        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
+        FederatedIdentityEntity federatedIdentityEntity = new FederatedIdentityEntity();
+        federatedIdentityEntity.setIdentityProvider(identity.getIdentityProvider());
+        federatedIdentityEntity.setUserId(identity.getUserId());
+        federatedIdentityEntity.setUserName(identity.getUserName().toLowerCase());
+        federatedIdentityEntity.setToken(identity.getToken());
+
+        getMongoStore().pushItemToList(userEntity, "federatedIdentities", federatedIdentityEntity, true, invocationContext);
+    }
+
+    @Override
+    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+        federatedUser = getUserById(federatedUser.getId(), realm);
+        MongoUserEntity userEntity = ((UserAdapter) federatedUser).getUser();
+        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, federatedIdentityModel.getIdentityProvider());
+
+        federatedIdentityEntity.setToken(federatedIdentityModel.getToken());
+    }
+
+    @Override
+    public boolean removeFederatedIdentity(RealmModel realm, UserModel userModel, String socialProvider) {
+        UserModel user = getUserById(userModel.getId(), realm);
+        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
+        FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
+        if (federatedIdentityEntity == null) {
+            return false;
+        }
+        return getMongoStore().pullItemFromList(userEntity, "federatedIdentities", federatedIdentityEntity, invocationContext);
+    }
+
+    private FederatedIdentityEntity findFederatedIdentityLink(MongoUserEntity userEntity, String identityProvider) {
+        List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
+        if (linkEntities == null) {
+            return null;
+        }
+
+        for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
+            if (federatedIdentityEntity.getIdentityProvider().equals(identityProvider)) {
+                return federatedIdentityEntity;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public UserModel addUser(RealmModel realm, String username) {
+        return this.addUser(realm, null, username, true, true);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .get();
+        getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, UserFederationProviderModel link) {
+        // Remove all users linked with federationProvider and their consents
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .and("federationLink").is(link.getId())
+                .get();
+        getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
+
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, ClientModel client) {
+        // Remove all role mappings and consents mapped to all roles of this client
+        for (RoleModel role : client.getRoles()) {
+            preRemove(realm, role);
+        }
+
+        // Finally remove all consents of this client
+        DBObject query = new QueryBuilder()
+                .and("clientId").is(client.getId())
+                .get();
+        getMongoStore().removeEntities(MongoUserConsentEntity.class, query, false, invocationContext);
+    }
+
+    @Override
+    public void preRemove(ClientModel client, ProtocolMapperModel protocolMapper) {
+        // Remove this protocol mapper from all consents, which has it
+        DBObject query = new QueryBuilder()
+                .and("grantedProtocolMappers").is(protocolMapper.getId())
+                .get();
+        DBObject pull = new BasicDBObject("$pull", query);
+        getMongoStore().updateEntities(MongoUserConsentEntity.class, query, pull, invocationContext);
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+        // Remove this role from all users, which has it
+        DBObject query = new QueryBuilder()
+                .and("roleIds").is(role.getId())
+                .get();
+
+        DBObject pull = new BasicDBObject("$pull", query);
+        getMongoStore().updateEntities(MongoUserEntity.class, query, pull, invocationContext);
+
+        // Remove this role from all consents, which has it
+        query = new QueryBuilder()
+                .and("grantedRoles").is(role.getId())
+                .get();
+        pull = new BasicDBObject("$pull", query);
+        getMongoStore().updateEntities(MongoUserConsentEntity.class, query, pull, invocationContext);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        return CredentialValidation.validCredentials(realm, user, input);
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return CredentialValidation.validCredentials(realm, user, input);
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
+        // Not supported yet
+        return null;
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java
index 02e7635..3f5fde3 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java
@@ -1,44 +1,44 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.connections.mongo.MongoConnectionProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.UserProviderFactory;
-
-/**
- * KeycloakSessionFactory implementation based on MongoDB
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoUserProviderFactory implements UserProviderFactory {
-    protected static final Logger logger = Logger.getLogger(MongoUserProviderFactory.class);
-
-    @Override
-    public String getId() {
-        return "mongo";
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public UserProvider create(KeycloakSession session) {
-        MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
-        return new MongoUserProvider(session, connection.getInvocationContext());
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
-
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.connections.mongo.MongoConnectionProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.UserProviderFactory;
+
+/**
+ * KeycloakSessionFactory implementation based on MongoDB
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoUserProviderFactory implements UserProviderFactory {
+    protected static final Logger logger = Logger.getLogger(MongoUserProviderFactory.class);
+
+    @Override
+    public String getId() {
+        return "mongo";
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public UserProvider create(KeycloakSession session) {
+        MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
+        return new MongoUserProvider(session, connection.getInvocationContext());
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
+
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 2766ece..3a63687 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -1,1769 +1,1769 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationMapperEventImpl;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProviderCreationEventImpl;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.entities.AuthenticationExecutionEntity;
-import org.keycloak.models.entities.AuthenticationFlowEntity;
-import org.keycloak.models.entities.AuthenticatorConfigEntity;
-import org.keycloak.models.entities.IdentityProviderEntity;
-import org.keycloak.models.entities.IdentityProviderMapperEntity;
-import org.keycloak.models.entities.RequiredActionProviderEntity;
-import org.keycloak.models.entities.RequiredCredentialEntity;
-import org.keycloak.models.entities.UserFederationMapperEntity;
-import org.keycloak.models.entities.UserFederationProviderEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> implements RealmModel {
-
-    private final MongoRealmEntity realm;
-    private final RealmProvider model;
-
-    protected volatile transient PublicKey publicKey;
-    protected volatile transient PrivateKey privateKey;
-    protected volatile transient X509Certificate certificate;
-    protected volatile transient Key codeSecretKey;
-
-    private volatile transient PasswordPolicy passwordPolicy;
-    private volatile transient KeycloakSession session;
-
-    public RealmAdapter(KeycloakSession session, MongoRealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
-        super(invocationContext);
-        this.realm = realmEntity;
-        this.session = session;
-        this.model = session.realms();
-    }
-
-    @Override
-    public String getId() {
-        return realm.getId();
-    }
-
-    @Override
-    public String getName() {
-        return realm.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        realm.setName(name);
-        updateRealm();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return realm.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        realm.setEnabled(enabled);
-        updateRealm();
-    }
-
-    @Override
-    public SslRequired getSslRequired() {
-        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
-    }
-
-    @Override
-    public void setSslRequired(SslRequired sslRequired) {
-        realm.setSslRequired(sslRequired.name());
-        updateRealm();
-    }
-
-    @Override
-    public boolean isRegistrationAllowed() {
-        return realm.isRegistrationAllowed();
-    }
-
-    @Override
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        realm.setRegistrationAllowed(registrationAllowed);
-        updateRealm();
-    }
-
-    public boolean isRegistrationEmailAsUsername() {
-        return realm.isRegistrationEmailAsUsername();
-    }
-
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
-        updateRealm();
-    }
-
-    @Override
-    public boolean isRememberMe() {
-        return realm.isRememberMe();
-    }
-
-    @Override
-    public void setRememberMe(boolean rememberMe) {
-        realm.setRememberMe(rememberMe);
-        updateRealm();
-    }
-
-    @Override
-    public boolean isBruteForceProtected() {
-        return realm.isBruteForceProtected();
-    }
-
-    @Override
-    public void setBruteForceProtected(boolean value) {
-        realm.setBruteForceProtected(value);
-        updateRealm();
-    }
-
-    @Override
-    public int getMaxFailureWaitSeconds() {
-        return realm.getMaxFailureWaitSeconds();
-    }
-
-    @Override
-    public void setMaxFailureWaitSeconds(int val) {
-        realm.setMaxFailureWaitSeconds(val);
-        updateRealm();
-    }
-
-    @Override
-    public int getWaitIncrementSeconds() {
-        return realm.getWaitIncrementSeconds();
-    }
-
-    @Override
-    public void setWaitIncrementSeconds(int val) {
-        realm.setWaitIncrementSeconds(val);
-        updateRealm();
-    }
-
-    @Override
-    public long getQuickLoginCheckMilliSeconds() {
-        return realm.getQuickLoginCheckMilliSeconds();
-    }
-
-    @Override
-    public void setQuickLoginCheckMilliSeconds(long val) {
-        realm.setQuickLoginCheckMilliSeconds(val);
-        updateRealm();
-    }
-
-    @Override
-    public int getMinimumQuickLoginWaitSeconds() {
-        return realm.getMinimumQuickLoginWaitSeconds();
-    }
-
-    @Override
-    public void setMinimumQuickLoginWaitSeconds(int val) {
-        realm.setMinimumQuickLoginWaitSeconds(val);
-        updateRealm();
-    }
-
-
-    @Override
-    public int getMaxDeltaTimeSeconds() {
-        return realm.getMaxDeltaTimeSeconds();
-    }
-
-    @Override
-    public void setMaxDeltaTimeSeconds(int val) {
-        realm.setMaxDeltaTimeSeconds(val);
-        updateRealm();
-    }
-
-    @Override
-    public int getFailureFactor() {
-        return realm.getFailureFactor();
-    }
-
-    @Override
-    public void setFailureFactor(int failureFactor) {
-        realm.setFailureFactor(failureFactor);
-        updateRealm();
-    }
-
-
-    @Override
-    public boolean isVerifyEmail() {
-        return realm.isVerifyEmail();
-    }
-
-    @Override
-    public void setVerifyEmail(boolean verifyEmail) {
-        realm.setVerifyEmail(verifyEmail);
-        updateRealm();
-    }
-
-    @Override
-    public boolean isResetPasswordAllowed() {
-        return realm.isResetPasswordAllowed();
-    }
-
-    @Override
-    public void setResetPasswordAllowed(boolean resetPassword) {
-        realm.setResetPasswordAllowed(resetPassword);
-        updateRealm();
-    }
-
-    @Override
-    public boolean isEditUsernameAllowed() {
-        return realm.isEditUsernameAllowed();
-    }
-
-    @Override
-    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
-        realm.setEditUsernameAllowed(editUsernameAllowed);
-        updateRealm();
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        if (passwordPolicy == null) {
-            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
-        }
-        return passwordPolicy;
-    }
-
-    @Override
-    public void setPasswordPolicy(PasswordPolicy policy) {
-        this.passwordPolicy = policy;
-        realm.setPasswordPolicy(policy.toString());
-        updateRealm();
-    }
-
-    @Override
-    public int getNotBefore() {
-        return realm.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        realm.setNotBefore(notBefore);
-        updateRealm();
-    }
-
-
-    @Override
-    public int getSsoSessionIdleTimeout() {
-        return realm.getSsoSessionIdleTimeout();
-    }
-
-    @Override
-    public void setSsoSessionIdleTimeout(int seconds) {
-        realm.setSsoSessionIdleTimeout(seconds);
-        updateRealm();
-    }
-
-    @Override
-    public int getSsoSessionMaxLifespan() {
-        return realm.getSsoSessionMaxLifespan();
-    }
-
-    @Override
-    public void setSsoSessionMaxLifespan(int seconds) {
-        realm.setSsoSessionMaxLifespan(seconds);
-        updateRealm();
-    }
-
-    @Override
-    public int getAccessTokenLifespan() {
-        return realm.getAccessTokenLifespan();
-    }
-
-    @Override
-    public void setAccessTokenLifespan(int tokenLifespan) {
-        realm.setAccessTokenLifespan(tokenLifespan);
-        updateRealm();
-    }
-
-    @Override
-    public int getAccessCodeLifespan() {
-        return realm.getAccessCodeLifespan();
-    }
-
-    @Override
-    public void setAccessCodeLifespan(int accessCodeLifespan) {
-        realm.setAccessCodeLifespan(accessCodeLifespan);
-        updateRealm();
-    }
-
-    @Override
-    public int getAccessCodeLifespanUserAction() {
-        return realm.getAccessCodeLifespanUserAction();
-    }
-
-    @Override
-    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
-        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
-        updateRealm();
-    }
-
-    @Override
-    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
-        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
-        updateRealm();
-    }
-
-    @Override
-    public int getAccessCodeLifespanLogin() {
-        return realm.getAccessCodeLifespanLogin();
-    }
-
-    @Override
-    public String getPublicKeyPem() {
-        return realm.getPublicKeyPem();
-    }
-
-    @Override
-    public void setPublicKeyPem(String publicKeyPem) {
-        realm.setPublicKeyPem(publicKeyPem);
-        this.publicKey = null;
-        updateRealm();
-    }
-
-    @Override
-    public X509Certificate getCertificate() {
-        if (certificate != null) return certificate;
-        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
-        return certificate;
-    }
-
-    @Override
-    public void setCertificate(X509Certificate certificate) {
-        this.certificate = certificate;
-        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
-        setCertificatePem(certificatePem);
-
-    }
-
-    @Override
-    public String getCertificatePem() {
-        return realm.getCertificatePem();
-    }
-
-    @Override
-    public void setCertificatePem(String certificate) {
-        realm.setCertificatePem(certificate);
-
-    }
-
-
-    @Override
-    public String getPrivateKeyPem() {
-        return realm.getPrivateKeyPem();
-    }
-
-    @Override
-    public void setPrivateKeyPem(String privateKeyPem) {
-        realm.setPrivateKeyPem(privateKeyPem);
-        this.privateKey = null;
-        updateRealm();
-    }
-
-    @Override
-    public PublicKey getPublicKey() {
-        if (publicKey != null) return publicKey;
-        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
-        return publicKey;
-    }
-
-    @Override
-    public void setPublicKey(PublicKey publicKey) {
-        this.publicKey = publicKey;
-        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
-        setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public PrivateKey getPrivateKey() {
-        if (privateKey != null) return privateKey;
-        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
-        return privateKey;
-    }
-
-    @Override
-    public void setPrivateKey(PrivateKey privateKey) {
-        this.privateKey = privateKey;
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-        setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public String getCodeSecret() {
-        return realm.getCodeSecret();
-    }
-
-    @Override
-    public Key getCodeSecretKey() {
-        if (codeSecretKey == null) {
-            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
-        }
-        return codeSecretKey;
-    }
-
-    @Override
-    public void setCodeSecret(String codeSecret) {
-        realm.setCodeSecret(codeSecret);
-        updateRealm();
-    }
-
-    @Override
-    public String getLoginTheme() {
-        return realm.getLoginTheme();
-    }
-
-    @Override
-    public void setLoginTheme(String name) {
-        realm.setLoginTheme(name);
-        updateRealm();
-    }
-
-    @Override
-    public String getAccountTheme() {
-        return realm.getAccountTheme();
-    }
-
-    @Override
-    public void setAccountTheme(String name) {
-        realm.setAccountTheme(name);
-        updateRealm();
-    }
-
-    @Override
-    public String getAdminTheme() {
-        return realm.getAdminTheme();
-    }
-
-    @Override
-    public void setAdminTheme(String name) {
-        realm.setAdminTheme(name);
-        updateRealm();
-    }
-
-    @Override
-    public String getEmailTheme() {
-        return realm.getEmailTheme();
-    }
-
-    @Override
-    public void setEmailTheme(String name) {
-        realm.setEmailTheme(name);
-        updateRealm();
-    }
-
-    @Override
-    public RoleAdapter getRole(String name) {
-        DBObject query = new QueryBuilder()
-                .and("name").is(name)
-                .and("realmId").is(getId())
-                .get();
-        MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
-        if (role == null) {
-            return null;
-        } else {
-            return new RoleAdapter(session, this, role, this, invocationContext);
-        }
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        return this.addRole(null, name);
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        MongoRoleEntity roleEntity = new MongoRoleEntity();
-        roleEntity.setId(id);
-        roleEntity.setName(name);
-        roleEntity.setRealmId(getId());
-
-        getMongoStore().insertEntity(roleEntity, invocationContext);
-
-        return new RoleAdapter(session, this, roleEntity, this, invocationContext);
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        return removeRoleById(role.getId());
-    }
-
-    @Override
-    public boolean removeRoleById(String id) {
-        RoleModel role = getRoleById(id);
-        if (role == null) return false;
-        session.users().preRemove(this, role);
-        return getMongoStore().removeEntity(MongoRoleEntity.class, id, invocationContext);
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .get();
-        List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
-
-        Set<RoleModel> result = new HashSet<RoleModel>();
-
-        if (roles == null) return result;
-        for (MongoRoleEntity role : roles) {
-            result.add(new RoleAdapter(session, this, role, this, invocationContext));
-        }
-
-        return result;
-    }
-
-    @Override
-    public RoleModel getRoleById(String id) {
-        return model.getRoleById(id, this);
-    }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        return realm.getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            addRole(name);
-        }
-
-        getMongoStore().pushItemToList(realm, "defaultRoles", name, true, invocationContext);
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        List<String> roleNames = new ArrayList<String>();
-        for (String roleName : defaultRoles) {
-            RoleModel role = getRole(roleName);
-            if (role == null) {
-                addRole(roleName);
-            }
-
-            roleNames.add(roleName);
-        }
-
-        realm.setDefaultRoles(roleNames);
-        updateRealm();
-    }
-
-    @Override
-    public ClientModel getClientById(String id) {
-        return model.getClientById(id, this);
-    }
-
-    @Override
-    public ClientModel getClientByClientId(String clientId) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .and("clientId").is(clientId)
-                .get();
-        MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext);
-        return appEntity == null ? null : new ClientAdapter(session, this, appEntity, invocationContext);
-    }
-
-    @Override
-    public Map<String, ClientModel> getClientNameMap() {
-        Map<String, ClientModel> resourceMap = new HashMap<String, ClientModel>();
-        for (ClientModel resource : getClients()) {
-            resourceMap.put(resource.getClientId(), resource);
-        }
-        return resourceMap;
-    }
-
-    @Override
-    public List<ClientModel> getClients() {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .get();
-        List<MongoClientEntity> clientEntities = getMongoStore().loadEntities(MongoClientEntity.class, query, invocationContext);
-
-        List<ClientModel> result = new ArrayList<ClientModel>();
-        for (MongoClientEntity clientEntity : clientEntities) {
-            result.add(new ClientAdapter(session, this, clientEntity, invocationContext));
-        }
-        return result;
-    }
-
-    @Override
-    public ClientModel addClient(String name) {
-        return this.addClient(null, name);
-    }
-
-    @Override
-    public ClientModel addClient(String id, String clientId) {
-        MongoClientEntity clientEntity = new MongoClientEntity();
-        clientEntity.setId(id);
-        clientEntity.setClientId(clientId);
-        clientEntity.setRealmId(getId());
-        clientEntity.setEnabled(true);
-        getMongoStore().insertEntity(clientEntity, invocationContext);
-
-        final ClientModel model = new ClientAdapter(session, this, clientEntity, invocationContext);
-        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
-            @Override
-            public ClientModel getCreatedClient() {
-                return model;
-            }
-        });
-        return model;
-    }
-
-    @Override
-    public boolean removeClient(String id) {
-        if (id == null) return false;
-        ClientModel client = getClientById(id);
-        if (client == null) return false;
-
-        session.users().preRemove(this, client);
-
-        return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
-    }
-
-    @Override
-    public void addRequiredCredential(String type) {
-        RequiredCredentialModel credentialModel = initRequiredCredentialModel(type);
-        addRequiredCredential(credentialModel, realm.getRequiredCredentials());
-    }
-
-    protected void addRequiredCredential(RequiredCredentialModel credentialModel, List<RequiredCredentialEntity> persistentCollection) {
-        RequiredCredentialEntity credEntity = new RequiredCredentialEntity();
-        credEntity.setType(credentialModel.getType());
-        credEntity.setFormLabel(credentialModel.getFormLabel());
-        credEntity.setInput(credentialModel.isInput());
-        credEntity.setSecret(credentialModel.isSecret());
-
-        persistentCollection.add(credEntity);
-
-        updateRealm();
-    }
-
-    @Override
-    public void updateRequiredCredentials(Set<String> creds) {
-        updateRequiredCredentials(creds, realm.getRequiredCredentials());
-    }
-
-    protected void updateRequiredCredentials(Set<String> creds, List<RequiredCredentialEntity> credsEntities) {
-        Set<String> already = new HashSet<String>();
-        Set<RequiredCredentialEntity> toRemove = new HashSet<RequiredCredentialEntity>();
-        for (RequiredCredentialEntity entity : credsEntities) {
-            if (!creds.contains(entity.getType())) {
-                toRemove.add(entity);
-            } else {
-                already.add(entity.getType());
-            }
-        }
-        for (RequiredCredentialEntity entity : toRemove) {
-            credsEntities.remove(entity);
-        }
-        for (String cred : creds) {
-            if (!already.contains(cred)) {
-                RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred);
-                addRequiredCredential(credentialModel, credsEntities);
-            }
-        }
-        updateRealm();
-    }
-
-    @Override
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-        return convertRequiredCredentialEntities(realm.getRequiredCredentials());
-    }
-
-    protected List<RequiredCredentialModel> convertRequiredCredentialEntities(Collection<RequiredCredentialEntity> credEntities) {
-
-        List<RequiredCredentialModel> result = new ArrayList<RequiredCredentialModel>();
-        for (RequiredCredentialEntity entity : credEntities) {
-            RequiredCredentialModel model = new RequiredCredentialModel();
-            model.setFormLabel(entity.getFormLabel());
-            model.setInput(entity.isInput());
-            model.setSecret(entity.isSecret());
-            model.setType(entity.getType());
-
-            result.add(model);
-        }
-        return result;
-    }
-
-    protected void updateRealm() {
-        super.updateMongoEntity();
-    }
-
-    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
-        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
-        if (model == null) {
-            throw new RuntimeException("Unknown credential type " + type);
-        }
-        return model;
-    }
-
-    @Override
-    public Map<String, String> getBrowserSecurityHeaders() {
-        return realm.getBrowserSecurityHeaders();
-    }
-
-    @Override
-    public void setBrowserSecurityHeaders(Map<String, String> headers) {
-        realm.setBrowserSecurityHeaders(headers);
-        updateRealm();
-    }
-
-    @Override
-    public Map<String, String> getSmtpConfig() {
-        return realm.getSmtpConfig();
-    }
-
-    @Override
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        realm.setSmtpConfig(smtpConfig);
-        updateRealm();
-    }
-
-
-    @Override
-    public List<IdentityProviderModel> getIdentityProviders() {
-        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
-
-        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
-            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
-
-            identityProviderModel.setProviderId(entity.getProviderId());
-            identityProviderModel.setAlias(entity.getAlias());
-            identityProviderModel.setInternalId(entity.getInternalId());
-            identityProviderModel.setConfig(entity.getConfig());
-            identityProviderModel.setEnabled(entity.isEnabled());
-            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
-            identityProviderModel.setTrustEmail(entity.isTrustEmail());
-            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
-            identityProviderModel.setStoreToken(entity.isStoreToken());
-            identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
-
-            identityProviders.add(identityProviderModel);
-        }
-
-        return identityProviders;
-    }
-
-    @Override
-    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
-            if (identityProviderModel.getAlias().equals(alias)) {
-                return identityProviderModel;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void addIdentityProvider(IdentityProviderModel identityProvider) {
-        IdentityProviderEntity entity = new IdentityProviderEntity();
-
-        entity.setInternalId(KeycloakModelUtils.generateId());
-        entity.setAlias(identityProvider.getAlias());
-        entity.setProviderId(identityProvider.getProviderId());
-        entity.setEnabled(identityProvider.isEnabled());
-        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
-        entity.setTrustEmail(identityProvider.isTrustEmail());
-        entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
-        entity.setStoreToken(identityProvider.isStoreToken());
-        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-        entity.setConfig(identityProvider.getConfig());
-
-        realm.getIdentityProviders().add(entity);
-        updateRealm();
-    }
-
-    @Override
-    public void removeIdentityProviderByAlias(String alias) {
-        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
-            if (entity.getAlias().equals(alias)) {
-                realm.getIdentityProviders().remove(entity);
-                updateRealm();
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
-        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
-            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
-                entity.setAlias(identityProvider.getAlias());
-                entity.setEnabled(identityProvider.isEnabled());
-                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
-                entity.setTrustEmail(identityProvider.isTrustEmail());
-                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-                entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
-                entity.setStoreToken(identityProvider.isStoreToken());
-                entity.setConfig(identityProvider.getConfig());
-            }
-        }
-
-        updateRealm();
-    }
-
-    @Override
-    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
-        KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
-
-        UserFederationProviderEntity entity = new UserFederationProviderEntity();
-        entity.setId(KeycloakModelUtils.generateId());
-        entity.setPriority(priority);
-        entity.setProviderName(providerName);
-        entity.setConfig(config);
-        if (displayName == null) {
-            displayName = entity.getId();
-        }
-        entity.setDisplayName(displayName);
-        entity.setFullSyncPeriod(fullSyncPeriod);
-        entity.setChangedSyncPeriod(changedSyncPeriod);
-        entity.setLastSync(lastSync);
-        realm.getUserFederationProviders().add(entity);
-        updateRealm();
-
-        UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
-
-        session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
-
-        return providerModel;
-    }
-
-    @Override
-    public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(provider.getId())) {
-                session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                        entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-                removeFederationMappersForProvider(provider.getId());
-
-                it.remove();
-            }
-        }
-        updateRealm();
-    }
-
-    private void removeFederationMappersForProvider(String federationProviderId) {
-        Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
-        for (UserFederationMapperEntity mapper : mappers) {
-            getMongoEntity().getUserFederationMappers().remove(mapper);
-        }
-    }
-
-    @Override
-    public void updateUserFederationProvider(UserFederationProviderModel model) {
-        KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
-
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(model.getId())) {
-                entity.setProviderName(model.getProviderName());
-                entity.setConfig(model.getConfig());
-                entity.setPriority(model.getPriority());
-                String displayName = model.getDisplayName();
-                if (displayName != null) {
-                    entity.setDisplayName(model.getDisplayName());
-                }
-                entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                entity.setLastSync(model.getLastSync());
-            }
-        }
-        updateRealm();
-    }
-
-    @Override
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
-        List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
-        for (UserFederationProviderEntity entity : entities) {
-            copy.add(entity);
-
-        }
-        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
-
-            @Override
-            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
-                return o1.getPriority() - o2.getPriority();
-            }
-
-        });
-        List<UserFederationProviderModel> result = new LinkedList<UserFederationProviderModel>();
-        for (UserFederationProviderEntity entity : copy) {
-            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-        }
-
-        return result;
-    }
-
-    @Override
-    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
-        for (UserFederationProviderModel currentProvider : providers) {
-            KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
-        }
-
-        List<UserFederationProviderEntity> existingProviders = realm.getUserFederationProviders();
-        List<UserFederationProviderEntity> toRemove = new LinkedList<>();
-        for (UserFederationProviderEntity entity : existingProviders) {
-            boolean found = false;
-            for (UserFederationProviderModel model : providers) {
-                if (entity.getId().equals(model.getId())) {
-                    entity.setConfig(model.getConfig());
-                    entity.setPriority(model.getPriority());
-                    entity.setProviderName(model.getProviderName());
-                    String displayName = model.getDisplayName();
-                    if (displayName != null) {
-                        entity.setDisplayName(displayName);
-                    }
-                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                    entity.setLastSync(model.getLastSync());
-                    found = true;
-                    break;
-                }
-
-            }
-            if (found) continue;
-            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-            removeFederationMappersForProvider(entity.getId());
-
-            toRemove.add(entity);
-        }
-
-        for (UserFederationProviderEntity entity : toRemove) {
-            realm.getUserFederationProviders().remove(entity);
-        }
-
-        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
-        for (UserFederationProviderModel model : providers) {
-            boolean found = false;
-            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
-                if (entity.getId().equals(model.getId())) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) add.add(model);
-        }
-
-        for (UserFederationProviderModel model : add) {
-            UserFederationProviderEntity entity = new UserFederationProviderEntity();
-            if (model.getId() != null) {
-                entity.setId(model.getId());
-            } else {
-                String id = KeycloakModelUtils.generateId();
-                entity.setId(id);
-                model.setId(id);
-            }
-            entity.setProviderName(model.getProviderName());
-            entity.setConfig(model.getConfig());
-            entity.setPriority(model.getPriority());
-            String displayName = model.getDisplayName();
-            if (displayName == null) {
-                displayName = entity.getId();
-            }
-            entity.setDisplayName(displayName);
-            entity.setFullSyncPeriod(model.getFullSyncPeriod());
-            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-            entity.setLastSync(model.getLastSync());
-            realm.getUserFederationProviders().add(entity);
-
-            session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
-        }
-
-        updateRealm();
-    }
-
-    @Override
-    public boolean isEventsEnabled() {
-        return realm.isEventsEnabled();
-    }
-
-    @Override
-    public void setEventsEnabled(boolean enabled) {
-        realm.setEventsEnabled(enabled);
-        updateRealm();
-    }
-
-    @Override
-    public long getEventsExpiration() {
-        return realm.getEventsExpiration();
-    }
-
-    @Override
-    public void setEventsExpiration(long expiration) {
-        realm.setEventsExpiration(expiration);
-        updateRealm();
-    }
-
-    @Override
-    public Set<String> getEventsListeners() {
-        return new HashSet<String>(realm.getEventsListeners());
-    }
-
-    @Override
-    public void setEventsListeners(Set<String> listeners) {
-        if (listeners != null) {
-            realm.setEventsListeners(new ArrayList<String>(listeners));
-        } else {
-            realm.setEventsListeners(Collections.EMPTY_LIST);
-        }
-        updateRealm();
-    }
-
-    @Override
-    public Set<String> getEnabledEventTypes() {
-        return new HashSet<String>(realm.getEnabledEventTypes());
-    }
-
-    @Override
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        if (enabledEventTypes != null) {
-            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
-        } else {
-            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
-        }
-        updateRealm();
-    }
-    
-    @Override
-    public boolean isAdminEventsEnabled() {
-        return realm.isAdminEventsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsEnabled(boolean enabled) {
-        realm.setAdminEventsEnabled(enabled);
-        updateRealm();
-        
-    }
-
-    @Override
-    public boolean isAdminEventsDetailsEnabled() {
-        return realm.isAdminEventsDetailsEnabled();
-    }
-
-    @Override
-    public void setAdminEventsDetailsEnabled(boolean enabled) {
-        realm.setAdminEventsDetailsEnabled(enabled);
-        updateRealm();
-    }
-    
-    @Override
-    public ClientModel getMasterAdminClient() {
-        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, realm.getMasterAdminClient(), invocationContext);
-        return appData != null ? new ClientAdapter(session, this, appData, invocationContext) : null;
-    }
-
-    @Override
-    public void setMasterAdminClient(ClientModel client) {
-        String adminAppId = client != null ? client.getId() : null;
-        realm.setMasterAdminClient(adminAppId);
-        updateRealm();
-    }
-
-    @Override
-    public MongoRealmEntity getMongoEntity() {
-        return realm;
-    }
-
-    @Override
-    public boolean isIdentityFederationEnabled() {
-        return this.realm.getIdentityProviders() != null && !this.realm.getIdentityProviders().isEmpty();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RealmModel)) return false;
-
-        RealmModel that = (RealmModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public boolean isInternationalizationEnabled() {
-        return realm.isInternationalizationEnabled();
-    }
-
-    @Override
-    public void setInternationalizationEnabled(boolean enabled) {
-        realm.setInternationalizationEnabled(enabled);
-        updateRealm();
-    }
-
-    @Override
-    public Set<String> getSupportedLocales() {
-        return new HashSet<String>(realm.getSupportedLocales());
-    }
-
-    @Override
-    public void setSupportedLocales(Set<String> locales) {
-        if (locales != null) {
-            realm.setSupportedLocales(new ArrayList<String>(locales));
-        } else {
-            realm.setSupportedLocales(Collections.EMPTY_LIST);
-        }
-        updateRealm();
-    }
-
-    @Override
-    public String getDefaultLocale() {
-        return realm.getDefaultLocale();
-    }
-
-    @Override
-    public void setDefaultLocale(String locale) {
-        realm.setDefaultLocale(locale);
-        updateRealm();
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
-            IdentityProviderMapperModel mapping = entityToModel(entity);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
-            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
-                continue;
-            }
-            IdentityProviderMapperModel mapping = entityToModel(entity);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
-        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
-            throw new RuntimeException("identity provider mapper name must be unique per identity provider");
-        }
-        String id = KeycloakModelUtils.generateId();
-        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
-        entity.setConfig(model.getConfig());
-
-        getMongoEntity().getIdentityProviderMappers().add(entity);
-        updateMongoEntity();
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
-        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
-        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
-            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
-        if (toDelete != null) {
-            this.realm.getIdentityProviderMappers().remove(toDelete);
-            updateMongoEntity();
-        }
-    }
-
-    @Override
-    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
-        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapping.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        }
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
-        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-    @Override
-    public List<AuthenticationFlowModel> getAuthenticationFlows() {
-        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
-        List<AuthenticationFlowModel> models = new LinkedList<>();
-        for (AuthenticationFlowEntity entity : flows) {
-            AuthenticationFlowModel model = entityToModel(entity);
-            models.add(model);
-        }
-        return models;
-    }
-
-    @Override
-    public AuthenticationFlowModel getFlowByAlias(String alias) {
-        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
-            if (flow.getAlias().equals(alias)) {
-                return flow;
-            }
-        }
-        return null;
-    }
-
-
-    protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
-        AuthenticationFlowModel model = new AuthenticationFlowModel();
-        model.setId(entity.getId());
-        model.setAlias(entity.getAlias());
-        model.setDescription(entity.getDescription());
-        model.setBuiltIn(entity.isBuiltIn());
-        model.setTopLevel(entity.isTopLevel());
-        return model;
-    }
-
-    @Override
-    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
-        AuthenticationFlowEntity entity = getFlowEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected AuthenticationFlowEntity getFlowEntity(String id) {
-        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
-        for (AuthenticationFlowEntity entity : flows) {
-            if (id.equals(entity.getId())) return entity;
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity toDelete = getFlowEntity(model.getId());
-        if (toDelete == null) return;
-        getMongoEntity().getAuthenticationFlows().remove(toDelete);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity toUpdate = getFlowEntity(model.getId());;
-        if (toUpdate == null) return;
-        toUpdate.setAlias(model.getAlias());
-        toUpdate.setDescription(model.getDescription());
-        toUpdate.setProviderId(model.getProviderId());
-        toUpdate.setBuiltIn(model.isBuiltIn());
-        toUpdate.setTopLevel(model.isTopLevel());
-        updateMongoEntity();
-    }
-
-    @Override
-    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
-        AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        entity.setId(id);
-        entity.setAlias(model.getAlias());
-        entity.setDescription(model.getDescription());
-        entity.setProviderId(model.getProviderId());
-        entity.setBuiltIn(model.isBuiltIn());
-        entity.setTopLevel(model.isTopLevel());
-        getMongoEntity().getAuthenticationFlows().add(entity);
-        model.setId(entity.getId());
-        updateMongoEntity();
-        return model;
-    }
-
-    @Override
-    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
-        AuthenticationFlowEntity flow = getFlowEntity(flowId);
-        if (flow == null) return Collections.EMPTY_LIST;
-
-        List<AuthenticationExecutionEntity> queryResult = flow.getExecutions();
-        List<AuthenticationExecutionModel> executions = new LinkedList<>();
-        for (AuthenticationExecutionEntity entity : queryResult) {
-            AuthenticationExecutionModel model = entityToModel(entity);
-            executions.add(model);
-        }
-        Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
-        return executions;
-    }
-
-    public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
-        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
-        model.setId(entity.getId());
-        model.setUserSetupAllowed(entity.isUserSetupAllowed());
-        model.setRequirement(entity.getRequirement());
-        model.setPriority(entity.getPriority());
-        model.setAuthenticator(entity.getAuthenticator());
-        model.setFlowId(entity.getFlowId());
-        model.setParentFlow(entity.getParentFlow());
-        model.setAutheticatorFlow(entity.isAuthenticatorFlow());
-        model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
-        return model;
-    }
-
-    @Override
-    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
-        AuthenticationExecutionEntity execution = getAuthenticationExecutionEntity(id);
-        return entityToModel(execution);
-    }
-
-    public AuthenticationExecutionEntity getAuthenticationExecutionEntity(String id) {
-        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
-        for (AuthenticationFlowEntity entity : flows) {
-            for (AuthenticationExecutionEntity exe : entity.getExecutions()) {
-                if (exe.getId().equals(id)) {
-                   return exe;
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        entity.setId(id);
-        entity.setAuthenticator(model.getAuthenticator());
-        entity.setPriority(model.getPriority());
-        entity.setRequirement(model.getRequirement());
-        entity.setUserSetupAllowed(model.isUserSetupAllowed());
-        entity.setAuthenticatorFlow(model.isAutheticatorFlow());
-        entity.setFlowId(model.getFlowId());
-        entity.setParentFlow(model.getParentFlow());
-        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
-        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
-        flow.getExecutions().add(entity);
-        updateMongoEntity();
-        model.setId(entity.getId());
-        return model;
-
-    }
-
-    @Override
-    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = null;
-        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
-        for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
-            if (exe.getId().equals(model.getId())) {
-                entity = exe;
-            }
-        }
-        if (entity == null) return;
-        entity.setAuthenticatorFlow(model.isAutheticatorFlow());
-        entity.setAuthenticator(model.getAuthenticator());
-        entity.setPriority(model.getPriority());
-        entity.setRequirement(model.getRequirement());
-        entity.setFlowId(model.getFlowId());
-        entity.setUserSetupAllowed(model.isUserSetupAllowed());
-        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
-        updateMongoEntity();
-    }
-
-    @Override
-    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
-        AuthenticationExecutionEntity entity = null;
-        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
-        for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
-            if (exe.getId().equals(model.getId())) {
-                entity = exe;
-            }
-        }
-        if (entity == null) return;
-        flow.getExecutions().remove(entity);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
-        List<AuthenticatorConfigModel> authenticators = new LinkedList<>();
-        for (AuthenticatorConfigEntity entity : getMongoEntity().getAuthenticatorConfigs()) {
-            authenticators.add(entityToModel(entity));
-        }
-        return authenticators;
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
-        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
-            if (config.getAlias().equals(alias)) {
-                return config;
-            }
-        }
-        return null;
-    }
-
-
-    @Override
-    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity();
-        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
-        auth.setId(id);
-        auth.setAlias(model.getAlias());
-        auth.setConfig(model.getConfig());
-        realm.getAuthenticatorConfigs().add(auth);
-        model.setId(auth.getId());
-        updateMongoEntity();
-        return model;
-    }
-
-    @Override
-    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId());
-        if (entity == null) return;
-        getMongoEntity().getAuthenticatorConfigs().remove(entity);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
-        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    public AuthenticatorConfigEntity getAuthenticatorConfigEntity(String id) {
-        AuthenticatorConfigEntity entity = null;
-        for (AuthenticatorConfigEntity auth : getMongoEntity().getAuthenticatorConfigs()) {
-            if (auth.getId().equals(id)) {
-                entity = auth;
-                break;
-            }
-        }
-        return entity;
-    }
-
-    public AuthenticatorConfigModel entityToModel(AuthenticatorConfigEntity entity) {
-        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
-        model.setId(entity.getId());
-        model.setAlias(entity.getAlias());
-        Map<String, String> config = new HashMap<>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        model.setConfig(config);
-        return model;
-    }
-
-    @Override
-    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
-        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId());
-        if (entity == null) return;
-        entity.setAlias(model.getAlias());
-        if (entity.getConfig() == null) {
-            entity.setConfig(model.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(model.getConfig());
-        }
-        updateMongoEntity();
-    }
-
-    @Override
-    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity auth = new RequiredActionProviderEntity();
-        auth.setId(KeycloakModelUtils.generateId());
-        auth.setAlias(model.getAlias());
-        auth.setProviderId(model.getProviderId());
-        auth.setConfig(model.getConfig());
-        auth.setEnabled(model.isEnabled());
-        auth.setDefaultAction(model.isDefaultAction());
-        realm.getRequiredActionProviders().add(auth);
-        model.setId(auth.getId());
-        updateMongoEntity();
-        return model;
-    }
-
-    @Override
-    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(model.getId());
-        if (entity == null) return;
-        getMongoEntity().getRequiredActionProviders().remove(entity);
-        updateMongoEntity();
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
-        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    public RequiredActionProviderModel entityToModel(RequiredActionProviderEntity entity) {
-        RequiredActionProviderModel model = new RequiredActionProviderModel();
-        model.setId(entity.getId());
-        model.setProviderId(entity.getProviderId());
-        model.setAlias(entity.getAlias());
-        model.setEnabled(entity.isEnabled());
-        model.setDefaultAction(entity.isDefaultAction());
-        Map<String, String> config = new HashMap<>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        model.setConfig(config);
-        return model;
-    }
-
-    @Override
-    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
-        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(model.getId());
-        if (entity == null) return;
-        entity.setAlias(model.getAlias());
-        entity.setProviderId(model.getProviderId());
-        entity.setEnabled(model.isEnabled());
-        entity.setDefaultAction(model.isDefaultAction());
-        if (entity.getConfig() == null) {
-            entity.setConfig(model.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(model.getConfig());
-        }
-        updateMongoEntity();
-    }
-
-    @Override
-    public List<RequiredActionProviderModel> getRequiredActionProviders() {
-        List<RequiredActionProviderModel> actions = new LinkedList<>();
-        for (RequiredActionProviderEntity entity : realm.getRequiredActionProviders()) {
-            actions.add(entityToModel(entity));
-        }
-        return actions;
-    }
-
-    public RequiredActionProviderEntity getRequiredActionProviderEntity(String id) {
-        RequiredActionProviderEntity entity = null;
-        for (RequiredActionProviderEntity auth : getMongoEntity().getRequiredActionProviders()) {
-            if (auth.getId().equals(id)) {
-                entity = auth;
-                break;
-            }
-        }
-        return entity;
-    }
-
-    @Override
-    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
-        for (RequiredActionProviderModel action : getRequiredActionProviders()) {
-            if (action.getAlias().equals(alias)) return action;
-        }
-        return null;
-    }
-
-
-
-
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappers() {
-        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
-        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
-            UserFederationMapperModel mapper = entityToModel(entity);
-            mappers.add(mapper);
-        }
-        return mappers;
-    }
-
-    @Override
-    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
-        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
-        Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
-        for (UserFederationMapperEntity entity : mapperEntities) {
-            mappers.add(entityToModel(entity));
-        }
-        return mappers;
-    }
-
-    @Override
-    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
-        if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
-            throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
-        }
-        String id = KeycloakModelUtils.generateId();
-        UserFederationMapperEntity entity = new UserFederationMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setFederationProviderId(model.getFederationProviderId());
-        entity.setFederationMapperType(model.getFederationMapperType());
-        entity.setConfig(model.getConfig());
-
-        getMongoEntity().getUserFederationMappers().add(entity);
-        updateMongoEntity();
-        UserFederationMapperModel mapperModel = entityToModel(entity);
-
-        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
-
-        return mapperModel;
-    }
-
-    protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
-        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
-        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
-            if (entity.getFederationProviderId().equals(federationProviderId) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
-        Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
-        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
-            if (federationProviderId.equals(entity.getFederationProviderId())) {
-                mappers.add(entity);
-            }
-        }
-        return mappers;
-    }
-
-    @Override
-    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
-        UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
-        if (toDelete != null) {
-            this.realm.getUserFederationMappers().remove(toDelete);
-            updateMongoEntity();
-        }
-    }
-
-    @Override
-    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
-        entity.setFederationProviderId(mapper.getFederationProviderId());
-        entity.setFederationMapperType(mapper.getFederationMapperType());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapper.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapper.getConfig());
-        }
-        updateMongoEntity();
-
-        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperById(String id) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
-        UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
-        UserFederationMapperModel mapper = new UserFederationMapperModel();
-        mapper.setId(entity.getId());
-        mapper.setName(entity.getName());
-        mapper.setFederationProviderId(entity.getFederationProviderId());
-        mapper.setFederationMapperType(entity.getFederationMapperType());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapper.setConfig(config);
-        return mapper;
-    }
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperEventImpl;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderCreationEventImpl;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.entities.AuthenticationExecutionEntity;
+import org.keycloak.models.entities.AuthenticationFlowEntity;
+import org.keycloak.models.entities.AuthenticatorConfigEntity;
+import org.keycloak.models.entities.IdentityProviderEntity;
+import org.keycloak.models.entities.IdentityProviderMapperEntity;
+import org.keycloak.models.entities.RequiredActionProviderEntity;
+import org.keycloak.models.entities.RequiredCredentialEntity;
+import org.keycloak.models.entities.UserFederationMapperEntity;
+import org.keycloak.models.entities.UserFederationProviderEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> implements RealmModel {
+
+    private final MongoRealmEntity realm;
+    private final RealmProvider model;
+
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+    protected volatile transient X509Certificate certificate;
+    protected volatile transient Key codeSecretKey;
+
+    private volatile transient PasswordPolicy passwordPolicy;
+    private volatile transient KeycloakSession session;
+
+    public RealmAdapter(KeycloakSession session, MongoRealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
+        super(invocationContext);
+        this.realm = realmEntity;
+        this.session = session;
+        this.model = session.realms();
+    }
+
+    @Override
+    public String getId() {
+        return realm.getId();
+    }
+
+    @Override
+    public String getName() {
+        return realm.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        realm.setName(name);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return realm.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        realm.setEnabled(enabled);
+        updateRealm();
+    }
+
+    @Override
+    public SslRequired getSslRequired() {
+        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
+    }
+
+    @Override
+    public void setSslRequired(SslRequired sslRequired) {
+        realm.setSslRequired(sslRequired.name());
+        updateRealm();
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        realm.setRegistrationAllowed(registrationAllowed);
+        updateRealm();
+    }
+
+    public boolean isRegistrationEmailAsUsername() {
+        return realm.isRegistrationEmailAsUsername();
+    }
+
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isBruteForceProtected() {
+        return realm.isBruteForceProtected();
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        realm.setBruteForceProtected(value);
+        updateRealm();
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        return realm.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        realm.setMaxFailureWaitSeconds(val);
+        updateRealm();
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return realm.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        realm.setWaitIncrementSeconds(val);
+        updateRealm();
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return realm.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        realm.setQuickLoginCheckMilliSeconds(val);
+        updateRealm();
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return realm.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        realm.setMinimumQuickLoginWaitSeconds(val);
+        updateRealm();
+    }
+
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return realm.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        realm.setMaxDeltaTimeSeconds(val);
+        updateRealm();
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return realm.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        realm.setFailureFactor(failureFactor);
+        updateRealm();
+    }
+
+
+    @Override
+    public boolean isVerifyEmail() {
+        return realm.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        realm.setVerifyEmail(verifyEmail);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        return realm.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPassword) {
+        realm.setResetPasswordAllowed(resetPassword);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isEditUsernameAllowed() {
+        return realm.isEditUsernameAllowed();
+    }
+
+    @Override
+    public void setEditUsernameAllowed(boolean editUsernameAllowed) {
+        realm.setEditUsernameAllowed(editUsernameAllowed);
+        updateRealm();
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (passwordPolicy == null) {
+            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
+        }
+        return passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        this.passwordPolicy = policy;
+        realm.setPasswordPolicy(policy.toString());
+        updateRealm();
+    }
+
+    @Override
+    public int getNotBefore() {
+        return realm.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        realm.setNotBefore(notBefore);
+        updateRealm();
+    }
+
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        return realm.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        realm.setSsoSessionIdleTimeout(seconds);
+        updateRealm();
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        return realm.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        realm.setSsoSessionMaxLifespan(seconds);
+        updateRealm();
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+        updateRealm();
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        return realm.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        realm.setAccessCodeLifespan(accessCodeLifespan);
+        updateRealm();
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        return realm.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
+        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
+        updateRealm();
+    }
+
+    @Override
+    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
+        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
+        updateRealm();
+    }
+
+    @Override
+    public int getAccessCodeLifespanLogin() {
+        return realm.getAccessCodeLifespanLogin();
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        return realm.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        realm.setPublicKeyPem(publicKeyPem);
+        this.publicKey = null;
+        updateRealm();
+    }
+
+    @Override
+    public X509Certificate getCertificate() {
+        if (certificate != null) return certificate;
+        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
+        return certificate;
+    }
+
+    @Override
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
+        setCertificatePem(certificatePem);
+
+    }
+
+    @Override
+    public String getCertificatePem() {
+        return realm.getCertificatePem();
+    }
+
+    @Override
+    public void setCertificatePem(String certificate) {
+        realm.setCertificatePem(certificate);
+
+    }
+
+
+    @Override
+    public String getPrivateKeyPem() {
+        return realm.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        realm.setPrivateKeyPem(privateKeyPem);
+        this.privateKey = null;
+        updateRealm();
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public String getCodeSecret() {
+        return realm.getCodeSecret();
+    }
+
+    @Override
+    public Key getCodeSecretKey() {
+        if (codeSecretKey == null) {
+            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
+        }
+        return codeSecretKey;
+    }
+
+    @Override
+    public void setCodeSecret(String codeSecret) {
+        realm.setCodeSecret(codeSecret);
+        updateRealm();
+    }
+
+    @Override
+    public String getLoginTheme() {
+        return realm.getLoginTheme();
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        realm.setLoginTheme(name);
+        updateRealm();
+    }
+
+    @Override
+    public String getAccountTheme() {
+        return realm.getAccountTheme();
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        realm.setAccountTheme(name);
+        updateRealm();
+    }
+
+    @Override
+    public String getAdminTheme() {
+        return realm.getAdminTheme();
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        realm.setAdminTheme(name);
+        updateRealm();
+    }
+
+    @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+        updateRealm();
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        DBObject query = new QueryBuilder()
+                .and("name").is(name)
+                .and("realmId").is(getId())
+                .get();
+        MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
+        if (role == null) {
+            return null;
+        } else {
+            return new RoleAdapter(session, this, role, this, invocationContext);
+        }
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(null, name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        MongoRoleEntity roleEntity = new MongoRoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setRealmId(getId());
+
+        getMongoStore().insertEntity(roleEntity, invocationContext);
+
+        return new RoleAdapter(session, this, roleEntity, this, invocationContext);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        return removeRoleById(role.getId());
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        RoleModel role = getRoleById(id);
+        if (role == null) return false;
+        session.users().preRemove(this, role);
+        return getMongoStore().removeEntity(MongoRoleEntity.class, id, invocationContext);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(getId())
+                .get();
+        List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
+
+        Set<RoleModel> result = new HashSet<RoleModel>();
+
+        if (roles == null) return result;
+        for (MongoRoleEntity role : roles) {
+            result.add(new RoleAdapter(session, this, role, this, invocationContext));
+        }
+
+        return result;
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        return model.getRoleById(id, this);
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return realm.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        getMongoStore().pushItemToList(realm, "defaultRoles", name, true, invocationContext);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        realm.setDefaultRoles(roleNames);
+        updateRealm();
+    }
+
+    @Override
+    public ClientModel getClientById(String id) {
+        return model.getClientById(id, this);
+    }
+
+    @Override
+    public ClientModel getClientByClientId(String clientId) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(getId())
+                .and("clientId").is(clientId)
+                .get();
+        MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext);
+        return appEntity == null ? null : new ClientAdapter(session, this, appEntity, invocationContext);
+    }
+
+    @Override
+    public Map<String, ClientModel> getClientNameMap() {
+        Map<String, ClientModel> resourceMap = new HashMap<String, ClientModel>();
+        for (ClientModel resource : getClients()) {
+            resourceMap.put(resource.getClientId(), resource);
+        }
+        return resourceMap;
+    }
+
+    @Override
+    public List<ClientModel> getClients() {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(getId())
+                .get();
+        List<MongoClientEntity> clientEntities = getMongoStore().loadEntities(MongoClientEntity.class, query, invocationContext);
+
+        List<ClientModel> result = new ArrayList<ClientModel>();
+        for (MongoClientEntity clientEntity : clientEntities) {
+            result.add(new ClientAdapter(session, this, clientEntity, invocationContext));
+        }
+        return result;
+    }
+
+    @Override
+    public ClientModel addClient(String name) {
+        return this.addClient(null, name);
+    }
+
+    @Override
+    public ClientModel addClient(String id, String clientId) {
+        MongoClientEntity clientEntity = new MongoClientEntity();
+        clientEntity.setId(id);
+        clientEntity.setClientId(clientId);
+        clientEntity.setRealmId(getId());
+        clientEntity.setEnabled(true);
+        getMongoStore().insertEntity(clientEntity, invocationContext);
+
+        final ClientModel model = new ClientAdapter(session, this, clientEntity, invocationContext);
+        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
+            @Override
+            public ClientModel getCreatedClient() {
+                return model;
+            }
+        });
+        return model;
+    }
+
+    @Override
+    public boolean removeClient(String id) {
+        if (id == null) return false;
+        ClientModel client = getClientById(id);
+        if (client == null) return false;
+
+        session.users().preRemove(this, client);
+
+        return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
+    }
+
+    @Override
+    public void addRequiredCredential(String type) {
+        RequiredCredentialModel credentialModel = initRequiredCredentialModel(type);
+        addRequiredCredential(credentialModel, realm.getRequiredCredentials());
+    }
+
+    protected void addRequiredCredential(RequiredCredentialModel credentialModel, List<RequiredCredentialEntity> persistentCollection) {
+        RequiredCredentialEntity credEntity = new RequiredCredentialEntity();
+        credEntity.setType(credentialModel.getType());
+        credEntity.setFormLabel(credentialModel.getFormLabel());
+        credEntity.setInput(credentialModel.isInput());
+        credEntity.setSecret(credentialModel.isSecret());
+
+        persistentCollection.add(credEntity);
+
+        updateRealm();
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        updateRequiredCredentials(creds, realm.getRequiredCredentials());
+    }
+
+    protected void updateRequiredCredentials(Set<String> creds, List<RequiredCredentialEntity> credsEntities) {
+        Set<String> already = new HashSet<String>();
+        Set<RequiredCredentialEntity> toRemove = new HashSet<RequiredCredentialEntity>();
+        for (RequiredCredentialEntity entity : credsEntities) {
+            if (!creds.contains(entity.getType())) {
+                toRemove.add(entity);
+            } else {
+                already.add(entity.getType());
+            }
+        }
+        for (RequiredCredentialEntity entity : toRemove) {
+            credsEntities.remove(entity);
+        }
+        for (String cred : creds) {
+            if (!already.contains(cred)) {
+                RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred);
+                addRequiredCredential(credentialModel, credsEntities);
+            }
+        }
+        updateRealm();
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        return convertRequiredCredentialEntities(realm.getRequiredCredentials());
+    }
+
+    protected List<RequiredCredentialModel> convertRequiredCredentialEntities(Collection<RequiredCredentialEntity> credEntities) {
+
+        List<RequiredCredentialModel> result = new ArrayList<RequiredCredentialModel>();
+        for (RequiredCredentialEntity entity : credEntities) {
+            RequiredCredentialModel model = new RequiredCredentialModel();
+            model.setFormLabel(entity.getFormLabel());
+            model.setInput(entity.isInput());
+            model.setSecret(entity.isSecret());
+            model.setType(entity.getType());
+
+            result.add(model);
+        }
+        return result;
+    }
+
+    protected void updateRealm() {
+        super.updateMongoEntity();
+    }
+
+    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
+        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
+        if (model == null) {
+            throw new RuntimeException("Unknown credential type " + type);
+        }
+        return model;
+    }
+
+    @Override
+    public Map<String, String> getBrowserSecurityHeaders() {
+        return realm.getBrowserSecurityHeaders();
+    }
+
+    @Override
+    public void setBrowserSecurityHeaders(Map<String, String> headers) {
+        realm.setBrowserSecurityHeaders(headers);
+        updateRealm();
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        return realm.getSmtpConfig();
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        realm.setSmtpConfig(smtpConfig);
+        updateRealm();
+    }
+
+
+    @Override
+    public List<IdentityProviderModel> getIdentityProviders() {
+        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
+
+        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
+            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
+
+            identityProviderModel.setProviderId(entity.getProviderId());
+            identityProviderModel.setAlias(entity.getAlias());
+            identityProviderModel.setInternalId(entity.getInternalId());
+            identityProviderModel.setConfig(entity.getConfig());
+            identityProviderModel.setEnabled(entity.isEnabled());
+            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
+            identityProviderModel.setTrustEmail(entity.isTrustEmail());
+            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
+            identityProviderModel.setStoreToken(entity.isStoreToken());
+            identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
+
+            identityProviders.add(identityProviderModel);
+        }
+
+        return identityProviders;
+    }
+
+    @Override
+    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
+            if (identityProviderModel.getAlias().equals(alias)) {
+                return identityProviderModel;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void addIdentityProvider(IdentityProviderModel identityProvider) {
+        IdentityProviderEntity entity = new IdentityProviderEntity();
+
+        entity.setInternalId(KeycloakModelUtils.generateId());
+        entity.setAlias(identityProvider.getAlias());
+        entity.setProviderId(identityProvider.getProviderId());
+        entity.setEnabled(identityProvider.isEnabled());
+        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+        entity.setTrustEmail(identityProvider.isTrustEmail());
+        entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
+        entity.setStoreToken(identityProvider.isStoreToken());
+        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+        entity.setConfig(identityProvider.getConfig());
+
+        realm.getIdentityProviders().add(entity);
+        updateRealm();
+    }
+
+    @Override
+    public void removeIdentityProviderByAlias(String alias) {
+        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
+            if (entity.getAlias().equals(alias)) {
+                realm.getIdentityProviders().remove(entity);
+                updateRealm();
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
+        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
+            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
+                entity.setAlias(identityProvider.getAlias());
+                entity.setEnabled(identityProvider.isEnabled());
+                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
+                entity.setTrustEmail(identityProvider.isTrustEmail());
+                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+                entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
+                entity.setStoreToken(identityProvider.isStoreToken());
+                entity.setConfig(identityProvider.getConfig());
+            }
+        }
+
+        updateRealm();
+    }
+
+    @Override
+    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
+        KeycloakModelUtils.ensureUniqueDisplayName(displayName, null, getUserFederationProviders());
+
+        UserFederationProviderEntity entity = new UserFederationProviderEntity();
+        entity.setId(KeycloakModelUtils.generateId());
+        entity.setPriority(priority);
+        entity.setProviderName(providerName);
+        entity.setConfig(config);
+        if (displayName == null) {
+            displayName = entity.getId();
+        }
+        entity.setDisplayName(displayName);
+        entity.setFullSyncPeriod(fullSyncPeriod);
+        entity.setChangedSyncPeriod(changedSyncPeriod);
+        entity.setLastSync(lastSync);
+        realm.getUserFederationProviders().add(entity);
+        updateRealm();
+
+        UserFederationProviderModel providerModel = new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+
+        session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, providerModel));
+
+        return providerModel;
+    }
+
+    @Override
+    public void removeUserFederationProvider(UserFederationProviderModel provider) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(provider.getId())) {
+                session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                        entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+                removeFederationMappersForProvider(provider.getId());
+
+                it.remove();
+            }
+        }
+        updateRealm();
+    }
+
+    private void removeFederationMappersForProvider(String federationProviderId) {
+        Set<UserFederationMapperEntity> mappers = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+        for (UserFederationMapperEntity mapper : mappers) {
+            getMongoEntity().getUserFederationMappers().remove(mapper);
+        }
+    }
+
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getUserFederationProviders());
+
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                entity.setProviderName(model.getProviderName());
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+                String displayName = model.getDisplayName();
+                if (displayName != null) {
+                    entity.setDisplayName(model.getDisplayName());
+                }
+                entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                entity.setLastSync(model.getLastSync());
+            }
+        }
+        updateRealm();
+    }
+
+    @Override
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
+        List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
+        for (UserFederationProviderEntity entity : entities) {
+            copy.add(entity);
+
+        }
+        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
+
+            @Override
+            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
+                return o1.getPriority() - o2.getPriority();
+            }
+
+        });
+        List<UserFederationProviderModel> result = new LinkedList<UserFederationProviderModel>();
+        for (UserFederationProviderEntity entity : copy) {
+            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+        }
+
+        return result;
+    }
+
+    @Override
+    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
+        for (UserFederationProviderModel currentProvider : providers) {
+            KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
+        }
+
+        List<UserFederationProviderEntity> existingProviders = realm.getUserFederationProviders();
+        List<UserFederationProviderEntity> toRemove = new LinkedList<>();
+        for (UserFederationProviderEntity entity : existingProviders) {
+            boolean found = false;
+            for (UserFederationProviderModel model : providers) {
+                if (entity.getId().equals(model.getId())) {
+                    entity.setConfig(model.getConfig());
+                    entity.setPriority(model.getPriority());
+                    entity.setProviderName(model.getProviderName());
+                    String displayName = model.getDisplayName();
+                    if (displayName != null) {
+                        entity.setDisplayName(displayName);
+                    }
+                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                    entity.setLastSync(model.getLastSync());
+                    found = true;
+                    break;
+                }
+
+            }
+            if (found) continue;
+            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+            removeFederationMappersForProvider(entity.getId());
+
+            toRemove.add(entity);
+        }
+
+        for (UserFederationProviderEntity entity : toRemove) {
+            realm.getUserFederationProviders().remove(entity);
+        }
+
+        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
+        for (UserFederationProviderModel model : providers) {
+            boolean found = false;
+            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
+                if (entity.getId().equals(model.getId())) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) add.add(model);
+        }
+
+        for (UserFederationProviderModel model : add) {
+            UserFederationProviderEntity entity = new UserFederationProviderEntity();
+            if (model.getId() != null) {
+                entity.setId(model.getId());
+            } else {
+                String id = KeycloakModelUtils.generateId();
+                entity.setId(id);
+                model.setId(id);
+            }
+            entity.setProviderName(model.getProviderName());
+            entity.setConfig(model.getConfig());
+            entity.setPriority(model.getPriority());
+            String displayName = model.getDisplayName();
+            if (displayName == null) {
+                displayName = entity.getId();
+            }
+            entity.setDisplayName(displayName);
+            entity.setFullSyncPeriod(model.getFullSyncPeriod());
+            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+            entity.setLastSync(model.getLastSync());
+            realm.getUserFederationProviders().add(entity);
+
+            session.getKeycloakSessionFactory().publish(new UserFederationProviderCreationEventImpl(this, model));
+        }
+
+        updateRealm();
+    }
+
+    @Override
+    public boolean isEventsEnabled() {
+        return realm.isEventsEnabled();
+    }
+
+    @Override
+    public void setEventsEnabled(boolean enabled) {
+        realm.setEventsEnabled(enabled);
+        updateRealm();
+    }
+
+    @Override
+    public long getEventsExpiration() {
+        return realm.getEventsExpiration();
+    }
+
+    @Override
+    public void setEventsExpiration(long expiration) {
+        realm.setEventsExpiration(expiration);
+        updateRealm();
+    }
+
+    @Override
+    public Set<String> getEventsListeners() {
+        return new HashSet<String>(realm.getEventsListeners());
+    }
+
+    @Override
+    public void setEventsListeners(Set<String> listeners) {
+        if (listeners != null) {
+            realm.setEventsListeners(new ArrayList<String>(listeners));
+        } else {
+            realm.setEventsListeners(Collections.EMPTY_LIST);
+        }
+        updateRealm();
+    }
+
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return new HashSet<String>(realm.getEnabledEventTypes());
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        if (enabledEventTypes != null) {
+            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
+        } else {
+            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
+        }
+        updateRealm();
+    }
+    
+    @Override
+    public boolean isAdminEventsEnabled() {
+        return realm.isAdminEventsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsEnabled(boolean enabled) {
+        realm.setAdminEventsEnabled(enabled);
+        updateRealm();
+        
+    }
+
+    @Override
+    public boolean isAdminEventsDetailsEnabled() {
+        return realm.isAdminEventsDetailsEnabled();
+    }
+
+    @Override
+    public void setAdminEventsDetailsEnabled(boolean enabled) {
+        realm.setAdminEventsDetailsEnabled(enabled);
+        updateRealm();
+    }
+    
+    @Override
+    public ClientModel getMasterAdminClient() {
+        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, realm.getMasterAdminClient(), invocationContext);
+        return appData != null ? new ClientAdapter(session, this, appData, invocationContext) : null;
+    }
+
+    @Override
+    public void setMasterAdminClient(ClientModel client) {
+        String adminAppId = client != null ? client.getId() : null;
+        realm.setMasterAdminClient(adminAppId);
+        updateRealm();
+    }
+
+    @Override
+    public MongoRealmEntity getMongoEntity() {
+        return realm;
+    }
+
+    @Override
+    public boolean isIdentityFederationEnabled() {
+        return this.realm.getIdentityProviders() != null && !this.realm.getIdentityProviders().isEmpty();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public boolean isInternationalizationEnabled() {
+        return realm.isInternationalizationEnabled();
+    }
+
+    @Override
+    public void setInternationalizationEnabled(boolean enabled) {
+        realm.setInternationalizationEnabled(enabled);
+        updateRealm();
+    }
+
+    @Override
+    public Set<String> getSupportedLocales() {
+        return new HashSet<String>(realm.getSupportedLocales());
+    }
+
+    @Override
+    public void setSupportedLocales(Set<String> locales) {
+        if (locales != null) {
+            realm.setSupportedLocales(new ArrayList<String>(locales));
+        } else {
+            realm.setSupportedLocales(Collections.EMPTY_LIST);
+        }
+        updateRealm();
+    }
+
+    @Override
+    public String getDefaultLocale() {
+        return realm.getDefaultLocale();
+    }
+
+    @Override
+    public void setDefaultLocale(String locale) {
+        realm.setDefaultLocale(locale);
+        updateRealm();
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
+            IdentityProviderMapperModel mapping = entityToModel(entity);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
+            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
+                continue;
+            }
+            IdentityProviderMapperModel mapping = entityToModel(entity);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
+        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
+            throw new RuntimeException("identity provider mapper name must be unique per identity provider");
+        }
+        String id = KeycloakModelUtils.generateId();
+        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
+        entity.setConfig(model.getConfig());
+
+        getMongoEntity().getIdentityProviderMappers().add(entity);
+        updateMongoEntity();
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
+        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
+        for (IdentityProviderMapperEntity entity : getMongoEntity().getIdentityProviderMappers()) {
+            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
+        if (toDelete != null) {
+            this.realm.getIdentityProviderMappers().remove(toDelete);
+            updateMongoEntity();
+        }
+    }
+
+    @Override
+    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
+        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapping.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        }
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
+        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+    @Override
+    public List<AuthenticationFlowModel> getAuthenticationFlows() {
+        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
+        List<AuthenticationFlowModel> models = new LinkedList<>();
+        for (AuthenticationFlowEntity entity : flows) {
+            AuthenticationFlowModel model = entityToModel(entity);
+            models.add(model);
+        }
+        return models;
+    }
+
+    @Override
+    public AuthenticationFlowModel getFlowByAlias(String alias) {
+        for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
+            if (flow.getAlias().equals(alias)) {
+                return flow;
+            }
+        }
+        return null;
+    }
+
+
+    protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
+        AuthenticationFlowModel model = new AuthenticationFlowModel();
+        model.setId(entity.getId());
+        model.setAlias(entity.getAlias());
+        model.setDescription(entity.getDescription());
+        model.setBuiltIn(entity.isBuiltIn());
+        model.setTopLevel(entity.isTopLevel());
+        return model;
+    }
+
+    @Override
+    public AuthenticationFlowModel getAuthenticationFlowById(String id) {
+        AuthenticationFlowEntity entity = getFlowEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected AuthenticationFlowEntity getFlowEntity(String id) {
+        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
+        for (AuthenticationFlowEntity entity : flows) {
+            if (id.equals(entity.getId())) return entity;
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity toDelete = getFlowEntity(model.getId());
+        if (toDelete == null) return;
+        getMongoEntity().getAuthenticationFlows().remove(toDelete);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void updateAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity toUpdate = getFlowEntity(model.getId());;
+        if (toUpdate == null) return;
+        toUpdate.setAlias(model.getAlias());
+        toUpdate.setDescription(model.getDescription());
+        toUpdate.setProviderId(model.getProviderId());
+        toUpdate.setBuiltIn(model.isBuiltIn());
+        toUpdate.setTopLevel(model.isTopLevel());
+        updateMongoEntity();
+    }
+
+    @Override
+    public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
+        AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        entity.setId(id);
+        entity.setAlias(model.getAlias());
+        entity.setDescription(model.getDescription());
+        entity.setProviderId(model.getProviderId());
+        entity.setBuiltIn(model.isBuiltIn());
+        entity.setTopLevel(model.isTopLevel());
+        getMongoEntity().getAuthenticationFlows().add(entity);
+        model.setId(entity.getId());
+        updateMongoEntity();
+        return model;
+    }
+
+    @Override
+    public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
+        AuthenticationFlowEntity flow = getFlowEntity(flowId);
+        if (flow == null) return Collections.EMPTY_LIST;
+
+        List<AuthenticationExecutionEntity> queryResult = flow.getExecutions();
+        List<AuthenticationExecutionModel> executions = new LinkedList<>();
+        for (AuthenticationExecutionEntity entity : queryResult) {
+            AuthenticationExecutionModel model = entityToModel(entity);
+            executions.add(model);
+        }
+        Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
+        return executions;
+    }
+
+    public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
+        AuthenticationExecutionModel model = new AuthenticationExecutionModel();
+        model.setId(entity.getId());
+        model.setUserSetupAllowed(entity.isUserSetupAllowed());
+        model.setRequirement(entity.getRequirement());
+        model.setPriority(entity.getPriority());
+        model.setAuthenticator(entity.getAuthenticator());
+        model.setFlowId(entity.getFlowId());
+        model.setParentFlow(entity.getParentFlow());
+        model.setAutheticatorFlow(entity.isAuthenticatorFlow());
+        model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
+        return model;
+    }
+
+    @Override
+    public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
+        AuthenticationExecutionEntity execution = getAuthenticationExecutionEntity(id);
+        return entityToModel(execution);
+    }
+
+    public AuthenticationExecutionEntity getAuthenticationExecutionEntity(String id) {
+        List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
+        for (AuthenticationFlowEntity entity : flows) {
+            for (AuthenticationExecutionEntity exe : entity.getExecutions()) {
+                if (exe.getId().equals(id)) {
+                   return exe;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        entity.setId(id);
+        entity.setAuthenticator(model.getAuthenticator());
+        entity.setPriority(model.getPriority());
+        entity.setRequirement(model.getRequirement());
+        entity.setUserSetupAllowed(model.isUserSetupAllowed());
+        entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+        entity.setFlowId(model.getFlowId());
+        entity.setParentFlow(model.getParentFlow());
+        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
+        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
+        flow.getExecutions().add(entity);
+        updateMongoEntity();
+        model.setId(entity.getId());
+        return model;
+
+    }
+
+    @Override
+    public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = null;
+        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
+        for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
+            if (exe.getId().equals(model.getId())) {
+                entity = exe;
+            }
+        }
+        if (entity == null) return;
+        entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+        entity.setAuthenticator(model.getAuthenticator());
+        entity.setPriority(model.getPriority());
+        entity.setRequirement(model.getRequirement());
+        entity.setFlowId(model.getFlowId());
+        entity.setUserSetupAllowed(model.isUserSetupAllowed());
+        entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
+        updateMongoEntity();
+    }
+
+    @Override
+    public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
+        AuthenticationExecutionEntity entity = null;
+        AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
+        for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
+            if (exe.getId().equals(model.getId())) {
+                entity = exe;
+            }
+        }
+        if (entity == null) return;
+        flow.getExecutions().remove(entity);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
+        List<AuthenticatorConfigModel> authenticators = new LinkedList<>();
+        for (AuthenticatorConfigEntity entity : getMongoEntity().getAuthenticatorConfigs()) {
+            authenticators.add(entityToModel(entity));
+        }
+        return authenticators;
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
+        for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
+            if (config.getAlias().equals(alias)) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+
+    @Override
+    public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity();
+        String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId();
+        auth.setId(id);
+        auth.setAlias(model.getAlias());
+        auth.setConfig(model.getConfig());
+        realm.getAuthenticatorConfigs().add(auth);
+        model.setId(auth.getId());
+        updateMongoEntity();
+        return model;
+    }
+
+    @Override
+    public void removeAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId());
+        if (entity == null) return;
+        getMongoEntity().getAuthenticatorConfigs().remove(entity);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
+        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    public AuthenticatorConfigEntity getAuthenticatorConfigEntity(String id) {
+        AuthenticatorConfigEntity entity = null;
+        for (AuthenticatorConfigEntity auth : getMongoEntity().getAuthenticatorConfigs()) {
+            if (auth.getId().equals(id)) {
+                entity = auth;
+                break;
+            }
+        }
+        return entity;
+    }
+
+    public AuthenticatorConfigModel entityToModel(AuthenticatorConfigEntity entity) {
+        AuthenticatorConfigModel model = new AuthenticatorConfigModel();
+        model.setId(entity.getId());
+        model.setAlias(entity.getAlias());
+        Map<String, String> config = new HashMap<>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        model.setConfig(config);
+        return model;
+    }
+
+    @Override
+    public void updateAuthenticatorConfig(AuthenticatorConfigModel model) {
+        AuthenticatorConfigEntity entity = getAuthenticatorConfigEntity(model.getId());
+        if (entity == null) return;
+        entity.setAlias(model.getAlias());
+        if (entity.getConfig() == null) {
+            entity.setConfig(model.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(model.getConfig());
+        }
+        updateMongoEntity();
+    }
+
+    @Override
+    public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity auth = new RequiredActionProviderEntity();
+        auth.setId(KeycloakModelUtils.generateId());
+        auth.setAlias(model.getAlias());
+        auth.setProviderId(model.getProviderId());
+        auth.setConfig(model.getConfig());
+        auth.setEnabled(model.isEnabled());
+        auth.setDefaultAction(model.isDefaultAction());
+        realm.getRequiredActionProviders().add(auth);
+        model.setId(auth.getId());
+        updateMongoEntity();
+        return model;
+    }
+
+    @Override
+    public void removeRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(model.getId());
+        if (entity == null) return;
+        getMongoEntity().getRequiredActionProviders().remove(entity);
+        updateMongoEntity();
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderById(String id) {
+        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    public RequiredActionProviderModel entityToModel(RequiredActionProviderEntity entity) {
+        RequiredActionProviderModel model = new RequiredActionProviderModel();
+        model.setId(entity.getId());
+        model.setProviderId(entity.getProviderId());
+        model.setAlias(entity.getAlias());
+        model.setEnabled(entity.isEnabled());
+        model.setDefaultAction(entity.isDefaultAction());
+        Map<String, String> config = new HashMap<>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        model.setConfig(config);
+        return model;
+    }
+
+    @Override
+    public void updateRequiredActionProvider(RequiredActionProviderModel model) {
+        RequiredActionProviderEntity entity = getRequiredActionProviderEntity(model.getId());
+        if (entity == null) return;
+        entity.setAlias(model.getAlias());
+        entity.setProviderId(model.getProviderId());
+        entity.setEnabled(model.isEnabled());
+        entity.setDefaultAction(model.isDefaultAction());
+        if (entity.getConfig() == null) {
+            entity.setConfig(model.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(model.getConfig());
+        }
+        updateMongoEntity();
+    }
+
+    @Override
+    public List<RequiredActionProviderModel> getRequiredActionProviders() {
+        List<RequiredActionProviderModel> actions = new LinkedList<>();
+        for (RequiredActionProviderEntity entity : realm.getRequiredActionProviders()) {
+            actions.add(entityToModel(entity));
+        }
+        return actions;
+    }
+
+    public RequiredActionProviderEntity getRequiredActionProviderEntity(String id) {
+        RequiredActionProviderEntity entity = null;
+        for (RequiredActionProviderEntity auth : getMongoEntity().getRequiredActionProviders()) {
+            if (auth.getId().equals(id)) {
+                entity = auth;
+                break;
+            }
+        }
+        return entity;
+    }
+
+    @Override
+    public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
+        for (RequiredActionProviderModel action : getRequiredActionProviders()) {
+            if (action.getAlias().equals(alias)) return action;
+        }
+        return null;
+    }
+
+
+
+
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappers() {
+        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
+        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
+            UserFederationMapperModel mapper = entityToModel(entity);
+            mappers.add(mapper);
+        }
+        return mappers;
+    }
+
+    @Override
+    public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
+        Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
+        Set<UserFederationMapperEntity> mapperEntities = getUserFederationMapperEntitiesByFederationProvider(federationProviderId);
+        for (UserFederationMapperEntity entity : mapperEntities) {
+            mappers.add(entityToModel(entity));
+        }
+        return mappers;
+    }
+
+    @Override
+    public UserFederationMapperModel addUserFederationMapper(UserFederationMapperModel model) {
+        if (getUserFederationMapperByName(model.getFederationProviderId(), model.getName()) != null) {
+            throw new ModelDuplicateException("User federation mapper must be unique per federation provider. There is already: " + model.getName());
+        }
+        String id = KeycloakModelUtils.generateId();
+        UserFederationMapperEntity entity = new UserFederationMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setFederationProviderId(model.getFederationProviderId());
+        entity.setFederationMapperType(model.getFederationMapperType());
+        entity.setConfig(model.getConfig());
+
+        getMongoEntity().getUserFederationMappers().add(entity);
+        updateMongoEntity();
+        UserFederationMapperModel mapperModel = entityToModel(entity);
+
+        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapperModel, this, session));
+
+        return mapperModel;
+    }
+
+    protected UserFederationMapperEntity getUserFederationMapperEntity(String id) {
+        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected UserFederationMapperEntity getUserFederationMapperEntityByName(String federationProviderId, String name) {
+        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
+            if (entity.getFederationProviderId().equals(federationProviderId) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected Set<UserFederationMapperEntity> getUserFederationMapperEntitiesByFederationProvider(String federationProviderId) {
+        Set<UserFederationMapperEntity> mappers = new HashSet<UserFederationMapperEntity>();
+        for (UserFederationMapperEntity entity : getMongoEntity().getUserFederationMappers()) {
+            if (federationProviderId.equals(entity.getFederationProviderId())) {
+                mappers.add(entity);
+            }
+        }
+        return mappers;
+    }
+
+    @Override
+    public void removeUserFederationMapper(UserFederationMapperModel mapper) {
+        UserFederationMapperEntity toDelete = getUserFederationMapperEntity(mapper.getId());
+        if (toDelete != null) {
+            this.realm.getUserFederationMappers().remove(toDelete);
+            updateMongoEntity();
+        }
+    }
+
+    @Override
+    public void updateUserFederationMapper(UserFederationMapperModel mapper) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntity(mapper.getId());
+        entity.setFederationProviderId(mapper.getFederationProviderId());
+        entity.setFederationMapperType(mapper.getFederationMapperType());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapper.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapper.getConfig());
+        }
+        updateMongoEntity();
+
+        session.getKeycloakSessionFactory().publish(new UserFederationMapperEventImpl(mapper, this, session));
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperById(String id) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
+        UserFederationMapperEntity entity = getUserFederationMapperEntityByName(federationProviderId, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
+        UserFederationMapperModel mapper = new UserFederationMapperModel();
+        mapper.setId(entity.getId());
+        mapper.setName(entity.getName());
+        mapper.setFederationProviderId(entity.getFederationProviderId());
+        mapper.setFederationMapperType(entity.getFederationMapperType());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapper.setConfig(config);
+        return mapper;
+    }
+}
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 e087225..f63494b 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
@@ -1,575 +1,575 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.entities.CredentialEntity;
-import org.keycloak.models.entities.UserConsentEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
-import org.keycloak.models.mongo.utils.MongoModelUtils;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
-import org.keycloak.util.Time;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implements UserModel {
-    
-    private final MongoUserEntity user;
-    private final RealmModel realm;
-    private final KeycloakSession session;
-
-    public UserAdapter(KeycloakSession session, RealmModel realm, MongoUserEntity userEntity, MongoStoreInvocationContext invContext) {
-        super(invContext);
-        this.user = userEntity;
-        this.realm = realm;
-        this.session = session;
-    }
-
-    @Override
-    public String getId() {
-        return user.getId();
-    }
-
-    @Override
-    public String getUsername() {
-        return user.getUsername();
-    }
-
-    @Override
-    public void setUsername(String username) {
-        user.setUsername(username);
-        updateUser();
-    }
-
-    @Override
-    public Long getCreatedTimestamp() {
-        return user.getCreatedTimestamp();
-    }
-
-    @Override
-    public void setCreatedTimestamp(Long timestamp) {
-        user.setCreatedTimestamp(timestamp);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return user.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        user.setEnabled(enabled);
-        updateUser();
-    }
-
-    @Override
-    public String getFirstName() {
-        return user.getFirstName();
-    }
-
-    @Override
-    public void setFirstName(String firstName) {
-        user.setFirstName(firstName);
-        updateUser();
-    }
-
-    @Override
-    public String getLastName() {
-        return user.getLastName();
-    }
-
-    @Override
-    public void setLastName(String lastName) {
-        user.setLastName(lastName);
-        updateUser();
-    }
-
-    @Override
-    public String getEmail() {
-        return user.getEmail();
-    }
-
-    @Override
-    public void setEmail(String email) {
-        user.setEmail(email);
-        updateUser();
-    }
-
-    @Override
-    public boolean isEmailVerified() {
-        return user.isEmailVerified();
-    }
-
-    @Override
-    public void setEmailVerified(boolean verified) {
-        user.setEmailVerified(verified);
-        updateUser();
-    }
-
-    @Override
-    public void setSingleAttribute(String name, String value) {
-        if (user.getAttributes() == null) {
-            user.setAttributes(new HashMap<String, List<String>>());
-        }
-
-        List<String> attrValues = new ArrayList<>();
-        attrValues.add(value);
-        user.getAttributes().put(name, attrValues);
-        updateUser();
-    }
-
-    @Override
-    public void setAttribute(String name, List<String> values) {
-        if (user.getAttributes() == null) {
-            user.setAttributes(new HashMap<String, List<String>>());
-        }
-
-        user.getAttributes().put(name, values);
-        updateUser();
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        if (user.getAttributes() == null) return;
-
-        user.getAttributes().remove(name);
-        updateUser();
-    }
-
-    @Override
-    public String getFirstAttribute(String name) {
-        if (user.getAttributes()==null) return null;
-
-        List<String> attrValues = user.getAttributes().get(name);
-        return (attrValues==null || attrValues.isEmpty()) ? null : attrValues.get(0);
-    }
-
-    @Override
-    public List<String> getAttribute(String name) {
-        if (user.getAttributes()==null) return Collections.<String>emptyList();
-        List<String> attrValues = user.getAttributes().get(name);
-        return (attrValues == null) ? Collections.<String>emptyList() : Collections.unmodifiableList(attrValues);
-    }
-
-    @Override
-    public Map<String, List<String>> getAttributes() {
-        return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map)user.getAttributes());
-    }
-
-    public MongoUserEntity getUser() {
-        return user;
-    }
-
-
-    @Override
-    public Set<String> getRequiredActions() {
-        Set<String> result = new HashSet<String>();
-        if (user.getRequiredActions() != null) {
-            result.addAll(user.getRequiredActions());
-        }
-        return result;
-    }
-
-    @Override
-    public void addRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        addRequiredAction(actionName);
-    }
-
-    @Override
-    public void addRequiredAction(String actionName) {
-        getMongoStore().pushItemToList(user, "requiredActions", actionName, true, invocationContext);
-    }
-
-    @Override
-    public void removeRequiredAction(RequiredAction action) {
-        String actionName = action.name();
-        removeRequiredAction(actionName);
-    }
-
-    @Override
-    public void removeRequiredAction(String actionName) {
-        getMongoStore().pullItemFromList(user, "requiredActions", actionName, invocationContext);
-    }
-
-    @Override
-    public boolean isTotp() {
-        return user.isTotp();
-    }
-
-    @Override
-    public void setTotp(boolean totp) {
-        user.setTotp(totp);
-        updateUser();
-    }
-
-    @Override
-    public void updateCredential(UserCredentialModel cred) {
-
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            updatePasswordCredential(cred);
-        } else {
-            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-            if (credentialEntity == null) {
-                credentialEntity = setCredentials(user, cred);
-                credentialEntity.setValue(cred.getValue());
-                user.getCredentials().add(credentialEntity);
-            } else {
-                credentialEntity.setValue(cred.getValue());
-            }
-        }
-        getMongoStore().updateEntity(user, invocationContext);
-    }
-
-    private void updatePasswordCredential(UserCredentialModel cred) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = setCredentials(user, cred);
-            setValue(credentialEntity, cred);
-            user.getCredentials().add(credentialEntity);
-        } else {
-
-            int expiredPasswordsPolicyValue = -1;
-            PasswordPolicy policy = realm.getPasswordPolicy();
-            if(policy != null) {
-                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
-            }
-            
-            if (expiredPasswordsPolicyValue != -1) {
-                user.getCredentials().remove(credentialEntity);
-                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
-                user.getCredentials().add(credentialEntity);
-
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
-                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
-                }
-
-                credentialEntity = setCredentials(user, cred);
-                setValue(credentialEntity, cred);
-                user.getCredentials().add(credentialEntity);
-            } else {
-                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
-                if (credentialEntities != null && credentialEntities.size() > 0) {
-                    user.getCredentials().removeAll(credentialEntities);
-                }
-                setValue(credentialEntity, cred);
-            }
-        }
-    }
-    
-    private CredentialEntity setCredentials(MongoUserEntity user, UserCredentialModel cred) {
-        CredentialEntity credentialEntity = new CredentialEntity();
-        credentialEntity.setType(cred.getType());
-        credentialEntity.setDevice(cred.getDevice());
-        return credentialEntity;
-    }
-
-    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
-        byte[] salt = getSalt();
-        int hashIterations = 1;
-        PasswordPolicy policy = realm.getPasswordPolicy();
-        if (policy != null) {
-            hashIterations = policy.getHashIterations();
-            if (hashIterations == -1)
-                hashIterations = 1;
-        }
-        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
-        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
-        credentialEntity.setSalt(salt);
-        credentialEntity.setHashIterations(hashIterations);
-    }
-
-    private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                return entity;
-            }
-        }
-
-        return null;
-    }
-
-    private List<CredentialEntity> getCredentialEntities(MongoUserEntity userEntity, String credType) {
-        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                credentialEntities.add(entity);
-            }
-        }
-        
-        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
-        // Orders from most recent to least recent
-        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
-            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
-                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
-                    return -1;
-                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-        });
-        return credentialEntities;
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly() {
-        List<CredentialEntity> credentials = user.getCredentials();
-        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
-        for (CredentialEntity credEntity : credentials) {
-            UserCredentialValueModel credModel = new UserCredentialValueModel();
-            credModel.setType(credEntity.getType());
-            credModel.setDevice(credEntity.getDevice());
-            credModel.setCreatedDate(credEntity.getCreatedDate());
-            credModel.setValue(credEntity.getValue());
-            credModel.setSalt(credEntity.getSalt());
-            credModel.setHashIterations(credEntity.getHashIterations());
-
-            result.add(credModel);
-        }
-
-        return result;
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
-        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setType(credModel.getType());
-            credModel.setCreatedDate(credModel.getCreatedDate());
-            user.getCredentials().add(credentialEntity);
-        }
-
-        credentialEntity.setValue(credModel.getValue());
-        credentialEntity.setSalt(credModel.getSalt());
-        credentialEntity.setDevice(credModel.getDevice());
-        credentialEntity.setHashIterations(credModel.getHashIterations());
-
-
-        getMongoStore().updateEntity(user, invocationContext);
-    }
-
-    protected void updateUser() {
-        super.updateMongoEntity();
-    }
-
-    @Override
-    public MongoUserEntity getMongoEntity() {
-        return user;
-    }
-
-    @Override
-    public boolean hasRole(RoleModel role) {
-        Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
-    }
-
-    @Override
-    public void grantRole(RoleModel role) {
-        getMongoStore().pushItemToList(getUser(), "roleIds", role.getId(), true, invocationContext);
-    }
-
-    @Override
-    public Set<RoleModel> getRoleMappings() {
-        List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
-        return new HashSet<RoleModel>(roles);
-    }
-
-    @Override
-    public Set<RoleModel> getRealmRoleMappings() {
-        Set<RoleModel> allRoles = getRoleMappings();
-
-        // Filter to retrieve just realm roles
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allRoles) {
-            if (role.getContainer() instanceof RealmModel) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public void deleteRoleMapping(RoleModel role) {
-        if (user == null || role == null) return;
-
-        getMongoStore().pullItemFromList(getUser(), "roleIds", role.getId(), invocationContext);
-    }
-
-    @Override
-    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        Set<RoleModel> result = new HashSet<RoleModel>();
-        List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
-
-        for (RoleModel role : roles) {
-            if (app.equals(role.getContainer())) {
-                result.add(role);
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public String getFederationLink() {
-        return user.getFederationLink();
-    }
-
-    @Override
-    public void setFederationLink(String link) {
-        user.setFederationLink(link);
-        updateUser();
-    }
-
-    @Override
-    public void addConsent(UserConsentModel consent) {
-        String clientId = consent.getClient().getId();
-        if (getConsentEntityByClientId(clientId) != null) {
-            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
-        }
-
-        MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
-        consentEntity.setUserId(getId());
-        consentEntity.setClientId(clientId);
-        fillEntityFromModel(consent, consentEntity);
-        getMongoStore().insertEntity(consentEntity, invocationContext);
-    }
-
-    @Override
-    public UserConsentModel getConsentByClient(String clientId) {
-        UserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
-        return consentEntity!=null ? toConsentModel(consentEntity) : null;
-    }
-
-    @Override
-    public List<UserConsentModel> getConsents() {
-        List<UserConsentModel> result = new ArrayList<UserConsentModel>();
-
-        DBObject query = new QueryBuilder()
-                .and("userId").is(getId())
-                .get();
-        List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
-
-        for (UserConsentEntity consentEntity : grantedConsents) {
-            UserConsentModel model = toConsentModel(consentEntity);
-            result.add(model);
-        }
-
-        return result;
-    }
-
-    private MongoUserConsentEntity getConsentEntityByClientId(String clientId) {
-        DBObject query = new QueryBuilder()
-                .and("userId").is(getId())
-                .and("clientId").is(clientId)
-                .get();
-        return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
-    }
-
-    private UserConsentModel toConsentModel(UserConsentEntity entity) {
-        ClientModel client = realm.getClientById(entity.getClientId());
-        if (client == null) {
-            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
-        }
-        UserConsentModel model = new UserConsentModel(client);
-
-        for (String roleId : entity.getGrantedRoles()) {
-            RoleModel roleModel = realm.getRoleById(roleId);
-            if (roleModel != null) {
-                model.addGrantedRole(roleModel);
-            }
-        }
-
-        for (String protMapperId : entity.getGrantedProtocolMappers()) {
-            ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId);
-            model.addGrantedProtocolMapper(protocolMapper);
-        }
-        return model;
-    }
-
-    // Fill roles and protocolMappers to entity
-    private void fillEntityFromModel(UserConsentModel consent, MongoUserConsentEntity consentEntity) {
-        List<String> roleIds = new LinkedList<String>();
-        for (RoleModel role : consent.getGrantedRoles()) {
-            roleIds.add(role.getId());
-        }
-        consentEntity.setGrantedRoles(roleIds);
-
-        List<String> protMapperIds = new LinkedList<String>();
-        for (ProtocolMapperModel protMapperModel : consent.getGrantedProtocolMappers()) {
-            protMapperIds.add(protMapperModel.getId());
-        }
-        consentEntity.setGrantedProtocolMappers(protMapperIds);
-    }
-
-    @Override
-    public void updateConsent(UserConsentModel consent) {
-        String clientId = consent.getClient().getId();
-        MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
-        if (consentEntity == null) {
-            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
-        } else {
-            fillEntityFromModel(consent, consentEntity);
-            getMongoStore().updateEntity(consentEntity, invocationContext);
-        }
-    }
-
-    @Override
-    public boolean revokeConsentForClient(String clientId) {
-        MongoUserConsentEntity entity = getConsentEntityByClientId(clientId);
-        if (entity == null) {
-            return false;
-        }
-
-        return getMongoStore().removeEntity(entity, invocationContext);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof UserModel)) return false;
-
-        UserModel that = (UserModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.CredentialEntity;
+import org.keycloak.models.entities.UserConsentEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
+import org.keycloak.models.mongo.utils.MongoModelUtils;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
+import org.keycloak.util.Time;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implements UserModel {
+    
+    private final MongoUserEntity user;
+    private final RealmModel realm;
+    private final KeycloakSession session;
+
+    public UserAdapter(KeycloakSession session, RealmModel realm, MongoUserEntity userEntity, MongoStoreInvocationContext invContext) {
+        super(invContext);
+        this.user = userEntity;
+        this.realm = realm;
+        this.session = session;
+    }
+
+    @Override
+    public String getId() {
+        return user.getId();
+    }
+
+    @Override
+    public String getUsername() {
+        return user.getUsername();
+    }
+
+    @Override
+    public void setUsername(String username) {
+        user.setUsername(username);
+        updateUser();
+    }
+
+    @Override
+    public Long getCreatedTimestamp() {
+        return user.getCreatedTimestamp();
+    }
+
+    @Override
+    public void setCreatedTimestamp(Long timestamp) {
+        user.setCreatedTimestamp(timestamp);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return user.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        user.setEnabled(enabled);
+        updateUser();
+    }
+
+    @Override
+    public String getFirstName() {
+        return user.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        user.setFirstName(firstName);
+        updateUser();
+    }
+
+    @Override
+    public String getLastName() {
+        return user.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        user.setLastName(lastName);
+        updateUser();
+    }
+
+    @Override
+    public String getEmail() {
+        return user.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        user.setEmail(email);
+        updateUser();
+    }
+
+    @Override
+    public boolean isEmailVerified() {
+        return user.isEmailVerified();
+    }
+
+    @Override
+    public void setEmailVerified(boolean verified) {
+        user.setEmailVerified(verified);
+        updateUser();
+    }
+
+    @Override
+    public void setSingleAttribute(String name, String value) {
+        if (user.getAttributes() == null) {
+            user.setAttributes(new HashMap<String, List<String>>());
+        }
+
+        List<String> attrValues = new ArrayList<>();
+        attrValues.add(value);
+        user.getAttributes().put(name, attrValues);
+        updateUser();
+    }
+
+    @Override
+    public void setAttribute(String name, List<String> values) {
+        if (user.getAttributes() == null) {
+            user.setAttributes(new HashMap<String, List<String>>());
+        }
+
+        user.getAttributes().put(name, values);
+        updateUser();
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        if (user.getAttributes() == null) return;
+
+        user.getAttributes().remove(name);
+        updateUser();
+    }
+
+    @Override
+    public String getFirstAttribute(String name) {
+        if (user.getAttributes()==null) return null;
+
+        List<String> attrValues = user.getAttributes().get(name);
+        return (attrValues==null || attrValues.isEmpty()) ? null : attrValues.get(0);
+    }
+
+    @Override
+    public List<String> getAttribute(String name) {
+        if (user.getAttributes()==null) return Collections.<String>emptyList();
+        List<String> attrValues = user.getAttributes().get(name);
+        return (attrValues == null) ? Collections.<String>emptyList() : Collections.unmodifiableList(attrValues);
+    }
+
+    @Override
+    public Map<String, List<String>> getAttributes() {
+        return user.getAttributes()==null ? Collections.<String, List<String>>emptyMap() : Collections.unmodifiableMap((Map)user.getAttributes());
+    }
+
+    public MongoUserEntity getUser() {
+        return user;
+    }
+
+
+    @Override
+    public Set<String> getRequiredActions() {
+        Set<String> result = new HashSet<String>();
+        if (user.getRequiredActions() != null) {
+            result.addAll(user.getRequiredActions());
+        }
+        return result;
+    }
+
+    @Override
+    public void addRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        addRequiredAction(actionName);
+    }
+
+    @Override
+    public void addRequiredAction(String actionName) {
+        getMongoStore().pushItemToList(user, "requiredActions", actionName, true, invocationContext);
+    }
+
+    @Override
+    public void removeRequiredAction(RequiredAction action) {
+        String actionName = action.name();
+        removeRequiredAction(actionName);
+    }
+
+    @Override
+    public void removeRequiredAction(String actionName) {
+        getMongoStore().pullItemFromList(user, "requiredActions", actionName, invocationContext);
+    }
+
+    @Override
+    public boolean isTotp() {
+        return user.isTotp();
+    }
+
+    @Override
+    public void setTotp(boolean totp) {
+        user.setTotp(totp);
+        updateUser();
+    }
+
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            updatePasswordCredential(cred);
+        } else {
+            CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+            if (credentialEntity == null) {
+                credentialEntity = setCredentials(user, cred);
+                credentialEntity.setValue(cred.getValue());
+                user.getCredentials().add(credentialEntity);
+            } else {
+                credentialEntity.setValue(cred.getValue());
+            }
+        }
+        getMongoStore().updateEntity(user, invocationContext);
+    }
+
+    private void updatePasswordCredential(UserCredentialModel cred) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = setCredentials(user, cred);
+            setValue(credentialEntity, cred);
+            user.getCredentials().add(credentialEntity);
+        } else {
+
+            int expiredPasswordsPolicyValue = -1;
+            PasswordPolicy policy = realm.getPasswordPolicy();
+            if(policy != null) {
+                expiredPasswordsPolicyValue = policy.getExpiredPasswords();
+            }
+            
+            if (expiredPasswordsPolicyValue != -1) {
+                user.getCredentials().remove(credentialEntity);
+                credentialEntity.setType(UserCredentialModel.PASSWORD_HISTORY);
+                user.getCredentials().add(credentialEntity);
+
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities.size() > expiredPasswordsPolicyValue - 1) {
+                    user.getCredentials().removeAll(credentialEntities.subList(expiredPasswordsPolicyValue - 1, credentialEntities.size()));
+                }
+
+                credentialEntity = setCredentials(user, cred);
+                setValue(credentialEntity, cred);
+                user.getCredentials().add(credentialEntity);
+            } else {
+                List<CredentialEntity> credentialEntities = getCredentialEntities(user, UserCredentialModel.PASSWORD_HISTORY);
+                if (credentialEntities != null && credentialEntities.size() > 0) {
+                    user.getCredentials().removeAll(credentialEntities);
+                }
+                setValue(credentialEntity, cred);
+            }
+        }
+    }
+    
+    private CredentialEntity setCredentials(MongoUserEntity user, UserCredentialModel cred) {
+        CredentialEntity credentialEntity = new CredentialEntity();
+        credentialEntity.setType(cred.getType());
+        credentialEntity.setDevice(cred.getDevice());
+        return credentialEntity;
+    }
+
+    private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
+        byte[] salt = getSalt();
+        int hashIterations = 1;
+        PasswordPolicy policy = realm.getPasswordPolicy();
+        if (policy != null) {
+            hashIterations = policy.getHashIterations();
+            if (hashIterations == -1)
+                hashIterations = 1;
+        }
+        credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
+        credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
+        credentialEntity.setSalt(salt);
+        credentialEntity.setHashIterations(hashIterations);
+    }
+
+    private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                return entity;
+            }
+        }
+
+        return null;
+    }
+
+    private List<CredentialEntity> getCredentialEntities(MongoUserEntity userEntity, String credType) {
+        List<CredentialEntity> credentialEntities = new ArrayList<CredentialEntity>();
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                credentialEntities.add(entity);
+            }
+        }
+        
+        // Avoiding direct use of credSecond.getCreatedDate() - credFirst.getCreatedDate() to prevent Integer Overflow
+        // Orders from most recent to least recent
+        Collections.sort(credentialEntities, new Comparator<CredentialEntity>() {
+            public int compare(CredentialEntity credFirst, CredentialEntity credSecond) {
+                if (credFirst.getCreatedDate() > credSecond.getCreatedDate()) {
+                    return -1;
+                } else if (credFirst.getCreatedDate() < credSecond.getCreatedDate()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+        return credentialEntities;
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        List<CredentialEntity> credentials = user.getCredentials();
+        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
+        for (CredentialEntity credEntity : credentials) {
+            UserCredentialValueModel credModel = new UserCredentialValueModel();
+            credModel.setType(credEntity.getType());
+            credModel.setDevice(credEntity.getDevice());
+            credModel.setCreatedDate(credEntity.getCreatedDate());
+            credModel.setValue(credEntity.getValue());
+            credModel.setSalt(credEntity.getSalt());
+            credModel.setHashIterations(credEntity.getHashIterations());
+
+            result.add(credModel);
+        }
+
+        return result;
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setType(credModel.getType());
+            credModel.setCreatedDate(credModel.getCreatedDate());
+            user.getCredentials().add(credentialEntity);
+        }
+
+        credentialEntity.setValue(credModel.getValue());
+        credentialEntity.setSalt(credModel.getSalt());
+        credentialEntity.setDevice(credModel.getDevice());
+        credentialEntity.setHashIterations(credModel.getHashIterations());
+
+
+        getMongoStore().updateEntity(user, invocationContext);
+    }
+
+    protected void updateUser() {
+        super.updateMongoEntity();
+    }
+
+    @Override
+    public MongoUserEntity getMongoEntity() {
+        return user;
+    }
+
+    @Override
+    public boolean hasRole(RoleModel role) {
+        Set<RoleModel> roles = getRoleMappings();
+        return KeycloakModelUtils.hasRole(roles, role);
+    }
+
+    @Override
+    public void grantRole(RoleModel role) {
+        getMongoStore().pushItemToList(getUser(), "roleIds", role.getId(), true, invocationContext);
+    }
+
+    @Override
+    public Set<RoleModel> getRoleMappings() {
+        List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
+        return new HashSet<RoleModel>(roles);
+    }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings() {
+        Set<RoleModel> allRoles = getRoleMappings();
+
+        // Filter to retrieve just realm roles
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allRoles) {
+            if (role.getContainer() instanceof RealmModel) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void deleteRoleMapping(RoleModel role) {
+        if (user == null || role == null) return;
+
+        getMongoStore().pullItemFromList(getUser(), "roleIds", role.getId(), invocationContext);
+    }
+
+    @Override
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        List<RoleModel> roles = MongoModelUtils.getAllRolesOfUser(realm, this);
+
+        for (RoleModel role : roles) {
+            if (app.equals(role.getContainer())) {
+                result.add(role);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String getFederationLink() {
+        return user.getFederationLink();
+    }
+
+    @Override
+    public void setFederationLink(String link) {
+        user.setFederationLink(link);
+        updateUser();
+    }
+
+    @Override
+    public void addConsent(UserConsentModel consent) {
+        String clientId = consent.getClient().getId();
+        if (getConsentEntityByClientId(clientId) != null) {
+            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+        }
+
+        MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
+        consentEntity.setUserId(getId());
+        consentEntity.setClientId(clientId);
+        fillEntityFromModel(consent, consentEntity);
+        getMongoStore().insertEntity(consentEntity, invocationContext);
+    }
+
+    @Override
+    public UserConsentModel getConsentByClient(String clientId) {
+        UserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
+        return consentEntity!=null ? toConsentModel(consentEntity) : null;
+    }
+
+    @Override
+    public List<UserConsentModel> getConsents() {
+        List<UserConsentModel> result = new ArrayList<UserConsentModel>();
+
+        DBObject query = new QueryBuilder()
+                .and("userId").is(getId())
+                .get();
+        List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
+
+        for (UserConsentEntity consentEntity : grantedConsents) {
+            UserConsentModel model = toConsentModel(consentEntity);
+            result.add(model);
+        }
+
+        return result;
+    }
+
+    private MongoUserConsentEntity getConsentEntityByClientId(String clientId) {
+        DBObject query = new QueryBuilder()
+                .and("userId").is(getId())
+                .and("clientId").is(clientId)
+                .get();
+        return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
+    }
+
+    private UserConsentModel toConsentModel(UserConsentEntity entity) {
+        ClientModel client = realm.getClientById(entity.getClientId());
+        if (client == null) {
+            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+        }
+        UserConsentModel model = new UserConsentModel(client);
+
+        for (String roleId : entity.getGrantedRoles()) {
+            RoleModel roleModel = realm.getRoleById(roleId);
+            if (roleModel != null) {
+                model.addGrantedRole(roleModel);
+            }
+        }
+
+        for (String protMapperId : entity.getGrantedProtocolMappers()) {
+            ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId);
+            model.addGrantedProtocolMapper(protocolMapper);
+        }
+        return model;
+    }
+
+    // Fill roles and protocolMappers to entity
+    private void fillEntityFromModel(UserConsentModel consent, MongoUserConsentEntity consentEntity) {
+        List<String> roleIds = new LinkedList<String>();
+        for (RoleModel role : consent.getGrantedRoles()) {
+            roleIds.add(role.getId());
+        }
+        consentEntity.setGrantedRoles(roleIds);
+
+        List<String> protMapperIds = new LinkedList<String>();
+        for (ProtocolMapperModel protMapperModel : consent.getGrantedProtocolMappers()) {
+            protMapperIds.add(protMapperModel.getId());
+        }
+        consentEntity.setGrantedProtocolMappers(protMapperIds);
+    }
+
+    @Override
+    public void updateConsent(UserConsentModel consent) {
+        String clientId = consent.getClient().getId();
+        MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
+        if (consentEntity == null) {
+            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+        } else {
+            fillEntityFromModel(consent, consentEntity);
+            getMongoStore().updateEntity(consentEntity, invocationContext);
+        }
+    }
+
+    @Override
+    public boolean revokeConsentForClient(String clientId) {
+        MongoUserConsentEntity entity = getConsentEntityByClientId(clientId);
+        if (entity == null) {
+            return false;
+        }
+
+        return getMongoStore().removeEntity(entity, invocationContext);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserModel)) return false;
+
+        UserModel that = (UserModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
index 8c12715..40b47d8 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoClientEntity.java
@@ -1,24 +1,24 @@
-package org.keycloak.models.mongo.keycloak.entities;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.entities.ClientEntity;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-@MongoCollection(collectionName = "clients")
-public class MongoClientEntity extends ClientEntity implements MongoIdentifiableEntity {
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext context) {
-        // Remove all roles, which belongs to this application
-        DBObject query = new QueryBuilder()
-                .and("clientId").is(getId())
-                .get();
-        context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
-    }
-}
+package org.keycloak.models.mongo.keycloak.entities;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.ClientEntity;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@MongoCollection(collectionName = "clients")
+public class MongoClientEntity extends ClientEntity implements MongoIdentifiableEntity {
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext context) {
+        // Remove all roles, which belongs to this application
+        DBObject query = new QueryBuilder()
+                .and("clientId").is(getId())
+                .get();
+        context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoMigrationModelEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoMigrationModelEntity.java
index 2eadc11..7c6ff4b 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoMigrationModelEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoMigrationModelEntity.java
@@ -1,40 +1,40 @@
-package org.keycloak.models.mongo.keycloak.entities;
-
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@MongoCollection(collectionName = "migrationModel")
-public class MongoMigrationModelEntity implements MongoIdentifiableEntity  {
-    public static final String MIGRATION_MODEL_ID = "VERSION";
-    private String id = MIGRATION_MODEL_ID;
-    private String version;
-
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
-
-    @Override
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public void setId(String id) {
-        this.id = id;
-
-    }
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext invocationContext) {
-
-    }
-}
+package org.keycloak.models.mongo.keycloak.entities;
+
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@MongoCollection(collectionName = "migrationModel")
+public class MongoMigrationModelEntity implements MongoIdentifiableEntity  {
+    public static final String MIGRATION_MODEL_ID = "VERSION";
+    private String id = MIGRATION_MODEL_ID;
+    private String version;
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(String id) {
+        this.id = id;
+
+    }
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext invocationContext) {
+
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
index a64c2b5..8269360 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
@@ -1,28 +1,28 @@
-package org.keycloak.models.mongo.keycloak.entities;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.entities.RealmEntity;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-@MongoCollection(collectionName = "realms")
-public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEntity {
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext context) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .get();
-
-        // Remove all roles of this realm
-        context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
-
-        // Remove all clients of this realm
-        context.getMongoStore().removeEntities(MongoClientEntity.class, query, true, context);
-    }
-}
+package org.keycloak.models.mongo.keycloak.entities;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.RealmEntity;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@MongoCollection(collectionName = "realms")
+public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEntity {
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext context) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(getId())
+                .get();
+
+        // Remove all roles of this realm
+        context.getMongoStore().removeEntities(MongoRoleEntity.class, query, true, context);
+
+        // Remove all clients of this realm
+        context.getMongoStore().removeEntities(MongoClientEntity.class, query, true, context);
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
index 2021069..29491f8 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
@@ -1,84 +1,84 @@
-package org.keycloak.models.mongo.keycloak.entities;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.jboss.logging.Logger;
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoField;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.MongoStore;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.entities.RoleEntity;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-@MongoCollection(collectionName = "roles")
-public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEntity {
-
-    private static final Logger logger = Logger.getLogger(MongoRoleEntity.class);
-
-    @MongoField
-    // TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193)
-    public String getNameIndex() {
-        String realmId = getRealmId();
-        String clientId = getClientId();
-        String name = getName();
-
-        if (realmId != null) {
-            return realmId + "//" + name;
-        } else {
-            return clientId + "//" + name;
-        }
-    }
-
-    public void setNameIndex(String ignored) {
-    }
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext invContext) {
-        MongoStore mongoStore = invContext.getMongoStore();
-
-        // Remove this scope from all clients, which has it
-        DBObject query = new QueryBuilder()
-                .and("scopeIds").is(getId())
-                .get();
-
-        List<MongoClientEntity> clients = mongoStore.loadEntities(MongoClientEntity.class, query, invContext);
-        for (MongoClientEntity client : clients) {
-            //logger.info("Removing scope " + getName() + " from user " + user.getUsername());
-            mongoStore.pullItemFromList(client, "scopeIds", getId(), invContext);
-        }
-
-        // Remove defaultRoles from realm
-        if (getRealmId() != null) {
-            MongoRealmEntity realmEntity = mongoStore.loadEntity(MongoRealmEntity.class, getRealmId(), invContext);
-
-            // Realm might be already removed at this point
-            if (realmEntity != null) {
-                mongoStore.pullItemFromList(realmEntity, "defaultRoles", getName(), invContext);
-            }
-        }
-
-        // Remove defaultRoles from application
-        if (getClientId() != null) {
-            MongoClientEntity appEntity = mongoStore.loadEntity(MongoClientEntity.class, getClientId(), invContext);
-
-            // Application might be already removed at this point
-            if (appEntity != null) {
-                mongoStore.pullItemFromList(appEntity, "defaultRoles", getName(), invContext);
-            }
-        }
-
-        // Remove this role from others who has it as composite
-        query = new QueryBuilder()
-                .and("compositeRoleIds").is(getId())
-                .get();
-        List<MongoRoleEntity> parentRoles = mongoStore.loadEntities(MongoRoleEntity.class, query, invContext);
-        for (MongoRoleEntity role : parentRoles) {
-            mongoStore.pullItemFromList(role, "compositeRoleIds", getId(), invContext);
-        }
-    }
-}
+package org.keycloak.models.mongo.keycloak.entities;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.jboss.logging.Logger;
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoField;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.MongoStore;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.RoleEntity;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@MongoCollection(collectionName = "roles")
+public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEntity {
+
+    private static final Logger logger = Logger.getLogger(MongoRoleEntity.class);
+
+    @MongoField
+    // TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193)
+    public String getNameIndex() {
+        String realmId = getRealmId();
+        String clientId = getClientId();
+        String name = getName();
+
+        if (realmId != null) {
+            return realmId + "//" + name;
+        } else {
+            return clientId + "//" + name;
+        }
+    }
+
+    public void setNameIndex(String ignored) {
+    }
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext invContext) {
+        MongoStore mongoStore = invContext.getMongoStore();
+
+        // Remove this scope from all clients, which has it
+        DBObject query = new QueryBuilder()
+                .and("scopeIds").is(getId())
+                .get();
+
+        List<MongoClientEntity> clients = mongoStore.loadEntities(MongoClientEntity.class, query, invContext);
+        for (MongoClientEntity client : clients) {
+            //logger.info("Removing scope " + getName() + " from user " + user.getUsername());
+            mongoStore.pullItemFromList(client, "scopeIds", getId(), invContext);
+        }
+
+        // Remove defaultRoles from realm
+        if (getRealmId() != null) {
+            MongoRealmEntity realmEntity = mongoStore.loadEntity(MongoRealmEntity.class, getRealmId(), invContext);
+
+            // Realm might be already removed at this point
+            if (realmEntity != null) {
+                mongoStore.pullItemFromList(realmEntity, "defaultRoles", getName(), invContext);
+            }
+        }
+
+        // Remove defaultRoles from application
+        if (getClientId() != null) {
+            MongoClientEntity appEntity = mongoStore.loadEntity(MongoClientEntity.class, getClientId(), invContext);
+
+            // Application might be already removed at this point
+            if (appEntity != null) {
+                mongoStore.pullItemFromList(appEntity, "defaultRoles", getName(), invContext);
+            }
+        }
+
+        // Remove this role from others who has it as composite
+        query = new QueryBuilder()
+                .and("compositeRoleIds").is(getId())
+                .get();
+        List<MongoRoleEntity> parentRoles = mongoStore.loadEntities(MongoRoleEntity.class, query, invContext);
+        for (MongoRoleEntity role : parentRoles) {
+            mongoStore.pullItemFromList(role, "compositeRoleIds", getId(), invContext);
+        }
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
index d1700d8..c5d538a 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
@@ -1,32 +1,32 @@
-package org.keycloak.models.mongo.keycloak.entities;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.entities.UserEntity;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-@MongoCollection(collectionName = "users")
-public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
-
-    public String getEmailIndex() {
-        return getEmail() != null ? getRealmId() + "//" + getEmail() : null;
-    }
-
-    public void setEmailIndex(String ignored) {
-    }
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext context) {
-        // Remove all consents of this user
-        DBObject query = new QueryBuilder()
-                .and("userId").is(getId())
-                .get();
-
-        context.getMongoStore().removeEntities(MongoUserConsentEntity.class, query, true, context);
-    }
-}
+package org.keycloak.models.mongo.keycloak.entities;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.UserEntity;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@MongoCollection(collectionName = "users")
+public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
+
+    public String getEmailIndex() {
+        return getEmail() != null ? getRealmId() + "//" + getEmail() : null;
+    }
+
+    public void setEmailIndex(String ignored) {
+    }
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext context) {
+        // Remove all consents of this user
+        DBObject query = new QueryBuilder()
+                .and("userId").is(getId())
+                .get();
+
+        context.getMongoStore().removeEntities(MongoUserConsentEntity.class, query, true, context);
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
index 02923cf..9c2b326 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
@@ -1,58 +1,58 @@
-package org.keycloak.models.mongo.utils;
-
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.entities.ClientEntity;
-import org.keycloak.models.mongo.keycloak.adapters.ClientAdapter;
-import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class MongoModelUtils {
-
-    // Get everything including both application and realm roles
-    public static List<RoleModel> getAllRolesOfUser(RealmModel realm, UserModel user) {
-        MongoUserEntity userEntity = ((UserAdapter)user).getUser();
-        List<String> roleIds = userEntity.getRoleIds();
-
-        if (roleIds == null || roleIds.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<RoleModel> roles = new LinkedList<RoleModel>();
-        for (String roleId : roleIds) {
-            RoleModel role = realm.getRoleById(roleId);
-            if (role != null) {
-                roles.add(role);
-            }
-        }
-        return roles;
-    }
-
-    // Get everything including both application and realm scopes
-    public static List<MongoRoleEntity> getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) {
-        ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntity();
-        List<String> scopeIds = scopedEntity.getScopeIds();
-
-        if (scopeIds == null || scopeIds.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        DBObject query = new QueryBuilder()
-                .and("_id").in(scopeIds)
-                .get();
-        return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
-    }
-}
+package org.keycloak.models.mongo.utils;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.ClientEntity;
+import org.keycloak.models.mongo.keycloak.adapters.ClientAdapter;
+import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoModelUtils {
+
+    // Get everything including both application and realm roles
+    public static List<RoleModel> getAllRolesOfUser(RealmModel realm, UserModel user) {
+        MongoUserEntity userEntity = ((UserAdapter)user).getUser();
+        List<String> roleIds = userEntity.getRoleIds();
+
+        if (roleIds == null || roleIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<RoleModel> roles = new LinkedList<RoleModel>();
+        for (String roleId : roleIds) {
+            RoleModel role = realm.getRoleById(roleId);
+            if (role != null) {
+                roles.add(role);
+            }
+        }
+        return roles;
+    }
+
+    // Get everything including both application and realm scopes
+    public static List<MongoRoleEntity> getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) {
+        ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntity();
+        List<String> scopeIds = scopedEntity.getScopeIds();
+
+        if (scopeIds == null || scopeIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        DBObject query = new QueryBuilder()
+                .and("_id").in(scopeIds)
+                .get();
+        return invContext.getMongoStore().loadEntities(MongoRoleEntity.class, query, invContext);
+    }
+}

model/pom.xml 76(+38 -38)

diff --git a/model/pom.xml b/model/pom.xml
index 1d2296d..6a19f6a 100755
--- a/model/pom.xml
+++ b/model/pom.xml
@@ -1,38 +1,38 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak Model Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>api</module>
-        <module>invalidation-cache</module>
-        <module>jpa</module>
-        <module>mongo</module>
-        <module>file</module>
-        <module>sessions-jpa</module>
-        <module>sessions-mem</module>
-        <module>sessions-mongo</module>
-        <module>sessions-infinispan</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak Model Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>api</module>
+        <module>invalidation-cache</module>
+        <module>jpa</module>
+        <module>mongo</module>
+        <module>file</module>
+        <module>sessions-jpa</module>
+        <module>sessions-mem</module>
+        <module>sessions-mongo</module>
+        <module>sessions-infinispan</module>
+    </modules>
+</project>
diff --git a/model/sessions-infinispan/pom.xml b/model/sessions-infinispan/pom.xml
index 0093184..0d17fd5 100755
--- a/model/sessions-infinispan/pom.xml
+++ b/model/sessions-infinispan/pom.xml
@@ -1,38 +1,38 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-sessions-infinispan</artifactId>
-    <name>Keycloak Model Sessions Infinispan</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-infinispan</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-sessions-infinispan</artifactId>
+    <name>Keycloak Model Sessions Infinispan</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-infinispan</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
index 52ff887..0dc6299 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
@@ -1,236 +1,236 @@
-package org.keycloak.models.sessions.infinispan;
-
-import org.infinispan.Cache;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.sessions.infinispan.entities.ClientSessionEntity;
-import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionAdapter implements ClientSessionModel {
-
-    private KeycloakSession session;
-    private InfinispanUserSessionProvider provider;
-    private Cache<String, SessionEntity> cache;
-    private RealmModel realm;
-    private ClientSessionEntity entity;
-
-    public ClientSessionAdapter(KeycloakSession session, InfinispanUserSessionProvider provider, Cache<String, SessionEntity> cache, RealmModel realm, ClientSessionEntity entity) {
-        this.session = session;
-        this.provider = provider;
-        this.cache = cache;
-        this.realm = realm;
-        this.entity = entity;
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public ClientModel getClient() {
-        return realm.getClientById(entity.getClient());
-    }
-
-    @Override
-    public UserSessionModel getUserSession() {
-        return entity.getUserSession() != null ? provider.getUserSession(realm, entity.getUserSession()) : null;
-    }
-
-    @Override
-    public void setUserSession(UserSessionModel userSession) {
-        if (userSession == null) {
-            if (entity.getUserSession() != null) {
-                provider.dettachSession(getUserSession(), this);
-            }
-            entity.setUserSession(null);
-        } else {
-            if (entity.getUserSession() != null) {
-                if (entity.getUserSession().equals(userSession.getId())) {
-                    return;
-                } else {
-                    provider.dettachSession(userSession, this);
-                }
-            } else {
-                provider.attachSession(userSession, this);
-            }
-
-            entity.setUserSession(userSession.getId());
-        }
-        update();
-    }
-
-    @Override
-    public String getRedirectUri() {
-        return entity.getRedirectUri();
-    }
-
-    @Override
-    public void setRedirectUri(String uri) {
-        entity.setRedirectUri(uri);
-        update();
-    }
-
-    @Override
-    public int getTimestamp() {
-        return entity.getTimestamp();
-    }
-
-    @Override
-    public void setTimestamp(int timestamp) {
-        entity.setTimestamp(timestamp);
-        update();
-    }
-
-    @Override
-    public String getAction() {
-        return entity.getAction();
-    }
-
-    @Override
-    public void setAction(String action) {
-        entity.setAction(action);
-        update();
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        return entity.getRoles();
-    }
-
-    @Override
-    public void setRoles(Set<String> roles) {
-        entity.setRoles(roles);
-        update();
-    }
-
-    @Override
-    public Set<String> getProtocolMappers() {
-        return entity.getProtocolMappers();
-    }
-
-    @Override
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        entity.setProtocolMappers(protocolMappers);
-        update();
-    }
-
-    @Override
-    public String getAuthMethod() {
-        return entity.getAuthMethod();
-    }
-
-    @Override
-    public void setAuthMethod(String authMethod) {
-        entity.setAuthMethod(authMethod);
-        update();
-    }
-
-    @Override
-    public String getNote(String name) {
-        return entity.getNotes() != null ? entity.getNotes().get(name) : null;
-    }
-
-    @Override
-    public void setNote(String name, String value) {
-        if (entity.getNotes() == null) {
-            entity.setNotes(new HashMap<String, String>());
-        }
-        entity.getNotes().put(name, value);
-        update();
-    }
-
-    @Override
-    public void removeNote(String name) {
-        if (entity.getNotes() != null) {
-            entity.getNotes().remove(name);
-            update();
-        }
-    }
-
-    @Override
-    public Map<String, String> getNotes() {
-        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
-        Map<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getNotes());
-        return copy;
-    }
-
-    @Override
-    public void setUserSessionNote(String name, String value) {
-        if (entity.getUserSessionNotes() == null) {
-            entity.setUserSessionNotes(new HashMap<String, String>());
-        }
-        entity.getNotes().put(name, value);
-        update();
-
-    }
-
-    @Override
-    public Map<String, String> getUserSessionNotes() {
-        if (entity.getUserSessionNotes() == null) {
-            return Collections.EMPTY_MAP;
-        }
-        HashMap<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getUserSessionNotes());
-        return copy;
-    }
-
-    @Override
-    public void clearUserSessionNotes() {
-        entity.setUserSessionNotes(new HashMap<String, String>());
-        update();
-
-    }
-
-    void update() {
-        provider.getTx().replace(cache, entity.getId(), entity);
-    }
-    @Override
-    public Map<String, ExecutionStatus> getExecutionStatus() {
-        return entity.getAuthenticatorStatus();
-    }
-
-    @Override
-    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
-        entity.getAuthenticatorStatus().put(authenticator, status);
-        update();
-
-    }
-
-    @Override
-    public void clearExecutionStatus() {
-        entity.getAuthenticatorStatus().clear();
-        update();
-    }
-
-    @Override
-    public UserModel getAuthenticatedUser() {
-        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);    }
-
-    @Override
-    public void setAuthenticatedUser(UserModel user) {
-        if (user == null) entity.setAuthUserId(null);
-        else entity.setAuthUserId(user.getId());
-        update();
-
-    }
-
-}
+package org.keycloak.models.sessions.infinispan;
+
+import org.infinispan.Cache;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.sessions.infinispan.entities.ClientSessionEntity;
+import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionAdapter implements ClientSessionModel {
+
+    private KeycloakSession session;
+    private InfinispanUserSessionProvider provider;
+    private Cache<String, SessionEntity> cache;
+    private RealmModel realm;
+    private ClientSessionEntity entity;
+
+    public ClientSessionAdapter(KeycloakSession session, InfinispanUserSessionProvider provider, Cache<String, SessionEntity> cache, RealmModel realm, ClientSessionEntity entity) {
+        this.session = session;
+        this.provider = provider;
+        this.cache = cache;
+        this.realm = realm;
+        this.entity = entity;
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public ClientModel getClient() {
+        return realm.getClientById(entity.getClient());
+    }
+
+    @Override
+    public UserSessionModel getUserSession() {
+        return entity.getUserSession() != null ? provider.getUserSession(realm, entity.getUserSession()) : null;
+    }
+
+    @Override
+    public void setUserSession(UserSessionModel userSession) {
+        if (userSession == null) {
+            if (entity.getUserSession() != null) {
+                provider.dettachSession(getUserSession(), this);
+            }
+            entity.setUserSession(null);
+        } else {
+            if (entity.getUserSession() != null) {
+                if (entity.getUserSession().equals(userSession.getId())) {
+                    return;
+                } else {
+                    provider.dettachSession(userSession, this);
+                }
+            } else {
+                provider.attachSession(userSession, this);
+            }
+
+            entity.setUserSession(userSession.getId());
+        }
+        update();
+    }
+
+    @Override
+    public String getRedirectUri() {
+        return entity.getRedirectUri();
+    }
+
+    @Override
+    public void setRedirectUri(String uri) {
+        entity.setRedirectUri(uri);
+        update();
+    }
+
+    @Override
+    public int getTimestamp() {
+        return entity.getTimestamp();
+    }
+
+    @Override
+    public void setTimestamp(int timestamp) {
+        entity.setTimestamp(timestamp);
+        update();
+    }
+
+    @Override
+    public String getAction() {
+        return entity.getAction();
+    }
+
+    @Override
+    public void setAction(String action) {
+        entity.setAction(action);
+        update();
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        return entity.getRoles();
+    }
+
+    @Override
+    public void setRoles(Set<String> roles) {
+        entity.setRoles(roles);
+        update();
+    }
+
+    @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers();
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        entity.setProtocolMappers(protocolMappers);
+        update();
+    }
+
+    @Override
+    public String getAuthMethod() {
+        return entity.getAuthMethod();
+    }
+
+    @Override
+    public void setAuthMethod(String authMethod) {
+        entity.setAuthMethod(authMethod);
+        update();
+    }
+
+    @Override
+    public String getNote(String name) {
+        return entity.getNotes() != null ? entity.getNotes().get(name) : null;
+    }
+
+    @Override
+    public void setNote(String name, String value) {
+        if (entity.getNotes() == null) {
+            entity.setNotes(new HashMap<String, String>());
+        }
+        entity.getNotes().put(name, value);
+        update();
+    }
+
+    @Override
+    public void removeNote(String name) {
+        if (entity.getNotes() != null) {
+            entity.getNotes().remove(name);
+            update();
+        }
+    }
+
+    @Override
+    public Map<String, String> getNotes() {
+        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
+        Map<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getNotes());
+        return copy;
+    }
+
+    @Override
+    public void setUserSessionNote(String name, String value) {
+        if (entity.getUserSessionNotes() == null) {
+            entity.setUserSessionNotes(new HashMap<String, String>());
+        }
+        entity.getNotes().put(name, value);
+        update();
+
+    }
+
+    @Override
+    public Map<String, String> getUserSessionNotes() {
+        if (entity.getUserSessionNotes() == null) {
+            return Collections.EMPTY_MAP;
+        }
+        HashMap<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getUserSessionNotes());
+        return copy;
+    }
+
+    @Override
+    public void clearUserSessionNotes() {
+        entity.setUserSessionNotes(new HashMap<String, String>());
+        update();
+
+    }
+
+    void update() {
+        provider.getTx().replace(cache, entity.getId(), entity);
+    }
+    @Override
+    public Map<String, ExecutionStatus> getExecutionStatus() {
+        return entity.getAuthenticatorStatus();
+    }
+
+    @Override
+    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
+        entity.getAuthenticatorStatus().put(authenticator, status);
+        update();
+
+    }
+
+    @Override
+    public void clearExecutionStatus() {
+        entity.getAuthenticatorStatus().clear();
+        update();
+    }
+
+    @Override
+    public UserModel getAuthenticatedUser() {
+        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);    }
+
+    @Override
+    public void setAuthenticatedUser(UserModel user) {
+        if (user == null) entity.setAuthUserId(null);
+        else entity.setAuthUserId(user.getId());
+        update();
+
+    }
+
+}
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
index f8be1e8..a00e805 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
@@ -1,140 +1,140 @@
-package org.keycloak.models.sessions.infinispan.entities;
-
-import org.keycloak.models.ClientSessionModel;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionEntity extends SessionEntity {
-
-    private String client;
-
-    private String userSession;
-
-    private String authMethod;
-
-    private String redirectUri;
-
-    private String state;
-
-    private int timestamp;
-
-    private String action;
-
-    private Set<String> roles;
-    private Set<String> protocolMappers;
-    private Map<String, String> notes;
-    private Map<String, String> userSessionNotes;
-    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
-    private String authUserId;
-
-    public String getClient() {
-        return client;
-    }
-
-    public void setClient(String client) {
-        this.client = client;
-    }
-
-    public String getUserSession() {
-        return userSession;
-    }
-
-    public void setUserSession(String userSession) {
-        this.userSession = userSession;
-    }
-
-    public String getAuthMethod() {
-        return authMethod;
-    }
-
-    public void setAuthMethod(String authMethod) {
-        this.authMethod = authMethod;
-    }
-
-    public String getRedirectUri() {
-        return redirectUri;
-    }
-
-    public void setRedirectUri(String redirectUri) {
-        this.redirectUri = redirectUri;
-    }
-
-    public String getState() {
-        return state;
-    }
-
-    public void setState(String state) {
-        this.state = state;
-    }
-
-    public int getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(int timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public Set<String> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(Set<String> roles) {
-        this.roles = roles;
-    }
-
-    public Set<String> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public Map<String, String> getNotes() {
-        return notes;
-    }
-
-    public void setNotes(Map<String, String> notes) {
-        this.notes = notes;
-    }
-
-    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
-        return authenticatorStatus;
-    }
-
-    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
-        this.authenticatorStatus = authenticatorStatus;
-    }
-
-    public String getAuthUserId() {
-        return authUserId;
-    }
-
-    public void setAuthUserId(String authUserId) {
-        this.authUserId = authUserId;
-    }
-
-    public Map<String, String> getUserSessionNotes() {
-        return userSessionNotes;
-    }
-
-    public void setUserSessionNotes(Map<String, String> userSessionNotes) {
-        this.userSessionNotes = userSessionNotes;
-    }
-
-
-}
+package org.keycloak.models.sessions.infinispan.entities;
+
+import org.keycloak.models.ClientSessionModel;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionEntity extends SessionEntity {
+
+    private String client;
+
+    private String userSession;
+
+    private String authMethod;
+
+    private String redirectUri;
+
+    private String state;
+
+    private int timestamp;
+
+    private String action;
+
+    private Set<String> roles;
+    private Set<String> protocolMappers;
+    private Map<String, String> notes;
+    private Map<String, String> userSessionNotes;
+    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
+    private String authUserId;
+
+    public String getClient() {
+        return client;
+    }
+
+    public void setClient(String client) {
+        this.client = client;
+    }
+
+    public String getUserSession() {
+        return userSession;
+    }
+
+    public void setUserSession(String userSession) {
+        this.userSession = userSession;
+    }
+
+    public String getAuthMethod() {
+        return authMethod;
+    }
+
+    public void setAuthMethod(String authMethod) {
+        this.authMethod = authMethod;
+    }
+
+    public String getRedirectUri() {
+        return redirectUri;
+    }
+
+    public void setRedirectUri(String redirectUri) {
+        this.redirectUri = redirectUri;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public int getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(int timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Set<String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Set<String> roles) {
+        this.roles = roles;
+    }
+
+    public Set<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public Map<String, String> getNotes() {
+        return notes;
+    }
+
+    public void setNotes(Map<String, String> notes) {
+        this.notes = notes;
+    }
+
+    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
+        return authenticatorStatus;
+    }
+
+    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
+        this.authenticatorStatus = authenticatorStatus;
+    }
+
+    public String getAuthUserId() {
+        return authUserId;
+    }
+
+    public void setAuthUserId(String authUserId) {
+        this.authUserId = authUserId;
+    }
+
+    public Map<String, String> getUserSessionNotes() {
+        return userSessionNotes;
+    }
+
+    public void setUserSessionNotes(Map<String, String> userSessionNotes) {
+        this.userSessionNotes = userSessionNotes;
+    }
+
+
+}
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UsernameLoginFailureAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UsernameLoginFailureAdapter.java
index c478a0f..fb7fa10 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UsernameLoginFailureAdapter.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UsernameLoginFailureAdapter.java
@@ -1,84 +1,84 @@
-package org.keycloak.models.sessions.infinispan;
-
-import org.infinispan.Cache;
-import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.models.sessions.infinispan.entities.LoginFailureEntity;
-import org.keycloak.models.sessions.infinispan.entities.LoginFailureKey;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class UsernameLoginFailureAdapter implements UsernameLoginFailureModel {
-
-    private InfinispanUserSessionProvider provider;
-    private Cache<LoginFailureKey, LoginFailureEntity> cache;
-    private LoginFailureKey key;
-    private LoginFailureEntity entity;
-
-    public UsernameLoginFailureAdapter(InfinispanUserSessionProvider provider, Cache<LoginFailureKey, LoginFailureEntity> cache, LoginFailureKey key, LoginFailureEntity entity) {
-        this.provider = provider;
-        this.cache = cache;
-        this.key = key;
-        this.entity = entity;
-    }
-
-    @Override
-    public String getUsername() {
-        return entity.getUsername();
-    }
-
-    @Override
-    public int getFailedLoginNotBefore() {
-        return entity.getFailedLoginNotBefore();
-    }
-
-    @Override
-    public void setFailedLoginNotBefore(int notBefore) {
-        entity.setFailedLoginNotBefore(notBefore);
-        update();
-    }
-
-    @Override
-    public int getNumFailures() {
-        return entity.getNumFailures();
-    }
-
-    @Override
-    public void incrementFailures() {
-        entity.setNumFailures(getNumFailures() + 1);
-        update();
-    }
-
-    @Override
-    public void clearFailures() {
-        entity.clearFailures();
-        update();
-    }
-
-    @Override
-    public long getLastFailure() {
-        return entity.getLastFailure();
-    }
-
-    @Override
-    public void setLastFailure(long lastFailure) {
-        entity.setLastFailure(lastFailure);
-        update();
-    }
-
-    @Override
-    public String getLastIPFailure() {
-        return entity.getLastIPFailure();
-    }
-
-    @Override
-    public void setLastIPFailure(String ip) {
-        entity.setLastIPFailure(ip);
-        update();
-    }
-
-    void update() {
-        provider.getTx().replace(cache, key, entity);
-    }
-
-}
+package org.keycloak.models.sessions.infinispan;
+
+import org.infinispan.Cache;
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.models.sessions.infinispan.entities.LoginFailureEntity;
+import org.keycloak.models.sessions.infinispan.entities.LoginFailureKey;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class UsernameLoginFailureAdapter implements UsernameLoginFailureModel {
+
+    private InfinispanUserSessionProvider provider;
+    private Cache<LoginFailureKey, LoginFailureEntity> cache;
+    private LoginFailureKey key;
+    private LoginFailureEntity entity;
+
+    public UsernameLoginFailureAdapter(InfinispanUserSessionProvider provider, Cache<LoginFailureKey, LoginFailureEntity> cache, LoginFailureKey key, LoginFailureEntity entity) {
+        this.provider = provider;
+        this.cache = cache;
+        this.key = key;
+        this.entity = entity;
+    }
+
+    @Override
+    public String getUsername() {
+        return entity.getUsername();
+    }
+
+    @Override
+    public int getFailedLoginNotBefore() {
+        return entity.getFailedLoginNotBefore();
+    }
+
+    @Override
+    public void setFailedLoginNotBefore(int notBefore) {
+        entity.setFailedLoginNotBefore(notBefore);
+        update();
+    }
+
+    @Override
+    public int getNumFailures() {
+        return entity.getNumFailures();
+    }
+
+    @Override
+    public void incrementFailures() {
+        entity.setNumFailures(getNumFailures() + 1);
+        update();
+    }
+
+    @Override
+    public void clearFailures() {
+        entity.clearFailures();
+        update();
+    }
+
+    @Override
+    public long getLastFailure() {
+        return entity.getLastFailure();
+    }
+
+    @Override
+    public void setLastFailure(long lastFailure) {
+        entity.setLastFailure(lastFailure);
+        update();
+    }
+
+    @Override
+    public String getLastIPFailure() {
+        return entity.getLastIPFailure();
+    }
+
+    @Override
+    public void setLastIPFailure(String ip) {
+        entity.setLastIPFailure(ip);
+        update();
+    }
+
+    void update() {
+        provider.getTx().replace(cache, key, entity);
+    }
+
+}
diff --git a/model/sessions-jpa/pom.xml b/model/sessions-jpa/pom.xml
index 2225012..f2e7b8e 100755
--- a/model/sessions-jpa/pom.xml
+++ b/model/sessions-jpa/pom.xml
@@ -1,43 +1,43 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-sessions-jpa</artifactId>
-    <name>Keycloak Model Sessions JPA</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-jpa</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-sessions-jpa</artifactId>
+    <name>Keycloak Model Sessions JPA</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-jpa</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
index 1de321e..4c645c7 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
@@ -1,312 +1,312 @@
-package org.keycloak.models.sessions.jpa;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.sessions.jpa.entities.ClientSessionAuthStatusEntity;
-import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity;
-import org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity;
-import org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity;
-import org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity;
-import org.keycloak.models.sessions.jpa.entities.ClientUserSessionNoteEntity;
-import org.keycloak.models.sessions.jpa.entities.UserSessionEntity;
-
-import javax.persistence.EntityManager;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionAdapter implements ClientSessionModel {
-
-    private KeycloakSession session;
-    private ClientSessionEntity entity;
-    private EntityManager em;
-    private RealmModel realm;
-
-    public ClientSessionAdapter(KeycloakSession session, EntityManager em, RealmModel realm, ClientSessionEntity entity) {
-        this.session = session;
-        this.em = em;
-        this.realm = realm;
-        this.entity = entity;
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return session.realms().getRealm(entity.getRealmId());
-    }
-
-    @Override
-    public void setNote(String name, String value) {
-        for (ClientSessionNoteEntity attr : entity.getNotes()) {
-            if (attr.getName().equals(name)) {
-                attr.setValue(value);
-                return;
-            }
-        }
-        ClientSessionNoteEntity attr = new ClientSessionNoteEntity();
-        attr.setName(name);
-        attr.setValue(value);
-        attr.setClientSession(entity);
-        em.persist(attr);
-        entity.getNotes().add(attr);
-    }
-
-    @Override
-    public void removeNote(String name) {
-        Iterator<ClientSessionNoteEntity> it = entity.getNotes().iterator();
-        while (it.hasNext()) {
-            ClientSessionNoteEntity attr = it.next();
-            if (attr.getName().equals(name)) {
-                it.remove();
-                em.remove(attr);
-            }
-        }
-    }
-
-    @Override
-    public String getNote(String name) {
-        for (ClientSessionNoteEntity attr : entity.getNotes()) {
-            if (attr.getName().equals(name)) {
-                return attr.getValue();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Map<String, String> getNotes() {
-        Map<String, String> copy = new HashMap<>();
-        for (ClientSessionNoteEntity attr : entity.getNotes()) {
-            copy.put(attr.getName(), attr.getValue());
-        }
-
-        return copy;
-    }
-
-    @Override
-    public void setUserSessionNote(String name, String value) {
-        for (ClientUserSessionNoteEntity attr : entity.getUserSessionNotes()) {
-            if (attr.getName().equals(name)) {
-                attr.setValue(value);
-                return;
-            }
-        }
-        ClientUserSessionNoteEntity attr = new ClientUserSessionNoteEntity();
-        attr.setName(name);
-        attr.setValue(value);
-        attr.setClientSession(entity);
-        em.persist(attr);
-        entity.getUserSessionNotes().add(attr);
-
-    }
-
-    @Override
-    public Map<String, String> getUserSessionNotes() {
-        Map<String, String> copy = new HashMap<>();
-        for (ClientUserSessionNoteEntity attr : entity.getUserSessionNotes()) {
-            copy.put(attr.getName(), attr.getValue());
-        }
-        return copy;
-    }
-
-    @Override
-    public void clearUserSessionNotes() {
-        Iterator<ClientUserSessionNoteEntity> it = entity.getUserSessionNotes().iterator();
-        while (it.hasNext()) {
-            ClientUserSessionNoteEntity attr = it.next();
-            it.remove();
-            em.remove(attr);
-        }
-
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public ClientModel getClient() {
-        return realm.getClientById(entity.getClientId());
-    }
-
-    public ClientSessionEntity getEntity() {
-        return entity;
-    }
-
-    @Override
-    public void setUserSession(UserSessionModel userSession) {
-        if (userSession == null) {
-            if (entity.getSession() != null) {
-                entity.getSession().getClientSessions().remove(entity);
-            }
-            entity.setSession(null);
-        } else {
-            UserSessionAdapter adapter = (UserSessionAdapter) userSession;
-            UserSessionEntity userSessionEntity = adapter.getEntity();
-            entity.setSession(userSessionEntity);
-            userSessionEntity.getClientSessions().add(entity);
-        }
-    }
-
-    @Override
-    public void setRedirectUri(String uri) {
-       entity.setRedirectUri(uri);
-    }
-
-    @Override
-    public void setRoles(Set<String> roles) {
-        if (roles != null) {
-            for (String r : roles) {
-                ClientSessionRoleEntity roleEntity = new ClientSessionRoleEntity();
-                roleEntity.setClientSession(entity);
-                roleEntity.setRoleId(r);
-                em.persist(roleEntity);
-
-                entity.getRoles().add(roleEntity);
-            }
-        } else {
-            if (entity.getRoles() != null) {
-                for (ClientSessionRoleEntity r : entity.getRoles()) {
-                    em.remove(r);
-                }
-                entity.getRoles().clear();
-            }
-        }
-    }
-
-    @Override
-    public String getAuthMethod() {
-        return entity.getAuthMethod();
-    }
-
-    @Override
-    public void setAuthMethod(String method) {
-        entity.setAuthMethod(method);
-    }
-
-    @Override
-    public UserSessionModel getUserSession() {
-        if (entity.getSession() == null) return null;
-        return new UserSessionAdapter(session, em, realm, entity.getSession());
-    }
-
-    @Override
-    public String getRedirectUri() {
-        return entity.getRedirectUri();
-    }
-
-    @Override
-    public int getTimestamp() {
-        return entity.getTimestamp();
-    }
-
-    @Override
-    public void setTimestamp(int timestamp) {
-        entity.setTimestamp(timestamp);
-    }
-
-    @Override
-    public String getAction() {
-        return entity.getAction();
-    }
-
-    @Override
-    public void setAction(String action) {
-        entity.setAction(action);
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        Set<String> roles = new HashSet<String>();
-        if (entity.getRoles() != null) {
-            for (ClientSessionRoleEntity e : entity.getRoles()) {
-                roles.add(e.getRoleId());
-            }
-        }
-        return roles;
-    }
-
-    @Override
-    public Set<String> getProtocolMappers() {
-        Set<String> protMappers = new HashSet<String>();
-        if (entity.getProtocolMappers() != null) {
-            for (ClientSessionProtocolMapperEntity e : entity.getProtocolMappers()) {
-                protMappers.add(e.getProtocolMapperId());
-            }
-        }
-        return protMappers;
-    }
-
-    @Override
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        if (protocolMappers != null) {
-            for (String pm : protocolMappers) {
-                ClientSessionProtocolMapperEntity protMapperEntity = new ClientSessionProtocolMapperEntity();
-                protMapperEntity.setClientSession(entity);
-                protMapperEntity.setProtocolMapperId(pm);
-                em.persist(protMapperEntity);
-
-                entity.getProtocolMappers().add(protMapperEntity);
-            }
-        } else {
-            if (entity.getProtocolMappers() != null) {
-                for (ClientSessionProtocolMapperEntity pm : entity.getProtocolMappers()) {
-                    em.remove(pm);
-                }
-                entity.getProtocolMappers().clear();
-            }
-        }
-    }
-
-    @Override
-    public Map<String, ExecutionStatus> getExecutionStatus() {
-        Map<String, ExecutionStatus> result = new HashMap<>();
-        for (ClientSessionAuthStatusEntity status : entity.getAuthanticatorStatus()) {
-            result.put(status.getAuthenticator(), status.getStatus());
-        }
-        return result;
-    }
-
-    @Override
-    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
-        ClientSessionAuthStatusEntity authStatus = new ClientSessionAuthStatusEntity();
-        authStatus.setAuthenticator(authenticator);
-        authStatus.setClientSession(entity);
-        authStatus.setStatus(status);
-        em.persist(authStatus);
-        entity.getAuthanticatorStatus().add(authStatus);
-        em.flush();
-
-
-    }
-
-    @Override
-    public void clearExecutionStatus() {
-        Iterator<ClientSessionAuthStatusEntity> iterator = entity.getAuthanticatorStatus().iterator();
-        while (iterator.hasNext()) {
-            ClientSessionAuthStatusEntity authStatus = iterator.next();
-            iterator.remove();
-            em.remove(authStatus);
-        }
-    }
-
-    @Override
-    public UserModel getAuthenticatedUser() {
-        return entity.getUserId() == null ? null : session.users().getUserById(entity.getUserId(), realm);
-    }
-
-    @Override
-    public void setAuthenticatedUser(UserModel user) {
-        if (user == null) entity.setUserId(null);
-        else entity.setUserId(user.getId());
-    }
-}
+package org.keycloak.models.sessions.jpa;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionAuthStatusEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientUserSessionNoteEntity;
+import org.keycloak.models.sessions.jpa.entities.UserSessionEntity;
+
+import javax.persistence.EntityManager;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionAdapter implements ClientSessionModel {
+
+    private KeycloakSession session;
+    private ClientSessionEntity entity;
+    private EntityManager em;
+    private RealmModel realm;
+
+    public ClientSessionAdapter(KeycloakSession session, EntityManager em, RealmModel realm, ClientSessionEntity entity) {
+        this.session = session;
+        this.em = em;
+        this.realm = realm;
+        this.entity = entity;
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return session.realms().getRealm(entity.getRealmId());
+    }
+
+    @Override
+    public void setNote(String name, String value) {
+        for (ClientSessionNoteEntity attr : entity.getNotes()) {
+            if (attr.getName().equals(name)) {
+                attr.setValue(value);
+                return;
+            }
+        }
+        ClientSessionNoteEntity attr = new ClientSessionNoteEntity();
+        attr.setName(name);
+        attr.setValue(value);
+        attr.setClientSession(entity);
+        em.persist(attr);
+        entity.getNotes().add(attr);
+    }
+
+    @Override
+    public void removeNote(String name) {
+        Iterator<ClientSessionNoteEntity> it = entity.getNotes().iterator();
+        while (it.hasNext()) {
+            ClientSessionNoteEntity attr = it.next();
+            if (attr.getName().equals(name)) {
+                it.remove();
+                em.remove(attr);
+            }
+        }
+    }
+
+    @Override
+    public String getNote(String name) {
+        for (ClientSessionNoteEntity attr : entity.getNotes()) {
+            if (attr.getName().equals(name)) {
+                return attr.getValue();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, String> getNotes() {
+        Map<String, String> copy = new HashMap<>();
+        for (ClientSessionNoteEntity attr : entity.getNotes()) {
+            copy.put(attr.getName(), attr.getValue());
+        }
+
+        return copy;
+    }
+
+    @Override
+    public void setUserSessionNote(String name, String value) {
+        for (ClientUserSessionNoteEntity attr : entity.getUserSessionNotes()) {
+            if (attr.getName().equals(name)) {
+                attr.setValue(value);
+                return;
+            }
+        }
+        ClientUserSessionNoteEntity attr = new ClientUserSessionNoteEntity();
+        attr.setName(name);
+        attr.setValue(value);
+        attr.setClientSession(entity);
+        em.persist(attr);
+        entity.getUserSessionNotes().add(attr);
+
+    }
+
+    @Override
+    public Map<String, String> getUserSessionNotes() {
+        Map<String, String> copy = new HashMap<>();
+        for (ClientUserSessionNoteEntity attr : entity.getUserSessionNotes()) {
+            copy.put(attr.getName(), attr.getValue());
+        }
+        return copy;
+    }
+
+    @Override
+    public void clearUserSessionNotes() {
+        Iterator<ClientUserSessionNoteEntity> it = entity.getUserSessionNotes().iterator();
+        while (it.hasNext()) {
+            ClientUserSessionNoteEntity attr = it.next();
+            it.remove();
+            em.remove(attr);
+        }
+
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public ClientModel getClient() {
+        return realm.getClientById(entity.getClientId());
+    }
+
+    public ClientSessionEntity getEntity() {
+        return entity;
+    }
+
+    @Override
+    public void setUserSession(UserSessionModel userSession) {
+        if (userSession == null) {
+            if (entity.getSession() != null) {
+                entity.getSession().getClientSessions().remove(entity);
+            }
+            entity.setSession(null);
+        } else {
+            UserSessionAdapter adapter = (UserSessionAdapter) userSession;
+            UserSessionEntity userSessionEntity = adapter.getEntity();
+            entity.setSession(userSessionEntity);
+            userSessionEntity.getClientSessions().add(entity);
+        }
+    }
+
+    @Override
+    public void setRedirectUri(String uri) {
+       entity.setRedirectUri(uri);
+    }
+
+    @Override
+    public void setRoles(Set<String> roles) {
+        if (roles != null) {
+            for (String r : roles) {
+                ClientSessionRoleEntity roleEntity = new ClientSessionRoleEntity();
+                roleEntity.setClientSession(entity);
+                roleEntity.setRoleId(r);
+                em.persist(roleEntity);
+
+                entity.getRoles().add(roleEntity);
+            }
+        } else {
+            if (entity.getRoles() != null) {
+                for (ClientSessionRoleEntity r : entity.getRoles()) {
+                    em.remove(r);
+                }
+                entity.getRoles().clear();
+            }
+        }
+    }
+
+    @Override
+    public String getAuthMethod() {
+        return entity.getAuthMethod();
+    }
+
+    @Override
+    public void setAuthMethod(String method) {
+        entity.setAuthMethod(method);
+    }
+
+    @Override
+    public UserSessionModel getUserSession() {
+        if (entity.getSession() == null) return null;
+        return new UserSessionAdapter(session, em, realm, entity.getSession());
+    }
+
+    @Override
+    public String getRedirectUri() {
+        return entity.getRedirectUri();
+    }
+
+    @Override
+    public int getTimestamp() {
+        return entity.getTimestamp();
+    }
+
+    @Override
+    public void setTimestamp(int timestamp) {
+        entity.setTimestamp(timestamp);
+    }
+
+    @Override
+    public String getAction() {
+        return entity.getAction();
+    }
+
+    @Override
+    public void setAction(String action) {
+        entity.setAction(action);
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        Set<String> roles = new HashSet<String>();
+        if (entity.getRoles() != null) {
+            for (ClientSessionRoleEntity e : entity.getRoles()) {
+                roles.add(e.getRoleId());
+            }
+        }
+        return roles;
+    }
+
+    @Override
+    public Set<String> getProtocolMappers() {
+        Set<String> protMappers = new HashSet<String>();
+        if (entity.getProtocolMappers() != null) {
+            for (ClientSessionProtocolMapperEntity e : entity.getProtocolMappers()) {
+                protMappers.add(e.getProtocolMapperId());
+            }
+        }
+        return protMappers;
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        if (protocolMappers != null) {
+            for (String pm : protocolMappers) {
+                ClientSessionProtocolMapperEntity protMapperEntity = new ClientSessionProtocolMapperEntity();
+                protMapperEntity.setClientSession(entity);
+                protMapperEntity.setProtocolMapperId(pm);
+                em.persist(protMapperEntity);
+
+                entity.getProtocolMappers().add(protMapperEntity);
+            }
+        } else {
+            if (entity.getProtocolMappers() != null) {
+                for (ClientSessionProtocolMapperEntity pm : entity.getProtocolMappers()) {
+                    em.remove(pm);
+                }
+                entity.getProtocolMappers().clear();
+            }
+        }
+    }
+
+    @Override
+    public Map<String, ExecutionStatus> getExecutionStatus() {
+        Map<String, ExecutionStatus> result = new HashMap<>();
+        for (ClientSessionAuthStatusEntity status : entity.getAuthanticatorStatus()) {
+            result.put(status.getAuthenticator(), status.getStatus());
+        }
+        return result;
+    }
+
+    @Override
+    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
+        ClientSessionAuthStatusEntity authStatus = new ClientSessionAuthStatusEntity();
+        authStatus.setAuthenticator(authenticator);
+        authStatus.setClientSession(entity);
+        authStatus.setStatus(status);
+        em.persist(authStatus);
+        entity.getAuthanticatorStatus().add(authStatus);
+        em.flush();
+
+
+    }
+
+    @Override
+    public void clearExecutionStatus() {
+        Iterator<ClientSessionAuthStatusEntity> iterator = entity.getAuthanticatorStatus().iterator();
+        while (iterator.hasNext()) {
+            ClientSessionAuthStatusEntity authStatus = iterator.next();
+            iterator.remove();
+            em.remove(authStatus);
+        }
+    }
+
+    @Override
+    public UserModel getAuthenticatedUser() {
+        return entity.getUserId() == null ? null : session.users().getUserById(entity.getUserId(), realm);
+    }
+
+    @Override
+    public void setAuthenticatedUser(UserModel user) {
+        if (user == null) entity.setUserId(null);
+        else entity.setUserId(user.getId());
+    }
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionAuthStatusEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionAuthStatusEntity.java
index e8dea7a..a30d81e 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionAuthStatusEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionAuthStatusEntity.java
@@ -1,111 +1,111 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import org.keycloak.models.ClientSessionModel;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name = "removeClientSessionAuthStatusByUser", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
-        @NamedQuery(name = "removeClientSessionAuthStatusByClient", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionAuthStatusByRealm", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionAuthStatusByExpired", query = "delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
-        @NamedQuery(name = "removeDetachedClientSessionAuthStatusByExpired", query = "delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
-})
-@Table(name="CLIENT_SESSION_AUTH_STATUS")
-@Entity
-@IdClass(ClientSessionAuthStatusEntity.Key.class)
-public class ClientSessionAuthStatusEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_SESSION")
-    protected ClientSessionEntity clientSession;
-
-    @Id
-    @Column(name = "AUTHENTICATOR")
-    protected String authenticator;
-    @Column(name = "STATUS")
-    protected ClientSessionModel.ExecutionStatus status;
-
-    public String getAuthenticator() {
-        return authenticator;
-    }
-
-    public void setAuthenticator(String authenticator) {
-        this.authenticator = authenticator;
-    }
-
-    public ClientSessionModel.ExecutionStatus getStatus() {
-        return status;
-    }
-
-    public void setStatus(ClientSessionModel.ExecutionStatus status) {
-        this.status = status;
-    }
-
-    public ClientSessionEntity getClientSession() {
-        return clientSession;
-    }
-
-    public void setClientSession(ClientSessionEntity clientSession) {
-        this.clientSession = clientSession;
-    }
-
-    public static class Key implements Serializable {
-
-        protected ClientSessionEntity clientSession;
-
-        protected String authenticator;
-
-        public Key() {
-        }
-
-        public Key(ClientSessionEntity clientSession, String authenticator) {
-            this.clientSession = clientSession;
-            this.authenticator = authenticator;
-        }
-
-        public ClientSessionEntity getClientSession() {
-            return clientSession;
-        }
-
-        public String getAuthenticator() {
-            return authenticator;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (authenticator != null ? !authenticator.equals(key.authenticator) : key.authenticator != null) return false;
-            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
-            result = 31 * result + (authenticator != null ? authenticator.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import org.keycloak.models.ClientSessionModel;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name = "removeClientSessionAuthStatusByUser", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+        @NamedQuery(name = "removeClientSessionAuthStatusByClient", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionAuthStatusByRealm", query="delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionAuthStatusByExpired", query = "delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
+        @NamedQuery(name = "removeDetachedClientSessionAuthStatusByExpired", query = "delete from ClientSessionAuthStatusEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
+})
+@Table(name="CLIENT_SESSION_AUTH_STATUS")
+@Entity
+@IdClass(ClientSessionAuthStatusEntity.Key.class)
+public class ClientSessionAuthStatusEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_SESSION")
+    protected ClientSessionEntity clientSession;
+
+    @Id
+    @Column(name = "AUTHENTICATOR")
+    protected String authenticator;
+    @Column(name = "STATUS")
+    protected ClientSessionModel.ExecutionStatus status;
+
+    public String getAuthenticator() {
+        return authenticator;
+    }
+
+    public void setAuthenticator(String authenticator) {
+        this.authenticator = authenticator;
+    }
+
+    public ClientSessionModel.ExecutionStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ClientSessionModel.ExecutionStatus status) {
+        this.status = status;
+    }
+
+    public ClientSessionEntity getClientSession() {
+        return clientSession;
+    }
+
+    public void setClientSession(ClientSessionEntity clientSession) {
+        this.clientSession = clientSession;
+    }
+
+    public static class Key implements Serializable {
+
+        protected ClientSessionEntity clientSession;
+
+        protected String authenticator;
+
+        public Key() {
+        }
+
+        public Key(ClientSessionEntity clientSession, String authenticator) {
+            this.clientSession = clientSession;
+            this.authenticator = authenticator;
+        }
+
+        public ClientSessionEntity getClientSession() {
+            return clientSession;
+        }
+
+        public String getAuthenticator() {
+            return authenticator;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (authenticator != null ? !authenticator.equals(key.authenticator) : key.authenticator != null) return false;
+            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
+            result = 31 * result + (authenticator != null ? authenticator.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
index 5789ea8..1c359b2 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
@@ -1,206 +1,206 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import org.keycloak.models.ClientSessionModel;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name = "CLIENT_SESSION")
-@NamedQueries({
-        @NamedQuery(name = "removeClientSessionByRealm", query = "delete from ClientSessionEntity a where a.realmId = :realmId"),
-        @NamedQuery(name = "removeClientSessionByUser", query = "delete from ClientSessionEntity a where a.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId)"),
-        @NamedQuery(name = "removeClientSessionByClient", query = "delete from ClientSessionEntity a where a.clientId = :clientId and a.realmId = :realmId"),
-        @NamedQuery(name = "removeClientSessionByExpired", query = "delete from ClientSessionEntity a where a.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime))"),
-        @NamedQuery(name = "removeDetachedClientSessionByExpired", query = "delete from ClientSessionEntity a where a.session IS NULL and a.timestamp < :maxTime and a.realmId = :realmId")
-})
-public class ClientSessionEntity {
-
-    @Id
-    @Column(name = "ID", length = 36)
-    protected String id;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "SESSION_ID")
-    protected UserSessionEntity session;
-
-    @Column(name="CLIENT_ID",length = 36)
-    protected String clientId;
-
-    @Column(name="REALM_ID")
-    protected String realmId;
-
-    @Column(name="TIMESTAMP")
-    protected int timestamp;
-
-    @Column(name="REDIRECT_URI")
-    protected String redirectUri;
-
-    @Column(name="AUTH_METHOD")
-    protected String authMethod;
-
-    @Column(name="CURRENT_ACTION")
-    protected String action;
-
-    @Column(name="AUTH_USER_ID")
-    protected String userId;
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
-    protected Collection<ClientSessionRoleEntity> roles = new ArrayList<ClientSessionRoleEntity>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
-    protected Collection<ClientSessionProtocolMapperEntity> protocolMappers = new ArrayList<ClientSessionProtocolMapperEntity>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
-    protected Collection<ClientSessionNoteEntity> notes = new ArrayList<ClientSessionNoteEntity>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
-    protected Collection<ClientUserSessionNoteEntity> userSessionNotes = new ArrayList<>();
-
-    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
-    protected Collection<ClientSessionAuthStatusEntity> authanticatorStatus = new ArrayList<>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public UserSessionEntity getSession() {
-        return session;
-    }
-
-    public void setSession(UserSessionEntity session) {
-        this.session = session;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public int getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(int timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getRedirectUri() {
-        return redirectUri;
-    }
-
-    public void setRedirectUri(String redirectUri) {
-        this.redirectUri = redirectUri;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public Collection<ClientSessionRoleEntity> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(Collection<ClientSessionRoleEntity> roles) {
-        this.roles = roles;
-    }
-
-    public Collection<ClientSessionProtocolMapperEntity> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(Collection<ClientSessionProtocolMapperEntity> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public Collection<ClientSessionNoteEntity> getNotes() {
-        return notes;
-    }
-
-    public void setNotes(Collection<ClientSessionNoteEntity> notes) {
-        this.notes = notes;
-    }
-
-    public String getAuthMethod() {
-        return authMethod;
-    }
-
-    public void setAuthMethod(String authMethod) {
-        this.authMethod = authMethod;
-    }
-
-    public Collection<ClientSessionAuthStatusEntity> getAuthanticatorStatus() {
-        return authanticatorStatus;
-    }
-
-    public void setAuthanticatorStatus(Collection<ClientSessionAuthStatusEntity> authanticatorStatus) {
-        this.authanticatorStatus = authanticatorStatus;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    public Collection<ClientUserSessionNoteEntity> getUserSessionNotes() {
-        return userSessionNotes;
-    }
-
-    public void setUserSessionNotes(Collection<ClientUserSessionNoteEntity> userSessionNotes) {
-        this.userSessionNotes = userSessionNotes;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof ClientSessionEntity)) return false;
-
-        ClientSessionEntity that = (ClientSessionEntity) o;
-
-        if (id != null ? !id.equals(that.id) : that.id != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id != null ? id.hashCode() : 0;
-    }
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import org.keycloak.models.ClientSessionModel;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name = "CLIENT_SESSION")
+@NamedQueries({
+        @NamedQuery(name = "removeClientSessionByRealm", query = "delete from ClientSessionEntity a where a.realmId = :realmId"),
+        @NamedQuery(name = "removeClientSessionByUser", query = "delete from ClientSessionEntity a where a.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId)"),
+        @NamedQuery(name = "removeClientSessionByClient", query = "delete from ClientSessionEntity a where a.clientId = :clientId and a.realmId = :realmId"),
+        @NamedQuery(name = "removeClientSessionByExpired", query = "delete from ClientSessionEntity a where a.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime))"),
+        @NamedQuery(name = "removeDetachedClientSessionByExpired", query = "delete from ClientSessionEntity a where a.session IS NULL and a.timestamp < :maxTime and a.realmId = :realmId")
+})
+public class ClientSessionEntity {
+
+    @Id
+    @Column(name = "ID", length = 36)
+    protected String id;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "SESSION_ID")
+    protected UserSessionEntity session;
+
+    @Column(name="CLIENT_ID",length = 36)
+    protected String clientId;
+
+    @Column(name="REALM_ID")
+    protected String realmId;
+
+    @Column(name="TIMESTAMP")
+    protected int timestamp;
+
+    @Column(name="REDIRECT_URI")
+    protected String redirectUri;
+
+    @Column(name="AUTH_METHOD")
+    protected String authMethod;
+
+    @Column(name="CURRENT_ACTION")
+    protected String action;
+
+    @Column(name="AUTH_USER_ID")
+    protected String userId;
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientSessionRoleEntity> roles = new ArrayList<ClientSessionRoleEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientSessionProtocolMapperEntity> protocolMappers = new ArrayList<ClientSessionProtocolMapperEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientSessionNoteEntity> notes = new ArrayList<ClientSessionNoteEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientUserSessionNoteEntity> userSessionNotes = new ArrayList<>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientSessionAuthStatusEntity> authanticatorStatus = new ArrayList<>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public UserSessionEntity getSession() {
+        return session;
+    }
+
+    public void setSession(UserSessionEntity session) {
+        this.session = session;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public int getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(int timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getRedirectUri() {
+        return redirectUri;
+    }
+
+    public void setRedirectUri(String redirectUri) {
+        this.redirectUri = redirectUri;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Collection<ClientSessionRoleEntity> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Collection<ClientSessionRoleEntity> roles) {
+        this.roles = roles;
+    }
+
+    public Collection<ClientSessionProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Collection<ClientSessionProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public Collection<ClientSessionNoteEntity> getNotes() {
+        return notes;
+    }
+
+    public void setNotes(Collection<ClientSessionNoteEntity> notes) {
+        this.notes = notes;
+    }
+
+    public String getAuthMethod() {
+        return authMethod;
+    }
+
+    public void setAuthMethod(String authMethod) {
+        this.authMethod = authMethod;
+    }
+
+    public Collection<ClientSessionAuthStatusEntity> getAuthanticatorStatus() {
+        return authanticatorStatus;
+    }
+
+    public void setAuthanticatorStatus(Collection<ClientSessionAuthStatusEntity> authanticatorStatus) {
+        this.authanticatorStatus = authanticatorStatus;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public Collection<ClientUserSessionNoteEntity> getUserSessionNotes() {
+        return userSessionNotes;
+    }
+
+    public void setUserSessionNotes(Collection<ClientUserSessionNoteEntity> userSessionNotes) {
+        this.userSessionNotes = userSessionNotes;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ClientSessionEntity)) return false;
+
+        ClientSessionEntity that = (ClientSessionEntity) o;
+
+        if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java
index d1025e0..349d78d 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java
@@ -1,109 +1,109 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name = "removeClientSessionNoteByUser", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
-        @NamedQuery(name = "removeClientSessionNoteByClient", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionNoteByRealm", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionNoteByExpired", query = "delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
-        @NamedQuery(name = "removeDetachedClientSessionNoteByExpired", query = "delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
-})
-@Table(name="CLIENT_SESSION_NOTE")
-@Entity
-@IdClass(ClientSessionNoteEntity.Key.class)
-public class ClientSessionNoteEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_SESSION")
-    protected ClientSessionEntity clientSession;
-
-    @Id
-    @Column(name = "NAME")
-    protected String name;
-    @Column(name = "VALUE")
-    protected String value;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public ClientSessionEntity getClientSession() {
-        return clientSession;
-    }
-
-    public void setClientSession(ClientSessionEntity clientSession) {
-        this.clientSession = clientSession;
-    }
-
-    public static class Key implements Serializable {
-
-        protected ClientSessionEntity clientSession;
-
-        protected String name;
-
-        public Key() {
-        }
-
-        public Key(ClientSessionEntity clientSession, String name) {
-            this.clientSession = clientSession;
-            this.name = name;
-        }
-
-        public ClientSessionEntity getClientSession() {
-            return clientSession;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (name != null ? !name.equals(key.name) : key.name != null) return false;
-            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
-            result = 31 * result + (name != null ? name.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name = "removeClientSessionNoteByUser", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+        @NamedQuery(name = "removeClientSessionNoteByClient", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionNoteByRealm", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionNoteByExpired", query = "delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
+        @NamedQuery(name = "removeDetachedClientSessionNoteByExpired", query = "delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
+})
+@Table(name="CLIENT_SESSION_NOTE")
+@Entity
+@IdClass(ClientSessionNoteEntity.Key.class)
+public class ClientSessionNoteEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_SESSION")
+    protected ClientSessionEntity clientSession;
+
+    @Id
+    @Column(name = "NAME")
+    protected String name;
+    @Column(name = "VALUE")
+    protected String value;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public ClientSessionEntity getClientSession() {
+        return clientSession;
+    }
+
+    public void setClientSession(ClientSessionEntity clientSession) {
+        this.clientSession = clientSession;
+    }
+
+    public static class Key implements Serializable {
+
+        protected ClientSessionEntity clientSession;
+
+        protected String name;
+
+        public Key() {
+        }
+
+        public Key(ClientSessionEntity clientSession, String name) {
+            this.clientSession = clientSession;
+            this.name = name;
+        }
+
+        public ClientSessionEntity getClientSession() {
+            return clientSession;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (name != null ? !name.equals(key.name) : key.name != null) return false;
+            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionRoleEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionRoleEntity.java
index fe79cad..988b04c 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionRoleEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionRoleEntity.java
@@ -1,98 +1,98 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-@NamedQueries({
-        @NamedQuery(name = "removeClientSessionRoleByUser", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
-        @NamedQuery(name = "removeClientSessionRoleByClient", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionRoleByRealm", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientSessionRoleByExpired", query = "delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
-        @NamedQuery(name = "removeDetachedClientSessionRoleByExpired", query = "delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
-})
-@Table(name="CLIENT_SESSION_ROLE")
-@Entity
-@IdClass(ClientSessionRoleEntity.Key.class)
-public class ClientSessionRoleEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name="CLIENT_SESSION")
-    protected ClientSessionEntity clientSession;
-
-    @Id
-    @Column(name = "ROLE_ID")
-    protected String roleId;
-
-    public ClientSessionEntity getClientSession() {
-        return clientSession;
-    }
-
-    public void setClientSession(ClientSessionEntity clientSession) {
-        this.clientSession = clientSession;
-    }
-
-    public String getRoleId() {
-        return roleId;
-    }
-
-    public void setRoleId(String roleId) {
-        this.roleId = roleId;
-    }
-
-
-    public static class Key implements Serializable {
-
-        protected ClientSessionEntity clientSession;
-
-        protected String roleId;
-
-        public Key() {
-        }
-
-        public Key(ClientSessionEntity clientSession, String roleId) {
-            this.clientSession = clientSession;
-            this.roleId = roleId;
-        }
-
-        public ClientSessionEntity getClientSession() {
-            return clientSession;
-        }
-
-        public String getRoleId() {
-            return roleId;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (!roleId.equals(key.roleId)) return false;
-            if (!clientSession.getId().equals(key.clientSession.getId())) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = clientSession.getId().hashCode();
-            result = 31 * result + roleId.hashCode();
-            return result;
-        }
-    }
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@NamedQueries({
+        @NamedQuery(name = "removeClientSessionRoleByUser", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+        @NamedQuery(name = "removeClientSessionRoleByClient", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionRoleByRealm", query="delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionRoleByExpired", query = "delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
+        @NamedQuery(name = "removeDetachedClientSessionRoleByExpired", query = "delete from ClientSessionRoleEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
+})
+@Table(name="CLIENT_SESSION_ROLE")
+@Entity
+@IdClass(ClientSessionRoleEntity.Key.class)
+public class ClientSessionRoleEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name="CLIENT_SESSION")
+    protected ClientSessionEntity clientSession;
+
+    @Id
+    @Column(name = "ROLE_ID")
+    protected String roleId;
+
+    public ClientSessionEntity getClientSession() {
+        return clientSession;
+    }
+
+    public void setClientSession(ClientSessionEntity clientSession) {
+        this.clientSession = clientSession;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+
+    public static class Key implements Serializable {
+
+        protected ClientSessionEntity clientSession;
+
+        protected String roleId;
+
+        public Key() {
+        }
+
+        public Key(ClientSessionEntity clientSession, String roleId) {
+            this.clientSession = clientSession;
+            this.roleId = roleId;
+        }
+
+        public ClientSessionEntity getClientSession() {
+            return clientSession;
+        }
+
+        public String getRoleId() {
+            return roleId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (!roleId.equals(key.roleId)) return false;
+            if (!clientSession.getId().equals(key.clientSession.getId())) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = clientSession.getId().hashCode();
+            result = 31 * result + roleId.hashCode();
+            return result;
+        }
+    }
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientUserSessionNoteEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientUserSessionNoteEntity.java
index 9051925..3804ed4 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientUserSessionNoteEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientUserSessionNoteEntity.java
@@ -1,109 +1,109 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name = "removeClientUserSessionNoteByUser", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
-        @NamedQuery(name = "removeClientUserSessionNoteByClient", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientUserSessionNoteByRealm", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
-        @NamedQuery(name = "removeClientUserSessionNoteByExpired", query = "delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
-        @NamedQuery(name = "removeDetachedUserClientSessionNoteByExpired", query = "delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
-})
-@Table(name="CLIENT_USER_SESSION_NOTE")
-@Entity
-@IdClass(ClientUserSessionNoteEntity.Key.class)
-public class ClientUserSessionNoteEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "CLIENT_SESSION")
-    protected ClientSessionEntity clientSession;
-
-    @Id
-    @Column(name = "NAME")
-    protected String name;
-    @Column(name = "VALUE")
-    protected String value;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public ClientSessionEntity getClientSession() {
-        return clientSession;
-    }
-
-    public void setClientSession(ClientSessionEntity clientSession) {
-        this.clientSession = clientSession;
-    }
-
-    public static class Key implements Serializable {
-
-        protected ClientSessionEntity clientSession;
-
-        protected String name;
-
-        public Key() {
-        }
-
-        public Key(ClientSessionEntity clientSession, String name) {
-            this.clientSession = clientSession;
-            this.name = name;
-        }
-
-        public ClientSessionEntity getClientSession() {
-            return clientSession;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (name != null ? !name.equals(key.name) : key.name != null) return false;
-            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
-            result = 31 * result + (name != null ? name.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name = "removeClientUserSessionNoteByUser", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+        @NamedQuery(name = "removeClientUserSessionNoteByClient", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientUserSessionNoteByRealm", query="delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientUserSessionNoteByExpired", query = "delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
+        @NamedQuery(name = "removeDetachedUserClientSessionNoteByExpired", query = "delete from ClientUserSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
+})
+@Table(name="CLIENT_USER_SESSION_NOTE")
+@Entity
+@IdClass(ClientUserSessionNoteEntity.Key.class)
+public class ClientUserSessionNoteEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "CLIENT_SESSION")
+    protected ClientSessionEntity clientSession;
+
+    @Id
+    @Column(name = "NAME")
+    protected String name;
+    @Column(name = "VALUE")
+    protected String value;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public ClientSessionEntity getClientSession() {
+        return clientSession;
+    }
+
+    public void setClientSession(ClientSessionEntity clientSession) {
+        this.clientSession = clientSession;
+    }
+
+    public static class Key implements Serializable {
+
+        protected ClientSessionEntity clientSession;
+
+        protected String name;
+
+        public Key() {
+        }
+
+        public Key(ClientSessionEntity clientSession, String name) {
+            this.clientSession = clientSession;
+            this.name = name;
+        }
+
+        public ClientSessionEntity getClientSession() {
+            return clientSession;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (name != null ? !name.equals(key.name) : key.name != null) return false;
+            if (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = clientSession != null ? clientSession.getId().hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UsernameLoginFailureEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UsernameLoginFailureEntity.java
index d03f597..f760d56 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UsernameLoginFailureEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UsernameLoginFailureEntity.java
@@ -1,144 +1,144 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Entity
-@Table(name="USERNAME_LOGIN_FAILURE")
-@NamedQueries({
-        @NamedQuery(name="getAllFailures", query="select failure from UsernameLoginFailureEntity failure"),
-        @NamedQuery(name = "removeLoginFailuresByRealm", query = "delete from UsernameLoginFailureEntity f where f.realmId = :realmId"),
-        @NamedQuery(name = "removeLoginFailuresByUser", query = "delete from UsernameLoginFailureEntity f where f.realmId = :realmId and (f.username = :username or f.username = :email)")
-})
-@IdClass(UsernameLoginFailureEntity.Key.class)
-public class UsernameLoginFailureEntity {
-
-    @Id
-    @Column(name="USERNAME",length = 200)
-    protected String username;
-
-    @Id
-    @Column(name="REALM_ID",length = 36)
-    protected String realmId;
-
-    @Column(name="FAILED_LOGIN_NOT_BEFORE")
-    protected int failedLoginNotBefore;
-
-    @Column(name="NUM_FAILURES")
-    protected int numFailures;
-
-    @Column(name="LAST_FAILURE")
-    protected long lastFailure;
-
-    @Column(name="LAST_IP_FAILURE")
-    protected String lastIPFailure;
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public int getFailedLoginNotBefore() {
-        return failedLoginNotBefore;
-    }
-
-    public void setFailedLoginNotBefore(int failedLoginNotBefore) {
-        this.failedLoginNotBefore = failedLoginNotBefore;
-    }
-
-    public int getNumFailures() {
-        return numFailures;
-    }
-
-    public void setNumFailures(int numFailures) {
-        this.numFailures = numFailures;
-    }
-
-    public long getLastFailure() {
-        return lastFailure;
-    }
-
-    public void setLastFailure(long lastFailure) {
-        this.lastFailure = lastFailure;
-    }
-
-    public String getLastIPFailure() {
-        return lastIPFailure;
-    }
-
-    public void setLastIPFailure(String lastIPFailure) {
-        this.lastIPFailure = lastIPFailure;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public void clearFailures() {
-        setFailedLoginNotBefore(0);
-        setLastFailure(0);
-        setLastIPFailure(null);
-        setNumFailures(0);
-    }
-
-    public static class Key implements Serializable {
-
-        private String realmId;
-
-        private String username;
-
-        public Key() {
-        }
-
-        public Key(String realmId, String username) {
-            this.realmId = realmId;
-            this.username = username;
-        }
-
-        public String getRealmId() {
-            return realmId;
-        }
-
-        public String getUsername() {
-            return username;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (realmId != null ? !realmId.equals(key.realmId) : key.realmId != null) return false;
-            if (username != null ? !username.equals(key.username) : key.username != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = realmId != null ? realmId.hashCode() : 0;
-            result = 31 * result + (username != null ? username.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Entity
+@Table(name="USERNAME_LOGIN_FAILURE")
+@NamedQueries({
+        @NamedQuery(name="getAllFailures", query="select failure from UsernameLoginFailureEntity failure"),
+        @NamedQuery(name = "removeLoginFailuresByRealm", query = "delete from UsernameLoginFailureEntity f where f.realmId = :realmId"),
+        @NamedQuery(name = "removeLoginFailuresByUser", query = "delete from UsernameLoginFailureEntity f where f.realmId = :realmId and (f.username = :username or f.username = :email)")
+})
+@IdClass(UsernameLoginFailureEntity.Key.class)
+public class UsernameLoginFailureEntity {
+
+    @Id
+    @Column(name="USERNAME",length = 200)
+    protected String username;
+
+    @Id
+    @Column(name="REALM_ID",length = 36)
+    protected String realmId;
+
+    @Column(name="FAILED_LOGIN_NOT_BEFORE")
+    protected int failedLoginNotBefore;
+
+    @Column(name="NUM_FAILURES")
+    protected int numFailures;
+
+    @Column(name="LAST_FAILURE")
+    protected long lastFailure;
+
+    @Column(name="LAST_IP_FAILURE")
+    protected String lastIPFailure;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public int getFailedLoginNotBefore() {
+        return failedLoginNotBefore;
+    }
+
+    public void setFailedLoginNotBefore(int failedLoginNotBefore) {
+        this.failedLoginNotBefore = failedLoginNotBefore;
+    }
+
+    public int getNumFailures() {
+        return numFailures;
+    }
+
+    public void setNumFailures(int numFailures) {
+        this.numFailures = numFailures;
+    }
+
+    public long getLastFailure() {
+        return lastFailure;
+    }
+
+    public void setLastFailure(long lastFailure) {
+        this.lastFailure = lastFailure;
+    }
+
+    public String getLastIPFailure() {
+        return lastIPFailure;
+    }
+
+    public void setLastIPFailure(String lastIPFailure) {
+        this.lastIPFailure = lastIPFailure;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public void clearFailures() {
+        setFailedLoginNotBefore(0);
+        setLastFailure(0);
+        setLastIPFailure(null);
+        setNumFailures(0);
+    }
+
+    public static class Key implements Serializable {
+
+        private String realmId;
+
+        private String username;
+
+        public Key() {
+        }
+
+        public Key(String realmId, String username) {
+            this.realmId = realmId;
+            this.username = username;
+        }
+
+        public String getRealmId() {
+            return realmId;
+        }
+
+        public String getUsername() {
+            return username;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (realmId != null ? !realmId.equals(key.realmId) : key.realmId != null) return false;
+            if (username != null ? !username.equals(key.username) : key.username != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = realmId != null ? realmId.hashCode() : 0;
+            result = 31 * result + (username != null ? username.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java
index d4bd889..3956a57 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java
@@ -1,108 +1,108 @@
-package org.keycloak.models.sessions.jpa.entities;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@NamedQueries({
-        @NamedQuery(name = "selectNoteByNameValue", query="select r from UserSessionNoteEntity r where r.name = :name and r.value = :value"),
-        @NamedQuery(name = "removeUserSessionNoteByUser", query="delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId)"),
-        @NamedQuery(name = "removeUserSessionNoteByRealm", query="delete from UserSessionNoteEntity r where r.userSession IN (select c from UserSessionEntity c where c.realmId = :realmId)"),
-        @NamedQuery(name = "removeUserSessionNoteByExpired", query = "delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime))")
-})
-@Table(name="USER_SESSION_NOTE")
-@Entity
-@IdClass(UserSessionNoteEntity.Key.class)
-public class UserSessionNoteEntity {
-
-    @Id
-    @ManyToOne(fetch= FetchType.LAZY)
-    @JoinColumn(name = "USER_SESSION")
-    protected UserSessionEntity userSession;
-
-    @Id
-    @Column(name = "NAME")
-    protected String name;
-    @Column(name = "VALUE")
-    protected String value;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    public UserSessionEntity getUserSession() {
-        return userSession;
-    }
-
-    public void setUserSession(UserSessionEntity userSession) {
-        this.userSession = userSession;
-    }
-
-    public static class Key implements Serializable {
-
-        protected UserSessionEntity userSession;
-
-        protected String name;
-
-        public Key() {
-        }
-
-        public Key(UserSessionEntity clientSession, String name) {
-            this.userSession = clientSession;
-            this.name = name;
-        }
-
-        public UserSessionEntity getUserSession() {
-            return userSession;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Key key = (Key) o;
-
-            if (name != null ? !name.equals(key.name) : key.name != null) return false;
-            if (userSession != null ? !userSession.getId().equals(key.userSession != null ? key.userSession.getId() : null) : key.userSession != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = userSession != null ? userSession.getId().hashCode() : 0;
-            result = 31 * result + (name != null ? name.hashCode() : 0);
-            return result;
-        }
-    }
-
-}
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+        @NamedQuery(name = "selectNoteByNameValue", query="select r from UserSessionNoteEntity r where r.name = :name and r.value = :value"),
+        @NamedQuery(name = "removeUserSessionNoteByUser", query="delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId)"),
+        @NamedQuery(name = "removeUserSessionNoteByRealm", query="delete from UserSessionNoteEntity r where r.userSession IN (select c from UserSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeUserSessionNoteByExpired", query = "delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime))")
+})
+@Table(name="USER_SESSION_NOTE")
+@Entity
+@IdClass(UserSessionNoteEntity.Key.class)
+public class UserSessionNoteEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name = "USER_SESSION")
+    protected UserSessionEntity userSession;
+
+    @Id
+    @Column(name = "NAME")
+    protected String name;
+    @Column(name = "VALUE")
+    protected String value;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public UserSessionEntity getUserSession() {
+        return userSession;
+    }
+
+    public void setUserSession(UserSessionEntity userSession) {
+        this.userSession = userSession;
+    }
+
+    public static class Key implements Serializable {
+
+        protected UserSessionEntity userSession;
+
+        protected String name;
+
+        public Key() {
+        }
+
+        public Key(UserSessionEntity clientSession, String name) {
+            this.userSession = clientSession;
+            this.name = name;
+        }
+
+        public UserSessionEntity getUserSession() {
+            return userSession;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (name != null ? !name.equals(key.name) : key.name != null) return false;
+            if (userSession != null ? !userSession.getId().equals(key.userSession != null ? key.userSession.getId() : null) : key.userSession != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = userSession != null ? userSession.getId().hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            return result;
+        }
+    }
+
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaKeycloakTransaction.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaKeycloakTransaction.java
index 09f92c0..7af2775 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaKeycloakTransaction.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaKeycloakTransaction.java
@@ -1,53 +1,53 @@
-package org.keycloak.models.sessions.jpa;
-
-import org.keycloak.models.KeycloakTransaction;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class JpaKeycloakTransaction implements KeycloakTransaction {
-
-    protected EntityManager em;
-
-    public JpaKeycloakTransaction(EntityManager em) {
-        this.em = em;
-    }
-
-    @Override
-    public void begin() {
-        em.getTransaction().begin();
-    }
-
-    @Override
-    public void commit() {
-        try {
-            em.getTransaction().commit();
-        } catch (PersistenceException e) {
-            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
-        }
-    }
-
-    @Override
-    public void rollback() {
-        em.getTransaction().rollback();
-    }
-
-    @Override
-    public void setRollbackOnly() {
-        em.getTransaction().setRollbackOnly();
-    }
-
-    @Override
-    public boolean getRollbackOnly() {
-        return  em.getTransaction().getRollbackOnly();
-    }
-
-    @Override
-    public boolean isActive() {
-        return em.getTransaction().isActive();
-    }
-}
+package org.keycloak.models.sessions.jpa;
+
+import org.keycloak.models.KeycloakTransaction;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JpaKeycloakTransaction implements KeycloakTransaction {
+
+    protected EntityManager em;
+
+    public JpaKeycloakTransaction(EntityManager em) {
+        this.em = em;
+    }
+
+    @Override
+    public void begin() {
+        em.getTransaction().begin();
+    }
+
+    @Override
+    public void commit() {
+        try {
+            em.getTransaction().commit();
+        } catch (PersistenceException e) {
+            throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
+        }
+    }
+
+    @Override
+    public void rollback() {
+        em.getTransaction().rollback();
+    }
+
+    @Override
+    public void setRollbackOnly() {
+        em.getTransaction().setRollbackOnly();
+    }
+
+    @Override
+    public boolean getRollbackOnly() {
+        return  em.getTransaction().getRollbackOnly();
+    }
+
+    @Override
+    public boolean isActive() {
+        return em.getTransaction().isActive();
+    }
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UsernameLoginFailureAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UsernameLoginFailureAdapter.java
index 9293648..ebe1d2e 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UsernameLoginFailureAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UsernameLoginFailureAdapter.java
@@ -1,69 +1,69 @@
-package org.keycloak.models.sessions.jpa;
-
-import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernameLoginFailureAdapter implements UsernameLoginFailureModel
-{
-   protected UsernameLoginFailureEntity user;
-
-   public UsernameLoginFailureAdapter(UsernameLoginFailureEntity user) {
-      this.user = user;
-   }
-
-   @Override
-   public String getUsername()
-   {
-      return user.getUsername();
-   }
-
-   @Override
-   public int getFailedLoginNotBefore() {
-      return user.getFailedLoginNotBefore();
-   }
-
-   @Override
-   public void setFailedLoginNotBefore(int notBefore) {
-      user.setFailedLoginNotBefore(notBefore);
-   }
-
-   @Override
-   public int getNumFailures() {
-      return user.getNumFailures();
-   }
-
-   @Override
-   public void incrementFailures() {
-      user.setNumFailures(getNumFailures() + 1);
-   }
-
-   @Override
-   public void clearFailures() {
-      user.clearFailures();
-   }
-
-   @Override
-   public long getLastFailure() {
-      return user.getLastFailure();
-   }
-
-   @Override
-   public void setLastFailure(long lastFailure) {
-      user.setLastFailure(lastFailure);
-   }
-
-   @Override
-   public String getLastIPFailure() {
-      return user.getLastIPFailure();
-   }
-
-   @Override
-   public void setLastIPFailure(String ip) {
-      user.setLastIPFailure(ip);
-   }
-
-}
+package org.keycloak.models.sessions.jpa;
+
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernameLoginFailureAdapter implements UsernameLoginFailureModel
+{
+   protected UsernameLoginFailureEntity user;
+
+   public UsernameLoginFailureAdapter(UsernameLoginFailureEntity user) {
+      this.user = user;
+   }
+
+   @Override
+   public String getUsername()
+   {
+      return user.getUsername();
+   }
+
+   @Override
+   public int getFailedLoginNotBefore() {
+      return user.getFailedLoginNotBefore();
+   }
+
+   @Override
+   public void setFailedLoginNotBefore(int notBefore) {
+      user.setFailedLoginNotBefore(notBefore);
+   }
+
+   @Override
+   public int getNumFailures() {
+      return user.getNumFailures();
+   }
+
+   @Override
+   public void incrementFailures() {
+      user.setNumFailures(getNumFailures() + 1);
+   }
+
+   @Override
+   public void clearFailures() {
+      user.clearFailures();
+   }
+
+   @Override
+   public long getLastFailure() {
+      return user.getLastFailure();
+   }
+
+   @Override
+   public void setLastFailure(long lastFailure) {
+      user.setLastFailure(lastFailure);
+   }
+
+   @Override
+   public String getLastIPFailure() {
+      return user.getLastIPFailure();
+   }
+
+   @Override
+   public void setLastIPFailure(String ip) {
+      user.setLastIPFailure(ip);
+   }
+
+}
diff --git a/model/sessions-mem/pom.xml b/model/sessions-mem/pom.xml
index f630a80..4995926 100755
--- a/model/sessions-mem/pom.xml
+++ b/model/sessions-mem/pom.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-sessions-mem</artifactId>
-    <name>Keycloak Model Sessions Mem</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-sessions-mem</artifactId>
+    <name>Keycloak Model Sessions Mem</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
index c54d341..27c744e 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
@@ -1,200 +1,200 @@
-package org.keycloak.models.sessions.mem;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.sessions.mem.entities.ClientSessionEntity;
-import org.keycloak.models.sessions.mem.entities.UserSessionEntity;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionAdapter implements ClientSessionModel {
-
-    private KeycloakSession session;
-    private MemUserSessionProvider provider;
-    private RealmModel realm;
-    private ClientSessionEntity entity;
-
-    public ClientSessionAdapter(KeycloakSession session, MemUserSessionProvider provider, RealmModel realm, ClientSessionEntity entity) {
-        this.session = session;
-        this.provider = provider;
-        this.realm = realm;
-        this.entity = entity;
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return session.realms().getRealm(entity.getRealmId());
-    }
-
-    public ClientSessionEntity getEntity() {
-        return entity;
-    }
-
-    @Override
-    public ClientModel getClient() {
-        return realm.getClientById(entity.getClientId());
-    }
-
-    @Override
-    public UserSessionModel getUserSession() {
-        if (entity.getSession() == null) return null;
-        return new UserSessionAdapter(session, provider, realm, entity.getSession());
-    }
-
-    @Override
-    public void setUserSession(UserSessionModel userSession) {
-        if (userSession == null) {
-            if (entity.getSession() != null) {
-                entity.getSession().getClientSessions().remove(entity);
-            }
-            entity.setSession(null);
-        } else {
-            UserSessionAdapter adapter = (UserSessionAdapter) userSession;
-            UserSessionEntity userSessionEntity = adapter.getEntity();
-            entity.setSession(userSessionEntity);
-            userSessionEntity.getClientSessions().add(entity);
-        }
-    }
-
-    @Override
-    public void setRedirectUri(String uri) {
-        entity.setRedirectUri(uri);
-    }
-
-    @Override
-    public void setRoles(Set<String> roles) {
-        entity.setRoles(roles);
-    }
-
-    @Override
-    public String getRedirectUri() {
-        return entity.getRedirectUri();
-    }
-
-    @Override
-    public int getTimestamp() {
-        return entity.getTimestamp();
-    }
-
-    @Override
-    public void setTimestamp(int timestamp) {
-        entity.setTimestamp(timestamp);
-    }
-
-    @Override
-    public String getAction() {
-        return entity.getAction();
-    }
-
-    @Override
-    public void setAction(String action) {
-        entity.setAction(action);
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        return entity.getRoles();
-    }
-
-    @Override
-    public Set<String> getProtocolMappers() {
-        return entity.getProtocolMappers();
-    }
-
-    @Override
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        entity.setProtocolMappers(protocolMappers);
-    }
-
-    @Override
-    public String getNote(String name) {
-        return entity.getNotes().get(name);
-    }
-
-    @Override
-    public void setNote(String name, String value) {
-        entity.getNotes().put(name, value);
-
-    }
-
-    @Override
-    public void removeNote(String name) {
-        entity.getNotes().remove(name);
-
-    }
-
-    @Override
-    public Map<String, String> getNotes() {
-        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
-        Map<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getNotes());
-        return copy;
-   }
-
-    @Override
-    public void setUserSessionNote(String name, String value) {
-        entity.getUserSessionNotes().put(name, value);
-    }
-
-    @Override
-    public Map<String, String> getUserSessionNotes() {
-        return entity.getUserSessionNotes();
-    }
-
-    @Override
-    public String getAuthMethod() {
-        return entity.getAuthMethod();
-    }
-
-    @Override
-    public void setAuthMethod(String method) {
-        entity.setAuthMethod(method);
-    }
-
-    @Override
-    public Map<String, ExecutionStatus> getExecutionStatus() {
-        return entity.getAuthenticatorStatus();
-    }
-
-    @Override
-    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
-        entity.getAuthenticatorStatus().put(authenticator, status);
-
-    }
-
-    @Override
-    public void clearExecutionStatus() {
-        entity.getAuthenticatorStatus().clear();
-    }
-
-    @Override
-    public void clearUserSessionNotes() {
-        entity.getUserSessionNotes().clear();
-    }
-
-    @Override
-    public UserModel getAuthenticatedUser() {
-        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);    }
-
-    @Override
-    public void setAuthenticatedUser(UserModel user) {
-        if (user == null) entity.setAuthUserId(null);
-        else entity.setAuthUserId(user.getId());
-
-    }
-}
+package org.keycloak.models.sessions.mem;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.sessions.mem.entities.ClientSessionEntity;
+import org.keycloak.models.sessions.mem.entities.UserSessionEntity;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionAdapter implements ClientSessionModel {
+
+    private KeycloakSession session;
+    private MemUserSessionProvider provider;
+    private RealmModel realm;
+    private ClientSessionEntity entity;
+
+    public ClientSessionAdapter(KeycloakSession session, MemUserSessionProvider provider, RealmModel realm, ClientSessionEntity entity) {
+        this.session = session;
+        this.provider = provider;
+        this.realm = realm;
+        this.entity = entity;
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return session.realms().getRealm(entity.getRealmId());
+    }
+
+    public ClientSessionEntity getEntity() {
+        return entity;
+    }
+
+    @Override
+    public ClientModel getClient() {
+        return realm.getClientById(entity.getClientId());
+    }
+
+    @Override
+    public UserSessionModel getUserSession() {
+        if (entity.getSession() == null) return null;
+        return new UserSessionAdapter(session, provider, realm, entity.getSession());
+    }
+
+    @Override
+    public void setUserSession(UserSessionModel userSession) {
+        if (userSession == null) {
+            if (entity.getSession() != null) {
+                entity.getSession().getClientSessions().remove(entity);
+            }
+            entity.setSession(null);
+        } else {
+            UserSessionAdapter adapter = (UserSessionAdapter) userSession;
+            UserSessionEntity userSessionEntity = adapter.getEntity();
+            entity.setSession(userSessionEntity);
+            userSessionEntity.getClientSessions().add(entity);
+        }
+    }
+
+    @Override
+    public void setRedirectUri(String uri) {
+        entity.setRedirectUri(uri);
+    }
+
+    @Override
+    public void setRoles(Set<String> roles) {
+        entity.setRoles(roles);
+    }
+
+    @Override
+    public String getRedirectUri() {
+        return entity.getRedirectUri();
+    }
+
+    @Override
+    public int getTimestamp() {
+        return entity.getTimestamp();
+    }
+
+    @Override
+    public void setTimestamp(int timestamp) {
+        entity.setTimestamp(timestamp);
+    }
+
+    @Override
+    public String getAction() {
+        return entity.getAction();
+    }
+
+    @Override
+    public void setAction(String action) {
+        entity.setAction(action);
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        return entity.getRoles();
+    }
+
+    @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers();
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        entity.setProtocolMappers(protocolMappers);
+    }
+
+    @Override
+    public String getNote(String name) {
+        return entity.getNotes().get(name);
+    }
+
+    @Override
+    public void setNote(String name, String value) {
+        entity.getNotes().put(name, value);
+
+    }
+
+    @Override
+    public void removeNote(String name) {
+        entity.getNotes().remove(name);
+
+    }
+
+    @Override
+    public Map<String, String> getNotes() {
+        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
+        Map<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getNotes());
+        return copy;
+   }
+
+    @Override
+    public void setUserSessionNote(String name, String value) {
+        entity.getUserSessionNotes().put(name, value);
+    }
+
+    @Override
+    public Map<String, String> getUserSessionNotes() {
+        return entity.getUserSessionNotes();
+    }
+
+    @Override
+    public String getAuthMethod() {
+        return entity.getAuthMethod();
+    }
+
+    @Override
+    public void setAuthMethod(String method) {
+        entity.setAuthMethod(method);
+    }
+
+    @Override
+    public Map<String, ExecutionStatus> getExecutionStatus() {
+        return entity.getAuthenticatorStatus();
+    }
+
+    @Override
+    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
+        entity.getAuthenticatorStatus().put(authenticator, status);
+
+    }
+
+    @Override
+    public void clearExecutionStatus() {
+        entity.getAuthenticatorStatus().clear();
+    }
+
+    @Override
+    public void clearUserSessionNotes() {
+        entity.getUserSessionNotes().clear();
+    }
+
+    @Override
+    public UserModel getAuthenticatedUser() {
+        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);    }
+
+    @Override
+    public void setAuthenticatedUser(UserModel user) {
+        if (user == null) entity.setAuthUserId(null);
+        else entity.setAuthUserId(user.getId());
+
+    }
+}
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
index 056e5a2..7c6fb22 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
@@ -1,152 +1,152 @@
-package org.keycloak.models.sessions.mem.entities;
-
-import org.keycloak.models.ClientSessionModel;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionEntity {
-
-    private String id;
-    private String clientId;
-    private String realmId;
-    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
-    private String authUserId;
-
-    private UserSessionEntity session;
-
-    private String redirectUri;
-    private String authMethod;
-
-    private int timestamp;
-    private String action;
-    private Set<String> roles;
-    private Set<String> protocolMappers;
-    private Map<String, String> notes = new HashMap<>();
-    private Map<String, String> userSessionNotes = new HashMap<>();
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public UserSessionEntity getSession() {
-        return session;
-    }
-
-    public void setSession(UserSessionEntity session) {
-        this.session = session;
-    }
-
-    public String getRedirectUri() {
-        return redirectUri;
-    }
-
-    public void setRedirectUri(String redirectUri) {
-        this.redirectUri = redirectUri;
-    }
-
-    public int getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(int timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public Set<String> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(Set<String> roles) {
-        this.roles = roles;
-    }
-
-    public Set<String> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public Map<String, String> getNotes() {
-        return notes;
-    }
-
-    public String getAuthMethod() {
-        return authMethod;
-    }
-
-    public void setAuthMethod(String authMethod) {
-        this.authMethod = authMethod;
-    }
-
-    public String getAuthUserId() {
-        return authUserId;
-    }
-
-    public void setAuthUserId(String authUserId) {
-        this.authUserId = authUserId;
-    }
-
-    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
-        return authenticatorStatus;
-    }
-
-    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
-        this.authenticatorStatus = authenticatorStatus;
-    }
-
-    public Map<String, String> getUserSessionNotes() {
-        return userSessionNotes;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof ClientSessionEntity)) return false;
-
-        ClientSessionEntity that = (ClientSessionEntity) o;
-
-        if (id != null ? !id.equals(that.id) : that.id != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return id != null ? id.hashCode() : 0;
-    }
-}
+package org.keycloak.models.sessions.mem.entities;
+
+import org.keycloak.models.ClientSessionModel;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionEntity {
+
+    private String id;
+    private String clientId;
+    private String realmId;
+    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
+    private String authUserId;
+
+    private UserSessionEntity session;
+
+    private String redirectUri;
+    private String authMethod;
+
+    private int timestamp;
+    private String action;
+    private Set<String> roles;
+    private Set<String> protocolMappers;
+    private Map<String, String> notes = new HashMap<>();
+    private Map<String, String> userSessionNotes = new HashMap<>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public UserSessionEntity getSession() {
+        return session;
+    }
+
+    public void setSession(UserSessionEntity session) {
+        this.session = session;
+    }
+
+    public String getRedirectUri() {
+        return redirectUri;
+    }
+
+    public void setRedirectUri(String redirectUri) {
+        this.redirectUri = redirectUri;
+    }
+
+    public int getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(int timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Set<String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Set<String> roles) {
+        this.roles = roles;
+    }
+
+    public Set<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public Map<String, String> getNotes() {
+        return notes;
+    }
+
+    public String getAuthMethod() {
+        return authMethod;
+    }
+
+    public void setAuthMethod(String authMethod) {
+        this.authMethod = authMethod;
+    }
+
+    public String getAuthUserId() {
+        return authUserId;
+    }
+
+    public void setAuthUserId(String authUserId) {
+        this.authUserId = authUserId;
+    }
+
+    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
+        return authenticatorStatus;
+    }
+
+    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
+        this.authenticatorStatus = authenticatorStatus;
+    }
+
+    public Map<String, String> getUserSessionNotes() {
+        return userSessionNotes;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ClientSessionEntity)) return false;
+
+        ClientSessionEntity that = (ClientSessionEntity) o;
+
+        if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
+}
diff --git a/model/sessions-mongo/pom.xml b/model/sessions-mongo/pom.xml
index 3774a6f..557268b 100755
--- a/model/sessions-mongo/pom.xml
+++ b/model/sessions-mongo/pom.xml
@@ -1,39 +1,39 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-model-sessions-mongo</artifactId>
-    <name>Keycloak Model Sessions Mongo</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-mongo</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-sessions-mongo</artifactId>
+    <name>Keycloak Model Sessions Mongo</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-mongo</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
 </project>
\ No newline at end of file
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
index 7545dd0..307b95b 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
@@ -1,234 +1,234 @@
-package org.keycloak.models.sessions.mongo;
-
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity;
-import org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientSessionAdapter extends AbstractMongoAdapter<MongoClientSessionEntity> implements ClientSessionModel {
-
-    private KeycloakSession session;
-    private MongoUserSessionProvider provider;
-    private RealmModel realm;
-    private MongoClientSessionEntity entity;
-
-    public ClientSessionAdapter(KeycloakSession session, MongoUserSessionProvider provider, RealmModel realm, MongoClientSessionEntity entity, MongoStoreInvocationContext invContext) {
-        super(invContext);
-        this.session = session;
-        this.provider = provider;
-        this.realm = realm;
-        this.entity = entity;
-    }
-
-    @Override
-    public String getId() {
-        return entity.getId();
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return session.realms().getRealm(entity.getRealmId());
-    }
-
-    @Override
-    public ClientModel getClient() {
-        return realm.getClientById(entity.getClientId());
-    }
-
-    @Override
-    public UserSessionModel getUserSession() {
-        if (entity.getSessionId() == null) return null;
-        return provider.getUserSession(realm, entity.getSessionId());
-    }
-
-    @Override
-    public void setUserSession(UserSessionModel userSession) {
-        if (userSession == null) {
-            if (entity.getSessionId() != null) {
-                MongoUserSessionEntity userSessionEntity = provider.getUserSessionEntity(realm, entity.getSessionId());
-                provider.getMongoStore().pullItemFromList(userSessionEntity, "clientSessions", entity.getSessionId(), invocationContext);
-            }
-            entity.setSessionId(null);
-        } else {
-            MongoUserSessionEntity userSessionEntity = provider.getUserSessionEntity(realm, userSession.getId());
-            entity.setSessionId(userSessionEntity.getId());
-            updateMongoEntity();
-
-            provider.getMongoStore().pushItemToList(userSessionEntity, "clientSessions", entity.getId(), true, invocationContext);
-        }
-    }
-
-    @Override
-    public void setRedirectUri(String uri) {
-        entity.setRedirectUri(uri);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void setRoles(Set<String> roles) {
-        if (roles == null) {
-            entity.setRoles(null);
-        } else {
-            List<String> list = new LinkedList<String>();
-            list.addAll(roles);
-            entity.setRoles(list);
-        }
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getRedirectUri() {
-        return entity.getRedirectUri();
-    }
-
-    @Override
-    public int getTimestamp() {
-        return entity.getTimestamp();
-    }
-
-    @Override
-    public void setTimestamp(int timestamp) {
-        entity.setTimestamp(timestamp);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getAction() {
-        return entity.getAction();
-    }
-
-    @Override
-    public void setAction(String action) {
-        entity.setAction(action);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        return entity.getRoles() != null ? new HashSet<String>(entity.getRoles()) : null;
-    }
-
-    @Override
-    public Set<String> getProtocolMappers() {
-        return entity.getProtocolMappers() != null ? new HashSet<String>(entity.getProtocolMappers()) : null;
-    }
-
-    @Override
-    public void setProtocolMappers(Set<String> protocolMappers) {
-        if (protocolMappers == null) {
-            entity.setProtocolMappers(null);
-        } else {
-            List<String> list = new LinkedList<String>();
-            list.addAll(protocolMappers);
-            entity.setProtocolMappers(list);
-        }
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getNote(String name) {
-        return entity.getNotes().get(name);
-    }
-
-    @Override
-    public void setNote(String name, String value) {
-        entity.getNotes().put(name, value);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void removeNote(String name) {
-        entity.getNotes().remove(name);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Map<String, String> getNotes() {
-        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
-        Map<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getNotes());
-        return copy;
-    }
-
-
-    @Override
-    public void setUserSessionNote(String name, String value) {
-        entity.getUserSessionNotes().put(name, value);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Map<String, String> getUserSessionNotes() {
-        Map<String, String> copy = new HashMap<>();
-        copy.putAll(entity.getUserSessionNotes());
-        return copy;
-    }
-
-    @Override
-    public Map<String, ExecutionStatus> getExecutionStatus() {
-        return entity.getAuthenticatorStatus();
-    }
-
-    @Override
-    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
-        entity.getAuthenticatorStatus().put(authenticator, status);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public void clearExecutionStatus() {
-        entity.getAuthenticatorStatus().clear();
-        updateMongoEntity();
-    }
-
-    @Override
-    public void clearUserSessionNotes() {
-        entity.getUserSessionNotes().clear();
-    }
-
-    @Override
-    public UserModel getAuthenticatedUser() {
-        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);
-    }
-
-    @Override
-    public void setAuthenticatedUser(UserModel user) {
-        if (user == null) entity.setAuthUserId(null);
-        else entity.setAuthUserId(user.getId());
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public String getAuthMethod() {
-        return entity.getAuthMethod();
-    }
-
-    @Override
-    public void setAuthMethod(String method) {
-        entity.setAuthMethod(method);
-        updateMongoEntity();
-    }
-
-    @Override
-    protected MongoClientSessionEntity getMongoEntity() {
-        return entity;
-    }
-}
+package org.keycloak.models.sessions.mongo;
+
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity;
+import org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientSessionAdapter extends AbstractMongoAdapter<MongoClientSessionEntity> implements ClientSessionModel {
+
+    private KeycloakSession session;
+    private MongoUserSessionProvider provider;
+    private RealmModel realm;
+    private MongoClientSessionEntity entity;
+
+    public ClientSessionAdapter(KeycloakSession session, MongoUserSessionProvider provider, RealmModel realm, MongoClientSessionEntity entity, MongoStoreInvocationContext invContext) {
+        super(invContext);
+        this.session = session;
+        this.provider = provider;
+        this.realm = realm;
+        this.entity = entity;
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return session.realms().getRealm(entity.getRealmId());
+    }
+
+    @Override
+    public ClientModel getClient() {
+        return realm.getClientById(entity.getClientId());
+    }
+
+    @Override
+    public UserSessionModel getUserSession() {
+        if (entity.getSessionId() == null) return null;
+        return provider.getUserSession(realm, entity.getSessionId());
+    }
+
+    @Override
+    public void setUserSession(UserSessionModel userSession) {
+        if (userSession == null) {
+            if (entity.getSessionId() != null) {
+                MongoUserSessionEntity userSessionEntity = provider.getUserSessionEntity(realm, entity.getSessionId());
+                provider.getMongoStore().pullItemFromList(userSessionEntity, "clientSessions", entity.getSessionId(), invocationContext);
+            }
+            entity.setSessionId(null);
+        } else {
+            MongoUserSessionEntity userSessionEntity = provider.getUserSessionEntity(realm, userSession.getId());
+            entity.setSessionId(userSessionEntity.getId());
+            updateMongoEntity();
+
+            provider.getMongoStore().pushItemToList(userSessionEntity, "clientSessions", entity.getId(), true, invocationContext);
+        }
+    }
+
+    @Override
+    public void setRedirectUri(String uri) {
+        entity.setRedirectUri(uri);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void setRoles(Set<String> roles) {
+        if (roles == null) {
+            entity.setRoles(null);
+        } else {
+            List<String> list = new LinkedList<String>();
+            list.addAll(roles);
+            entity.setRoles(list);
+        }
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getRedirectUri() {
+        return entity.getRedirectUri();
+    }
+
+    @Override
+    public int getTimestamp() {
+        return entity.getTimestamp();
+    }
+
+    @Override
+    public void setTimestamp(int timestamp) {
+        entity.setTimestamp(timestamp);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getAction() {
+        return entity.getAction();
+    }
+
+    @Override
+    public void setAction(String action) {
+        entity.setAction(action);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Set<String> getRoles() {
+        return entity.getRoles() != null ? new HashSet<String>(entity.getRoles()) : null;
+    }
+
+    @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers() != null ? new HashSet<String>(entity.getProtocolMappers()) : null;
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        if (protocolMappers == null) {
+            entity.setProtocolMappers(null);
+        } else {
+            List<String> list = new LinkedList<String>();
+            list.addAll(protocolMappers);
+            entity.setProtocolMappers(list);
+        }
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getNote(String name) {
+        return entity.getNotes().get(name);
+    }
+
+    @Override
+    public void setNote(String name, String value) {
+        entity.getNotes().put(name, value);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void removeNote(String name) {
+        entity.getNotes().remove(name);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Map<String, String> getNotes() {
+        if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
+        Map<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getNotes());
+        return copy;
+    }
+
+
+    @Override
+    public void setUserSessionNote(String name, String value) {
+        entity.getUserSessionNotes().put(name, value);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Map<String, String> getUserSessionNotes() {
+        Map<String, String> copy = new HashMap<>();
+        copy.putAll(entity.getUserSessionNotes());
+        return copy;
+    }
+
+    @Override
+    public Map<String, ExecutionStatus> getExecutionStatus() {
+        return entity.getAuthenticatorStatus();
+    }
+
+    @Override
+    public void setExecutionStatus(String authenticator, ExecutionStatus status) {
+        entity.getAuthenticatorStatus().put(authenticator, status);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public void clearExecutionStatus() {
+        entity.getAuthenticatorStatus().clear();
+        updateMongoEntity();
+    }
+
+    @Override
+    public void clearUserSessionNotes() {
+        entity.getUserSessionNotes().clear();
+    }
+
+    @Override
+    public UserModel getAuthenticatedUser() {
+        return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm);
+    }
+
+    @Override
+    public void setAuthenticatedUser(UserModel user) {
+        if (user == null) entity.setAuthUserId(null);
+        else entity.setAuthUserId(user.getId());
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public String getAuthMethod() {
+        return entity.getAuthMethod();
+    }
+
+    @Override
+    public void setAuthMethod(String method) {
+        entity.setAuthMethod(method);
+        updateMongoEntity();
+    }
+
+    @Override
+    protected MongoClientSessionEntity getMongoEntity() {
+        return entity;
+    }
+}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
index a8dc6a1..de7bed3 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
@@ -1,152 +1,152 @@
-package org.keycloak.models.sessions.mongo.entities;
-
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.entities.AbstractIdentifiableEntity;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-@MongoCollection(collectionName = "clientSessions")
-public class MongoClientSessionEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
-
-    private String id;
-    private String clientId;
-    private String realmId;
-    private String sessionId;
-
-    private String redirectUri;
-    private String authMethod;
-
-    private int timestamp;
-    private String action;
-    private List<String> roles;
-    private List<String> protocolMappers;
-    private Map<String, String> notes = new HashMap<String, String>();
-    private Map<String, String> userSessionNotes = new HashMap<String, String>();
-    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
-    private String authUserId;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public String getRedirectUri() {
-        return redirectUri;
-    }
-
-    public void setRedirectUri(String redirectUri) {
-        this.redirectUri = redirectUri;
-    }
-
-    public String getAuthMethod() {
-        return authMethod;
-    }
-
-    public void setAuthMethod(String authMethod) {
-        this.authMethod = authMethod;
-    }
-
-    public int getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(int timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public List<String> getRoles() {
-        return roles;
-    }
-
-    public void setRoles(List<String> roles) {
-        this.roles = roles;
-    }
-
-    public List<String> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(List<String> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-
-    public Map<String, String> getNotes() {
-        return notes;
-    }
-
-    public void setNotes(Map<String, String> notes) {
-        this.notes = notes;
-    }
-
-    public Map<String, String> getUserSessionNotes() {
-        return userSessionNotes;
-    }
-
-    public void setUserSessionNotes(Map<String, String> userSessionNotes) {
-        this.userSessionNotes = userSessionNotes;
-    }
-
-    public String getSessionId() {
-        return sessionId;
-    }
-
-    public void setSessionId(String sessionId) {
-        this.sessionId = sessionId;
-    }
-
-    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
-        return authenticatorStatus;
-    }
-
-    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
-        this.authenticatorStatus = authenticatorStatus;
-    }
-
-    public String getAuthUserId() {
-        return authUserId;
-    }
-
-    public void setAuthUserId(String authUserId) {
-        this.authUserId = authUserId;
-    }
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext context) {
-    }
-
-}
+package org.keycloak.models.sessions.mongo.entities;
+
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.entities.AbstractIdentifiableEntity;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@MongoCollection(collectionName = "clientSessions")
+public class MongoClientSessionEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
+
+    private String id;
+    private String clientId;
+    private String realmId;
+    private String sessionId;
+
+    private String redirectUri;
+    private String authMethod;
+
+    private int timestamp;
+    private String action;
+    private List<String> roles;
+    private List<String> protocolMappers;
+    private Map<String, String> notes = new HashMap<String, String>();
+    private Map<String, String> userSessionNotes = new HashMap<String, String>();
+    private Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus = new HashMap<>();
+    private String authUserId;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public String getRedirectUri() {
+        return redirectUri;
+    }
+
+    public void setRedirectUri(String redirectUri) {
+        this.redirectUri = redirectUri;
+    }
+
+    public String getAuthMethod() {
+        return authMethod;
+    }
+
+    public void setAuthMethod(String authMethod) {
+        this.authMethod = authMethod;
+    }
+
+    public int getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(int timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(List<String> roles) {
+        this.roles = roles;
+    }
+
+    public List<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(List<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public Map<String, String> getNotes() {
+        return notes;
+    }
+
+    public void setNotes(Map<String, String> notes) {
+        this.notes = notes;
+    }
+
+    public Map<String, String> getUserSessionNotes() {
+        return userSessionNotes;
+    }
+
+    public void setUserSessionNotes(Map<String, String> userSessionNotes) {
+        this.userSessionNotes = userSessionNotes;
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    public Map<String, ClientSessionModel.ExecutionStatus> getAuthenticatorStatus() {
+        return authenticatorStatus;
+    }
+
+    public void setAuthenticatorStatus(Map<String, ClientSessionModel.ExecutionStatus> authenticatorStatus) {
+        this.authenticatorStatus = authenticatorStatus;
+    }
+
+    public String getAuthUserId() {
+        return authUserId;
+    }
+
+    public void setAuthUserId(String authUserId) {
+        this.authUserId = authUserId;
+    }
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext context) {
+    }
+
+}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUsernameLoginFailureEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUsernameLoginFailureEntity.java
index 9d0bb2b..d496571 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUsernameLoginFailureEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoUsernameLoginFailureEntity.java
@@ -1,19 +1,19 @@
-package org.keycloak.models.sessions.mongo.entities;
-
-import org.keycloak.connections.mongo.api.MongoCollection;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.entities.UsernameLoginFailureEntity;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@MongoCollection(collectionName = "userFailures")
-public class MongoUsernameLoginFailureEntity extends UsernameLoginFailureEntity implements MongoIdentifiableEntity {
-
-    @Override
-    public void afterRemove(MongoStoreInvocationContext invocationContext) {
-    }
-
-}
+package org.keycloak.models.sessions.mongo.entities;
+
+import org.keycloak.connections.mongo.api.MongoCollection;
+import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.entities.UsernameLoginFailureEntity;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@MongoCollection(collectionName = "userFailures")
+public class MongoUsernameLoginFailureEntity extends UsernameLoginFailureEntity implements MongoIdentifiableEntity {
+
+    @Override
+    public void afterRemove(MongoStoreInvocationContext invocationContext) {
+    }
+
+}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UsernameLoginFailureAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UsernameLoginFailureAdapter.java
index 251d26e..7cd5249 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UsernameLoginFailureAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UsernameLoginFailureAdapter.java
@@ -1,77 +1,77 @@
-package org.keycloak.models.sessions.mongo;
-
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernameLoginFailureAdapter  extends AbstractMongoAdapter<MongoUsernameLoginFailureEntity> implements UsernameLoginFailureModel {
-    protected MongoUsernameLoginFailureEntity user;
-
-    public UsernameLoginFailureAdapter(MongoStoreInvocationContext invocationContext, MongoUsernameLoginFailureEntity user) {
-        super(invocationContext);
-        this.user = user;
-    }
-
-    @Override
-    protected MongoUsernameLoginFailureEntity getMongoEntity() {
-        return user;
-    }
-
-    @Override
-    public String getUsername() {
-        return user.getUsername();
-    }
-
-    @Override
-    public int getFailedLoginNotBefore() {
-        return user.getFailedLoginNotBefore();
-    }
-
-    @Override
-    public void setFailedLoginNotBefore(int notBefore) {
-        user.setFailedLoginNotBefore(notBefore);
-        updateMongoEntity();
-    }
-
-    @Override
-    public int getNumFailures() {
-        return user.getNumFailures();
-    }
-
-    @Override
-    public void incrementFailures() {
-        user.setNumFailures(getNumFailures() + 1);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void clearFailures() {
-        user.clearFailures();
-        updateMongoEntity();
-    }
-
-    @Override
-    public long getLastFailure() {
-        return user.getLastFailure();
-    }
-
-    @Override
-    public void setLastFailure(long lastFailure) {
-        user.setLastFailure(lastFailure);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getLastIPFailure() {
-        return user.getLastIPFailure();
-    }
-
-    @Override
-    public void setLastIPFailure(String ip) {
-        user.setLastIPFailure(ip);
-        updateMongoEntity();
-    }}
+package org.keycloak.models.sessions.mongo;
+
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernameLoginFailureAdapter  extends AbstractMongoAdapter<MongoUsernameLoginFailureEntity> implements UsernameLoginFailureModel {
+    protected MongoUsernameLoginFailureEntity user;
+
+    public UsernameLoginFailureAdapter(MongoStoreInvocationContext invocationContext, MongoUsernameLoginFailureEntity user) {
+        super(invocationContext);
+        this.user = user;
+    }
+
+    @Override
+    protected MongoUsernameLoginFailureEntity getMongoEntity() {
+        return user;
+    }
+
+    @Override
+    public String getUsername() {
+        return user.getUsername();
+    }
+
+    @Override
+    public int getFailedLoginNotBefore() {
+        return user.getFailedLoginNotBefore();
+    }
+
+    @Override
+    public void setFailedLoginNotBefore(int notBefore) {
+        user.setFailedLoginNotBefore(notBefore);
+        updateMongoEntity();
+    }
+
+    @Override
+    public int getNumFailures() {
+        return user.getNumFailures();
+    }
+
+    @Override
+    public void incrementFailures() {
+        user.setNumFailures(getNumFailures() + 1);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void clearFailures() {
+        user.clearFailures();
+        updateMongoEntity();
+    }
+
+    @Override
+    public long getLastFailure() {
+        return user.getLastFailure();
+    }
+
+    @Override
+    public void setLastFailure(long lastFailure) {
+        user.setLastFailure(lastFailure);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getLastIPFailure() {
+        return user.getLastIPFailure();
+    }
+
+    @Override
+    public void setLastIPFailure(String ip) {
+        user.setLastIPFailure(ip);
+        updateMongoEntity();
+    }}

pom.xml 2816(+1408 -1408)

diff --git a/pom.xml b/pom.xml
index ff601f1..87a1a96 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1,1408 +1,1408 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.jboss</groupId>
-        <artifactId>jboss-parent</artifactId>
-        <version>16</version>
-    </parent>
-
-    <name>Keycloak</name>
-    <description>
-        Keycloak SSO
-    </description>
-    <groupId>org.keycloak</groupId>
-    <artifactId>keycloak-parent</artifactId>
-    <version>1.4.0.Final-SNAPSHOT</version>
-    <packaging>pom</packaging>
-
-    <properties>
-        <apacheds.version>2.0.0-M17</apacheds.version>
-        <apacheds.codec.version>1.0.0-M23</apacheds.codec.version>
-        <org.apache.james.apache-mime4j.version>0.6</org.apache.james.apache-mime4j.version>
-        <base64.version>2.3.8</base64.version>
-        <bouncycastle.crypto.version>1.50</bouncycastle.crypto.version>
-        <jackson.version>1.9.9</jackson.version>
-        <apache.httpcomponents.version>4.3.6</apache.httpcomponents.version>
-        <apache.httpcomponents.httpcore.version>4.3.3</apache.httpcomponents.httpcore.version>
-        <resteasy.version>2.3.7.Final</resteasy.version>
-        <resteasy.latest.version>3.0.9.Final</resteasy.latest.version>
-        <joda-time.version>2.7</joda-time.version>
-        <keycloak.apache.httpcomponents.version>4.2.1</keycloak.apache.httpcomponents.version>
-        <!-- <undertow.version>1.1.0.Final</undertow.version> -->
-        <undertow.version>1.1.1.Final</undertow.version>
-        <picketlink.version>2.7.0.Final</picketlink.version>
-        <mongo.driver.version>2.11.3</mongo.driver.version>
-        <jboss.logging.version>3.1.4.GA</jboss.logging.version>
-        <syslog4j.version>0.9.30</syslog4j.version>
-        <jboss-logging-tools.version>1.2.0.Beta1</jboss-logging-tools.version>
-        <jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version>1.0.4.Final</jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version>
-        <io.netty.version>4.0.26.Final</io.netty.version> 
-        <xnio.netty.netty-xnio-transport.version>0.1.1.Final</xnio.netty.netty-xnio-transport.version>
-        <hibernate.javax.persistence.version>1.0.1.Final</hibernate.javax.persistence.version>
-        <hibernate.entitymanager.version>4.0.1.Final</hibernate.entitymanager.version>
-        <h2.version>1.4.187</h2.version>
-        <mysql.version>5.1.29</mysql.version>
-        <postgresql.version>9.3-1100-jdbc41</postgresql.version>
-        <dom4j.version>1.6.1</dom4j.version>
-        <xml-apis.version>1.4.01</xml-apis.version>
-        <slf4j.version>1.7.7.jbossorg-1</slf4j.version>
-        <wildfly.version>9.0.0.Final</wildfly.version>
-        <wildfly.core.version>1.0.0.Final</wildfly.core.version>
-        <wildfly.build-tools.version>1.0.0.Alpha8</wildfly.build-tools.version>
-
-        <!-- this is EAP 6.4 alpha, publicly available -->
-        <jboss.version>7.5.0.Final-redhat-15</jboss.version>
-
-        <!--jboss.version>7.1.1.Final</jboss.version-->
-
-        <servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
-        <google.zxing.version>2.2</google.zxing.version>
-        <google.client.version>1.14.1-beta</google.client.version>
-        <github.relaxng.version>2011.1</github.relaxng.version>
-        <winzipaes.version>1.0.1</winzipaes.version>
-        <freemarker.version>2.3.20</freemarker.version>
-        <twitter4j.version>3.0.5</twitter4j.version>
-        <selenium.version>2.35.0</selenium.version>
-        <sun.istack.version>2.21</sun.istack.version>
-        <sun.jaxb.version>2.2.11</sun.jaxb.version>
-        <sun.xsom.version>20140925</sun.xsom.version>
-        <javax.mail.version>1.4.5</javax.mail.version>
-        <infinispan.version>6.0.2.Final</infinispan.version>
-        <liquibase.version>3.3.5</liquibase.version>
-        <jetty9.version>9.1.0.v20131115</jetty9.version>
-        <osgi.version>4.2.0</osgi.version>
-        <pax.web.version>3.1.2</pax.web.version>
-        <jmeter.version>2.10</jmeter.version>
-        <junit.version>4.12</junit.version>
-        <hamcrest.version>1.3</hamcrest.version>
-        <log4j.version>1.2.17</log4j.version>
-        <greenmail.version>1.3.1b</greenmail.version>
-        <xmlsec.version>1.5.1</xmlsec.version>
-
-        <enforcer.plugin.version>1.4</enforcer.plugin.version>
-        <jboss.as.plugin.version>7.5.Final</jboss.as.plugin.version>
-        <wildfly.plugin.version>1.0.1.Final</wildfly.plugin.version>
-        <minify.plugin.version>1.7.2</minify.plugin.version>
-        <embedmongo.plugin.version>0.1.12</embedmongo.plugin.version>
-        <jmeter.plugin.version>1.9.0</jmeter.plugin.version>
-        <jmeter.analysis.plugin.version>1.0.4</jmeter.analysis.plugin.version>
-        <osgi.bundle.plugin.version>2.3.7</osgi.bundle.plugin.version>
-    </properties>
-
-    <url>http://keycloak.org</url>
-
-    <licenses>
-        <license>
-            <name>Apache License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
-            <distribution>repo</distribution>
-        </license>
-    </licenses>
-
-    <scm>
-        <connection>scm:git:git://github.com/keycloak/keycloak.git</connection>
-        <developerConnection>scm:git:git@github.com:keycloak/keycloak.git</developerConnection>
-        <url>http://github.com/keycloak/keycloak/tree/master/</url>
-    </scm>
-
-    <distributionManagement>
-        <repository>
-            <id>jboss-releases-repository</id>
-            <name>JBoss Releases Repository</name>
-            <url>https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/</url>
-        </repository>
-    </distributionManagement>
-
-    <issueManagement>
-        <system>JIRA</system>
-        <url>http://jira.jboss.com/jira/browse/KEYCLOAK</url>
-    </issueManagement>
-
-    <developers>
-        <developer>
-            <id>patriot1burke</id>
-            <name>Bill Burke</name>
-            <email>bburke@redhat.co</email>
-            <organization>Red Hat</organization>
-            <roles>
-                <role>project-owner</role>
-            </roles>
-            <timezone>-5</timezone>
-        </developer>
-    </developers>
-
-    <contributors>
-    </contributors>
-
-    <modules>
-        <module>core</module>
-        <module>core-jaxrs</module>
-        <module>connections</module>
-        <module>dependencies</module>
-        <module>events</module>
-        <module>model</module>
-        <module>integration</module>
-        <module>proxy</module>
-        <module>federation</module>
-        <module>services</module>
-        <module>saml</module>
-        <module>broker</module>
-        <module>social</module>
-        <module>forms</module>
-        <module>examples</module>
-        <module>testsuite</module>
-        <module>timer</module>
-        <module>export-import</module>
-        <module>util</module>
-    </modules>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>com.github.relaxng</groupId>
-                <artifactId>relaxngDatatype</artifactId>
-                <version>${github.relaxng.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.istack</groupId>
-                <artifactId>istack-commons-runtime</artifactId>
-                <version>${sun.istack.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.istack</groupId>
-                <artifactId>istack-commons-tools</artifactId>
-                <version>${sun.istack.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.xml.bind.external</groupId>
-                <artifactId>rngom</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.xsom</groupId>
-                <artifactId>xsom</artifactId>
-                <version>${sun.xsom.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jaxb</groupId>
-                <artifactId>jaxb-core</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jaxb</groupId>
-                <artifactId>jaxb-runtime</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jaxb</groupId>
-                <artifactId>jaxb-xjc</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jaxb</groupId>
-                <artifactId>codemodel</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jaxb</groupId>
-                <artifactId>txw2</artifactId>
-                <version>${sun.jaxb.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>joda-time</groupId>
-                <artifactId>joda-time</artifactId>
-                <version>${joda-time.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.bouncycastle</groupId>
-                <artifactId>bcprov-jdk15on</artifactId>
-                <version>${bouncycastle.crypto.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.bouncycastle</groupId>
-                <artifactId>bcpkix-jdk15on</artifactId>
-                <version>${bouncycastle.crypto.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>net.iharder</groupId>
-                <artifactId>base64</artifactId>
-                <version>${base64.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>javax.mail</groupId>
-                <artifactId>mail</artifactId>
-                <version>${javax.mail.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>jaxrs-api</artifactId>
-                <version>${resteasy.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-jaxrs</artifactId>
-                <version>${resteasy.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-multipart-provider</artifactId>
-                <version>${resteasy.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-jackson-provider</artifactId>
-                <version>${resteasy.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-client</artifactId>
-                <version>${resteasy.latest.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-undertow</artifactId>
-                <version>${resteasy.latest.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.spec.javax.xml.bind</groupId>
-                <artifactId>jboss-jaxb-api_2.2_spec</artifactId>
-                <version>${jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.netty</groupId>
-                <artifactId>netty-all</artifactId>
-                <version>${io.netty.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.xnio.netty</groupId>
-                <artifactId>netty-xnio-transport</artifactId>
-                <version>${xnio.netty.netty-xnio-transport.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wildfly-adapter-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.undertow</groupId>
-                <artifactId>undertow-servlet</artifactId>
-                <version>${undertow.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.undertow</groupId>
-                <artifactId>undertow-core</artifactId>
-                <version>${undertow.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-core-asl</artifactId>
-                <version>${jackson.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-mapper-asl</artifactId>
-                <version>${jackson.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-xc</artifactId>
-                <version>${jackson.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-jaxrs</artifactId>
-                <version>${jackson.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.spec.javax.servlet</groupId>
-                <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-                <version>${servlet.api.30.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.picketlink</groupId>
-                <artifactId>picketlink-wildfly-common</artifactId>
-                <version>${picketlink.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.logging</groupId>
-                <artifactId>jboss-logging</artifactId>
-                <version>${jboss.logging.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.syslog4j</groupId>
-                <artifactId>syslog4j</artifactId>
-                <version>${syslog4j.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>log4j</groupId>
-                <artifactId>log4j</artifactId>
-                <version>${log4j.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>junit</groupId>
-                <artifactId>junit</artifactId>
-                <version>${junit.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.hamcrest</groupId>
-                <artifactId>hamcrest-all</artifactId>
-                <version>${hamcrest.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.hibernate.javax.persistence</groupId>
-                <artifactId>hibernate-jpa-2.0-api</artifactId>
-                <version>${hibernate.javax.persistence.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.h2database</groupId>
-                <artifactId>h2</artifactId>
-                <version>${h2.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.hibernate</groupId>
-                <artifactId>hibernate-entitymanager</artifactId>
-                <version>${hibernate.entitymanager.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.freemarker</groupId>
-                <artifactId>freemarker</artifactId>
-                <version>${freemarker.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.santuario</groupId>
-                <artifactId>xmlsec</artifactId>
-                <version>${xmlsec.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>javax.servlet</groupId>
-                        <artifactId>servlet-api</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-dist</artifactId>
-                <version>${wildfly.version}</version>
-                <type>zip</type>
-            </dependency>
-
-            <!-- Twitter -->
-            <dependency>
-                <groupId>org.twitter4j</groupId>
-                <artifactId>twitter4j-core</artifactId>
-                <version>${twitter4j.version}</version>
-            </dependency>
-
-            <!-- QR Code Generator -->
-            <dependency>
-                <groupId>com.google.zxing</groupId>
-                <artifactId>core</artifactId>
-                <version>${google.zxing.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.google.zxing</groupId>
-                <artifactId>javase</artifactId>
-                <version>${google.zxing.version}</version>
-            </dependency>
-
-            <!-- Email Test Servers -->
-            <dependency>
-                <groupId>com.icegreen</groupId>
-                <artifactId>greenmail</artifactId>
-                <version>${greenmail.version}</version>
-                <scope>test</scope>
-            </dependency>
-
-            <!-- Encrypted ZIP -->
-            <dependency>
-                <groupId>de.idyl</groupId>
-                <artifactId>winzipaes</artifactId>
-                <version>${winzipaes.version}</version>
-            </dependency>
-
-            <!-- Apache DS -->
-            <dependency>
-                <groupId>org.apache.directory.server</groupId>
-                <artifactId>apacheds-core-annotations</artifactId>
-                <version>${apacheds.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.directory.server</groupId>
-                <artifactId>apacheds-interceptor-kerberos</artifactId>
-                <version>${apacheds.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.directory.server</groupId>
-                <artifactId>apacheds-server-annotations</artifactId>
-                <version>${apacheds.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.directory.api</groupId>
-                <artifactId>api-ldap-codec-standalone</artifactId>
-                <version>${apacheds.codec.version}</version>
-            </dependency>
-
-            <!-- Selenium -->
-            <dependency>
-                <groupId>org.seleniumhq.selenium</groupId>
-                <artifactId>selenium-java</artifactId>
-                <version>${selenium.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.seleniumhq.selenium</groupId>
-                <artifactId>selenium-chrome-driver</artifactId>
-                <version>${selenium.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.mongodb</groupId>
-                <artifactId>mongo-java-driver</artifactId>
-                <version>${mongo.driver.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.jmeter</groupId>
-                <artifactId>ApacheJMeter_java</artifactId>
-                <version>${jmeter.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>dom4j</groupId>
-                <artifactId>dom4j</artifactId>
-                <version>${dom4j.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>xml-apis</groupId>
-                <artifactId>xml-apis</artifactId>
-                <version>${xml-apis.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <!-- Older 1.5.10 binding required by embedded ApacheDS -->
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-api</artifactId>
-                <version>${slf4j.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-simple</artifactId>
-                <version>${slf4j.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-log4j12</artifactId>
-                <version>${slf4j.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>jcl-over-slf4j</artifactId>
-                <version>${slf4j.version}</version>
-            </dependency>
-            <!-- Needed for picketlink perf test -->
-            <dependency>
-                <groupId>mysql</groupId>
-                <artifactId>mysql-connector-java</artifactId>
-                <version>${mysql.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.httpcomponents</groupId>
-                <artifactId>httpclient</artifactId>
-                <version>${apache.httpcomponents.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.httpcomponents</groupId>
-                <artifactId>httpcore</artifactId>
-                <version>${apache.httpcomponents.httpcore.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.httpcomponents</groupId>
-                <artifactId>httpmime</artifactId>
-                <version>${apache.httpcomponents.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>commons-logging</groupId>
-                        <artifactId>commons-logging</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.james</groupId>
-                <artifactId>apache-mime4j</artifactId>
-                <version>${org.apache.james.apache-mime4j.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>commons-logging</groupId>
-                        <artifactId>commons-logging</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-controller</artifactId>
-                <version>${wildfly.core.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-server</artifactId>
-                <version>${wildfly.core.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-ee</artifactId>
-                <version>${wildfly.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-feature-pack</artifactId>
-                <version>${wildfly.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-web-feature-pack</artifactId>
-                <version>${wildfly.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-subsystem-test</artifactId>
-                <version>${wildfly.core.version}</version>
-                <type>pom</type>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-undertow</artifactId>
-                <version>${wildfly.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-subsystem-test-framework</artifactId>
-                <version>${wildfly.core.version}</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-core-feature-pack</artifactId>
-                <type>pom</type>
-                <version>${wildfly.core.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-core-feature-pack</artifactId>
-                <type>zip</type>
-                <version>${wildfly.core.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly.core</groupId>
-                <artifactId>wildfly-version</artifactId>
-                <version>${wildfly.core.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.wildfly</groupId>
-                <artifactId>wildfly-web-common</artifactId>
-                <version>${wildfly.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.logging</groupId>
-                <artifactId>jboss-logging-processor</artifactId>
-                <version>${jboss-logging-tools.version}</version>
-                <scope>compile</scope>
-            </dependency>
-            <dependency>
-                <groupId>org.infinispan</groupId>
-                <artifactId>infinispan-core</artifactId>
-                <version>${infinispan.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.liquibase</groupId>
-                <artifactId>liquibase-core</artifactId>
-                <version>${liquibase.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.osgi</groupId>
-                <artifactId>org.osgi.core</artifactId>
-                <version>${osgi.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.osgi</groupId>
-                <artifactId>org.osgi.enterprise</artifactId>
-                <version>${osgi.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.ops4j.pax.web</groupId>
-                <artifactId>pax-web-runtime</artifactId>
-                <version>${pax.web.version}</version>
-            </dependency>
-
-            <!-- keycloak -->
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-broker-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-broker-oidc</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-broker-saml</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-file</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-infinispan</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-jpa</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-jpa-liquibase</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-mongo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-http-client</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-connections-mongo-update</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-core-jaxrs</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-email</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-jboss-logging</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-jpa</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-mongo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-events-syslog</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-export-import-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-export-import-dir</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-export-import-single-file</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-export-import-zip</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-kerberos-federation</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-ldap-federation</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-account-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-account-freemarker</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-dependencies-server-min</artifactId>
-                <version>${project.version}</version>
-                <type>pom</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-dependencies-server-all</artifactId>
-                <version>${project.version}</version>
-                <type>pom</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-forms-common-freemarker</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-forms-common-themes</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-email-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-email-freemarker</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-adapter-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-admin-client</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-installed-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jaxrs-oauth-client</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jboss-adapter-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jetty-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jetty81-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jetty91-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-jetty92-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-server-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf8-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf9-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf9-server-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>            
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-subsystem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-js-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-osgi-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-servlet-oauth-client</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-spring-boot-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-tomcat-core-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-tomcat6-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-tomcat7-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-tomcat8-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-undertow-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wildfly-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wildfly-extensions</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-login-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-login-freemarker</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-file</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-invalidation-cache-model</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-jpa</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-mongo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-sessions-infinispan</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-sessions-jpa</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-sessions-mem</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-model-sessions-mongo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>launcher</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-proxy-server</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-saml-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-saml-protocol</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-services</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-facebook</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-github</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-google</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-linkedin</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-stackoverflow</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-social-twitter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-timer-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-timer-basic</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-server-modules-eap6</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-modules</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf8-modules</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf9-modules</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf9-adapter-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-server-overlay</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-server-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-util-embedded-ldap</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-docs-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-examples-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-wf8-adapter-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-adapter-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-eap6-adapter-dist</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-server-feature-pack</artifactId>
-                <version>${project.version}</version>
-                <type>zip</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-testsuite-integration</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-testsuite-integration</artifactId>
-                <version>${project.version}</version>
-                <type>test-jar</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-testsuite-tools</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-testsuite-tools</artifactId>
-                <version>${project.version}</version>
-                <classifier>classes</classifier>
-            </dependency>
-
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>federation-properties-example</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak.example.demo</groupId>
-                <artifactId>cxf-jaxws-example</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak.example.demo</groupId>
-                <artifactId>customer-portal-example</artifactId>
-                <version>${project.version}</version>
-                <type>war</type>
-            </dependency>
-            <dependency>
-                <groupId>org.keycloak.example.demo</groupId>
-                <artifactId>product-portal-example</artifactId>
-                <version>${project.version}</version>
-                <type>war</type>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <repositories>
-        <!-- for org.jboss.web:jbossweb -->
-        <repository>
-            <id>jboss</id>
-            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
-        </repository>
-    </repositories>
-
-    <build>
-        <pluginManagement>
-            <plugins>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-surefire-plugin</artifactId>
-                    <configuration>
-                        <forkMode>once</forkMode>
-                        <argLine>-Xms512m -Xmx1024m -XX:MaxPermSize=512m</argLine>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-install-plugin</artifactId>
-                    <configuration>
-                        <createChecksum>true</createChecksum>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>com.lazerycode.jmeter</groupId>
-                    <artifactId>jmeter-maven-plugin</artifactId>
-                    <version>${jmeter.plugin.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>com.lazerycode.jmeter</groupId>
-                    <artifactId>jmeter-analysis-maven-plugin</artifactId>
-                    <version>${jmeter.analysis.plugin.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                    <artifactId>embedmongo-maven-plugin</artifactId>
-                    <version>${embedmongo.plugin.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.jboss.as.plugins</groupId>
-                    <artifactId>jboss-as-maven-plugin</artifactId>
-                    <version>${jboss.as.plugin.version}</version>
-                    <configuration>
-                        <skip>true</skip>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>org.wildfly.plugins</groupId>
-                    <artifactId>wildfly-maven-plugin</artifactId>
-                    <version>${wildfly.plugin.version}</version>
-                    <configuration>
-                        <skip>true</skip>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>com.samaxes.maven</groupId>
-                    <artifactId>minify-maven-plugin</artifactId>
-                    <version>${minify.plugin.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.liquibase</groupId>
-                    <artifactId>liquibase-maven-plugin</artifactId>
-                    <version>${liquibase.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.wildfly.build</groupId>
-                    <artifactId>wildfly-feature-pack-build-maven-plugin</artifactId>
-                    <version>${wildfly.build-tools.version}</version>
-                </plugin> 
-                <plugin>
-                    <groupId>org.wildfly.build</groupId>
-                    <artifactId>wildfly-server-provisioning-maven-plugin</artifactId>
-                    <version>${wildfly.build-tools.version}</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-enforcer-plugin</artifactId>
-                    <version>${enforcer.plugin.version}</version>
-                    <executions>
-                        <execution>
-                            <id>enforce-maven</id>
-                            <goals>
-                                <goal>enforce</goal>
-                            </goals>
-                            <configuration>
-                                <rules>
-                                    <requireMavenVersion>
-                                        <version>3.1.1</version>
-                                    </requireMavenVersion>
-                                </rules>    
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.felix</groupId>
-                    <artifactId>maven-bundle-plugin</artifactId>
-                    <version>${osgi.bundle.plugin.version}</version>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-    </build>
-
-    <profiles>
-        <!-- Configure the JBoss Early Access Maven repository -->
-        <profile>
-            <id>jboss-earlyaccess-repository</id>
-            <activation>
-                <property>
-                    <name>!no-jboss-ea-repo</name>
-                </property>
-            </activation>
-            <repositories>
-                <repository>
-                    <id>jboss-earlyaccess-repository</id>
-                    <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
-                    <releases>
-                        <enabled>true</enabled>
-                    </releases>
-                    <snapshots>
-                        <enabled>false</enabled>
-                    </snapshots>
-                </repository>
-            </repositories>
-            <pluginRepositories>
-                <pluginRepository>
-                    <id>jboss-earlyaccess-plugin-repository</id>
-                    <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
-                    <releases>
-                        <enabled>true</enabled>
-                    </releases>
-                    <snapshots>
-                        <enabled>false</enabled>
-                    </snapshots>
-                </pluginRepository>
-            </pluginRepositories>
-        </profile>
-        <profile>
-            <id>distribution</id>
-            <modules>
-                <module>distribution</module>
-                <module>testsuite/integration-arquillian</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>jboss-release</id>
-            <modules>
-                <module>docbook</module>
-                <module>distribution</module>
-                <module>testsuite/integration-arquillian</module>
-            </modules>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-javadoc-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>aggregate</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>aggregate</goal>
-                                </goals>
-                                <configuration>
-                                    <minmemory>128m</minmemory>
-                                    <maxmemory>1024m</maxmemory>
-                                    <aggregate>true</aggregate>
-                                    <excludePackageNames>
-                                        se.unlogic.*:com.restfully.*:org.jboss.resteasy.examples.*:org.jboss.resteasy.tests.*
-                                    </excludePackageNames>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>          
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>doclint-java8-disable</id>
-            <activation>
-                <jdk>[1.8,)</jdk>
-            </activation>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-javadoc-plugin</artifactId>
-                        <configuration>
-                            <additionalparam>-Xdoclint:none</additionalparam>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.jboss</groupId>
+        <artifactId>jboss-parent</artifactId>
+        <version>16</version>
+    </parent>
+
+    <name>Keycloak</name>
+    <description>
+        Keycloak SSO
+    </description>
+    <groupId>org.keycloak</groupId>
+    <artifactId>keycloak-parent</artifactId>
+    <version>1.4.0.Final-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <apacheds.version>2.0.0-M17</apacheds.version>
+        <apacheds.codec.version>1.0.0-M23</apacheds.codec.version>
+        <org.apache.james.apache-mime4j.version>0.6</org.apache.james.apache-mime4j.version>
+        <base64.version>2.3.8</base64.version>
+        <bouncycastle.crypto.version>1.50</bouncycastle.crypto.version>
+        <jackson.version>1.9.9</jackson.version>
+        <apache.httpcomponents.version>4.3.6</apache.httpcomponents.version>
+        <apache.httpcomponents.httpcore.version>4.3.3</apache.httpcomponents.httpcore.version>
+        <resteasy.version>2.3.7.Final</resteasy.version>
+        <resteasy.latest.version>3.0.9.Final</resteasy.latest.version>
+        <joda-time.version>2.7</joda-time.version>
+        <keycloak.apache.httpcomponents.version>4.2.1</keycloak.apache.httpcomponents.version>
+        <!-- <undertow.version>1.1.0.Final</undertow.version> -->
+        <undertow.version>1.1.1.Final</undertow.version>
+        <picketlink.version>2.7.0.Final</picketlink.version>
+        <mongo.driver.version>2.11.3</mongo.driver.version>
+        <jboss.logging.version>3.1.4.GA</jboss.logging.version>
+        <syslog4j.version>0.9.30</syslog4j.version>
+        <jboss-logging-tools.version>1.2.0.Beta1</jboss-logging-tools.version>
+        <jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version>1.0.4.Final</jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version>
+        <io.netty.version>4.0.26.Final</io.netty.version> 
+        <xnio.netty.netty-xnio-transport.version>0.1.1.Final</xnio.netty.netty-xnio-transport.version>
+        <hibernate.javax.persistence.version>1.0.1.Final</hibernate.javax.persistence.version>
+        <hibernate.entitymanager.version>4.0.1.Final</hibernate.entitymanager.version>
+        <h2.version>1.4.187</h2.version>
+        <mysql.version>5.1.29</mysql.version>
+        <postgresql.version>9.3-1100-jdbc41</postgresql.version>
+        <dom4j.version>1.6.1</dom4j.version>
+        <xml-apis.version>1.4.01</xml-apis.version>
+        <slf4j.version>1.7.7.jbossorg-1</slf4j.version>
+        <wildfly.version>9.0.0.Final</wildfly.version>
+        <wildfly.core.version>1.0.0.Final</wildfly.core.version>
+        <wildfly.build-tools.version>1.0.0.Alpha8</wildfly.build-tools.version>
+
+        <!-- this is EAP 6.4 alpha, publicly available -->
+        <jboss.version>7.5.0.Final-redhat-15</jboss.version>
+
+        <!--jboss.version>7.1.1.Final</jboss.version-->
+
+        <servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
+        <google.zxing.version>2.2</google.zxing.version>
+        <google.client.version>1.14.1-beta</google.client.version>
+        <github.relaxng.version>2011.1</github.relaxng.version>
+        <winzipaes.version>1.0.1</winzipaes.version>
+        <freemarker.version>2.3.20</freemarker.version>
+        <twitter4j.version>3.0.5</twitter4j.version>
+        <selenium.version>2.35.0</selenium.version>
+        <sun.istack.version>2.21</sun.istack.version>
+        <sun.jaxb.version>2.2.11</sun.jaxb.version>
+        <sun.xsom.version>20140925</sun.xsom.version>
+        <javax.mail.version>1.4.5</javax.mail.version>
+        <infinispan.version>6.0.2.Final</infinispan.version>
+        <liquibase.version>3.3.5</liquibase.version>
+        <jetty9.version>9.1.0.v20131115</jetty9.version>
+        <osgi.version>4.2.0</osgi.version>
+        <pax.web.version>3.1.2</pax.web.version>
+        <jmeter.version>2.10</jmeter.version>
+        <junit.version>4.12</junit.version>
+        <hamcrest.version>1.3</hamcrest.version>
+        <log4j.version>1.2.17</log4j.version>
+        <greenmail.version>1.3.1b</greenmail.version>
+        <xmlsec.version>1.5.1</xmlsec.version>
+
+        <enforcer.plugin.version>1.4</enforcer.plugin.version>
+        <jboss.as.plugin.version>7.5.Final</jboss.as.plugin.version>
+        <wildfly.plugin.version>1.0.1.Final</wildfly.plugin.version>
+        <minify.plugin.version>1.7.2</minify.plugin.version>
+        <embedmongo.plugin.version>0.1.12</embedmongo.plugin.version>
+        <jmeter.plugin.version>1.9.0</jmeter.plugin.version>
+        <jmeter.analysis.plugin.version>1.0.4</jmeter.analysis.plugin.version>
+        <osgi.bundle.plugin.version>2.3.7</osgi.bundle.plugin.version>
+    </properties>
+
+    <url>http://keycloak.org</url>
+
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <scm>
+        <connection>scm:git:git://github.com/keycloak/keycloak.git</connection>
+        <developerConnection>scm:git:git@github.com:keycloak/keycloak.git</developerConnection>
+        <url>http://github.com/keycloak/keycloak/tree/master/</url>
+    </scm>
+
+    <distributionManagement>
+        <repository>
+            <id>jboss-releases-repository</id>
+            <name>JBoss Releases Repository</name>
+            <url>https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/</url>
+        </repository>
+    </distributionManagement>
+
+    <issueManagement>
+        <system>JIRA</system>
+        <url>http://jira.jboss.com/jira/browse/KEYCLOAK</url>
+    </issueManagement>
+
+    <developers>
+        <developer>
+            <id>patriot1burke</id>
+            <name>Bill Burke</name>
+            <email>bburke@redhat.co</email>
+            <organization>Red Hat</organization>
+            <roles>
+                <role>project-owner</role>
+            </roles>
+            <timezone>-5</timezone>
+        </developer>
+    </developers>
+
+    <contributors>
+    </contributors>
+
+    <modules>
+        <module>core</module>
+        <module>core-jaxrs</module>
+        <module>connections</module>
+        <module>dependencies</module>
+        <module>events</module>
+        <module>model</module>
+        <module>integration</module>
+        <module>proxy</module>
+        <module>federation</module>
+        <module>services</module>
+        <module>saml</module>
+        <module>broker</module>
+        <module>social</module>
+        <module>forms</module>
+        <module>examples</module>
+        <module>testsuite</module>
+        <module>timer</module>
+        <module>export-import</module>
+        <module>util</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.github.relaxng</groupId>
+                <artifactId>relaxngDatatype</artifactId>
+                <version>${github.relaxng.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-runtime</artifactId>
+                <version>${sun.istack.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-tools</artifactId>
+                <version>${sun.istack.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind.external</groupId>
+                <artifactId>rngom</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xsom</groupId>
+                <artifactId>xsom</artifactId>
+                <version>${sun.xsom.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>jaxb-core</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>jaxb-runtime</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>jaxb-xjc</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>codemodel</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>txw2</artifactId>
+                <version>${sun.jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>joda-time</groupId>
+                <artifactId>joda-time</artifactId>
+                <version>${joda-time.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.bouncycastle</groupId>
+                <artifactId>bcprov-jdk15on</artifactId>
+                <version>${bouncycastle.crypto.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.bouncycastle</groupId>
+                <artifactId>bcpkix-jdk15on</artifactId>
+                <version>${bouncycastle.crypto.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>net.iharder</groupId>
+                <artifactId>base64</artifactId>
+                <version>${base64.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.mail</groupId>
+                <artifactId>mail</artifactId>
+                <version>${javax.mail.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>jaxrs-api</artifactId>
+                <version>${resteasy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-jaxrs</artifactId>
+                <version>${resteasy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-multipart-provider</artifactId>
+                <version>${resteasy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-jackson-provider</artifactId>
+                <version>${resteasy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-client</artifactId>
+                <version>${resteasy.latest.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-undertow</artifactId>
+                <version>${resteasy.latest.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.spec.javax.xml.bind</groupId>
+                <artifactId>jboss-jaxb-api_2.2_spec</artifactId>
+                <version>${jboss.spec.javax.xml.bind.jboss-jaxb-api_2.2_spec.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-all</artifactId>
+                <version>${io.netty.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.xnio.netty</groupId>
+                <artifactId>netty-xnio-transport</artifactId>
+                <version>${xnio.netty.netty-xnio-transport.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wildfly-adapter-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.undertow</groupId>
+                <artifactId>undertow-servlet</artifactId>
+                <version>${undertow.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.undertow</groupId>
+                <artifactId>undertow-core</artifactId>
+                <version>${undertow.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.jackson</groupId>
+                <artifactId>jackson-core-asl</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.jackson</groupId>
+                <artifactId>jackson-mapper-asl</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.jackson</groupId>
+                <artifactId>jackson-xc</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.jackson</groupId>
+                <artifactId>jackson-jaxrs</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.spec.javax.servlet</groupId>
+                <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+                <version>${servlet.api.30.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.picketlink</groupId>
+                <artifactId>picketlink-wildfly-common</artifactId>
+                <version>${picketlink.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.logging</groupId>
+                <artifactId>jboss-logging</artifactId>
+                <version>${jboss.logging.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.syslog4j</groupId>
+                <artifactId>syslog4j</artifactId>
+                <version>${syslog4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>log4j</groupId>
+                <artifactId>log4j</artifactId>
+                <version>${log4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>junit</groupId>
+                <artifactId>junit</artifactId>
+                <version>${junit.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-all</artifactId>
+                <version>${hamcrest.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hibernate.javax.persistence</groupId>
+                <artifactId>hibernate-jpa-2.0-api</artifactId>
+                <version>${hibernate.javax.persistence.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.h2database</groupId>
+                <artifactId>h2</artifactId>
+                <version>${h2.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.hibernate</groupId>
+                <artifactId>hibernate-entitymanager</artifactId>
+                <version>${hibernate.entitymanager.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.freemarker</groupId>
+                <artifactId>freemarker</artifactId>
+                <version>${freemarker.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.santuario</groupId>
+                <artifactId>xmlsec</artifactId>
+                <version>${xmlsec.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>javax.servlet</groupId>
+                        <artifactId>servlet-api</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-dist</artifactId>
+                <version>${wildfly.version}</version>
+                <type>zip</type>
+            </dependency>
+
+            <!-- Twitter -->
+            <dependency>
+                <groupId>org.twitter4j</groupId>
+                <artifactId>twitter4j-core</artifactId>
+                <version>${twitter4j.version}</version>
+            </dependency>
+
+            <!-- QR Code Generator -->
+            <dependency>
+                <groupId>com.google.zxing</groupId>
+                <artifactId>core</artifactId>
+                <version>${google.zxing.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.zxing</groupId>
+                <artifactId>javase</artifactId>
+                <version>${google.zxing.version}</version>
+            </dependency>
+
+            <!-- Email Test Servers -->
+            <dependency>
+                <groupId>com.icegreen</groupId>
+                <artifactId>greenmail</artifactId>
+                <version>${greenmail.version}</version>
+                <scope>test</scope>
+            </dependency>
+
+            <!-- Encrypted ZIP -->
+            <dependency>
+                <groupId>de.idyl</groupId>
+                <artifactId>winzipaes</artifactId>
+                <version>${winzipaes.version}</version>
+            </dependency>
+
+            <!-- Apache DS -->
+            <dependency>
+                <groupId>org.apache.directory.server</groupId>
+                <artifactId>apacheds-core-annotations</artifactId>
+                <version>${apacheds.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.directory.server</groupId>
+                <artifactId>apacheds-interceptor-kerberos</artifactId>
+                <version>${apacheds.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.directory.server</groupId>
+                <artifactId>apacheds-server-annotations</artifactId>
+                <version>${apacheds.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.directory.api</groupId>
+                <artifactId>api-ldap-codec-standalone</artifactId>
+                <version>${apacheds.codec.version}</version>
+            </dependency>
+
+            <!-- Selenium -->
+            <dependency>
+                <groupId>org.seleniumhq.selenium</groupId>
+                <artifactId>selenium-java</artifactId>
+                <version>${selenium.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.seleniumhq.selenium</groupId>
+                <artifactId>selenium-chrome-driver</artifactId>
+                <version>${selenium.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.mongodb</groupId>
+                <artifactId>mongo-java-driver</artifactId>
+                <version>${mongo.driver.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.jmeter</groupId>
+                <artifactId>ApacheJMeter_java</artifactId>
+                <version>${jmeter.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>dom4j</groupId>
+                <artifactId>dom4j</artifactId>
+                <version>${dom4j.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>${xml-apis.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <!-- Older 1.5.10 binding required by embedded ApacheDS -->
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-simple</artifactId>
+                <version>${slf4j.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-log4j12</artifactId>
+                <version>${slf4j.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>jcl-over-slf4j</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <!-- Needed for picketlink perf test -->
+            <dependency>
+                <groupId>mysql</groupId>
+                <artifactId>mysql-connector-java</artifactId>
+                <version>${mysql.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>${apache.httpcomponents.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpcore</artifactId>
+                <version>${apache.httpcomponents.httpcore.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpmime</artifactId>
+                <version>${apache.httpcomponents.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>commons-logging</groupId>
+                        <artifactId>commons-logging</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.james</groupId>
+                <artifactId>apache-mime4j</artifactId>
+                <version>${org.apache.james.apache-mime4j.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>commons-logging</groupId>
+                        <artifactId>commons-logging</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-controller</artifactId>
+                <version>${wildfly.core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-server</artifactId>
+                <version>${wildfly.core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-ee</artifactId>
+                <version>${wildfly.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-feature-pack</artifactId>
+                <version>${wildfly.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-web-feature-pack</artifactId>
+                <version>${wildfly.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-subsystem-test</artifactId>
+                <version>${wildfly.core.version}</version>
+                <type>pom</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-undertow</artifactId>
+                <version>${wildfly.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-subsystem-test-framework</artifactId>
+                <version>${wildfly.core.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-core-feature-pack</artifactId>
+                <type>pom</type>
+                <version>${wildfly.core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-core-feature-pack</artifactId>
+                <type>zip</type>
+                <version>${wildfly.core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly.core</groupId>
+                <artifactId>wildfly-version</artifactId>
+                <version>${wildfly.core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.wildfly</groupId>
+                <artifactId>wildfly-web-common</artifactId>
+                <version>${wildfly.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.logging</groupId>
+                <artifactId>jboss-logging-processor</artifactId>
+                <version>${jboss-logging-tools.version}</version>
+                <scope>compile</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.infinispan</groupId>
+                <artifactId>infinispan-core</artifactId>
+                <version>${infinispan.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.liquibase</groupId>
+                <artifactId>liquibase-core</artifactId>
+                <version>${liquibase.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.osgi</groupId>
+                <artifactId>org.osgi.core</artifactId>
+                <version>${osgi.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.osgi</groupId>
+                <artifactId>org.osgi.enterprise</artifactId>
+                <version>${osgi.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.ops4j.pax.web</groupId>
+                <artifactId>pax-web-runtime</artifactId>
+                <version>${pax.web.version}</version>
+            </dependency>
+
+            <!-- keycloak -->
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-broker-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-broker-oidc</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-broker-saml</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-file</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-infinispan</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-jpa</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-jpa-liquibase</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-mongo</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-http-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-connections-mongo-update</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-core-jaxrs</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-email</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-jboss-logging</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-jpa</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-mongo</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-events-syslog</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-export-import-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-export-import-dir</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-export-import-single-file</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-export-import-zip</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-kerberos-federation</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-ldap-federation</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-account-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-account-freemarker</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-dependencies-server-min</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-dependencies-server-all</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-forms-common-freemarker</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-forms-common-themes</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-email-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-email-freemarker</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-adapter-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-admin-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-installed-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jaxrs-oauth-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jboss-adapter-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jetty-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jetty81-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jetty91-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-jetty92-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-server-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf8-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf9-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf9-server-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>            
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-subsystem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-js-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-osgi-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-servlet-oauth-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-spring-boot-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-tomcat-core-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-tomcat6-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-tomcat7-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-tomcat8-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-undertow-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wildfly-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wildfly-extensions</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-login-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-login-freemarker</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-file</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-invalidation-cache-infinispan</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-invalidation-cache-model</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-jpa</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-mongo</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-sessions-infinispan</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-sessions-jpa</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-sessions-mem</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-model-sessions-mongo</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>launcher</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-proxy-server</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-saml-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-saml-protocol</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-services</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-facebook</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-github</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-google</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-linkedin</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-stackoverflow</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-twitter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-timer-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-timer-basic</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-server-modules-eap6</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-modules</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf8-modules</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf9-modules</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf9-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-server-overlay</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-server-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-util-embedded-ldap</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-docs-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-examples-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-wf8-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-eap6-adapter-dist</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-server-feature-pack</artifactId>
+                <version>${project.version}</version>
+                <type>zip</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-testsuite-integration</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-testsuite-integration</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-testsuite-tools</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-testsuite-tools</artifactId>
+                <version>${project.version}</version>
+                <classifier>classes</classifier>
+            </dependency>
+
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>federation-properties-example</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak.example.demo</groupId>
+                <artifactId>cxf-jaxws-example</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak.example.demo</groupId>
+                <artifactId>customer-portal-example</artifactId>
+                <version>${project.version}</version>
+                <type>war</type>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak.example.demo</groupId>
+                <artifactId>product-portal-example</artifactId>
+                <version>${project.version}</version>
+                <type>war</type>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <repositories>
+        <!-- for org.jboss.web:jbossweb -->
+        <repository>
+            <id>jboss</id>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <configuration>
+                        <forkMode>once</forkMode>
+                        <argLine>-Xms512m -Xmx1024m -XX:MaxPermSize=512m</argLine>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <configuration>
+                        <createChecksum>true</createChecksum>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>com.lazerycode.jmeter</groupId>
+                    <artifactId>jmeter-maven-plugin</artifactId>
+                    <version>${jmeter.plugin.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>com.lazerycode.jmeter</groupId>
+                    <artifactId>jmeter-analysis-maven-plugin</artifactId>
+                    <version>${jmeter.analysis.plugin.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                    <artifactId>embedmongo-maven-plugin</artifactId>
+                    <version>${embedmongo.plugin.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.jboss.as.plugins</groupId>
+                    <artifactId>jboss-as-maven-plugin</artifactId>
+                    <version>${jboss.as.plugin.version}</version>
+                    <configuration>
+                        <skip>true</skip>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.wildfly.plugins</groupId>
+                    <artifactId>wildfly-maven-plugin</artifactId>
+                    <version>${wildfly.plugin.version}</version>
+                    <configuration>
+                        <skip>true</skip>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>com.samaxes.maven</groupId>
+                    <artifactId>minify-maven-plugin</artifactId>
+                    <version>${minify.plugin.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.liquibase</groupId>
+                    <artifactId>liquibase-maven-plugin</artifactId>
+                    <version>${liquibase.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.wildfly.build</groupId>
+                    <artifactId>wildfly-feature-pack-build-maven-plugin</artifactId>
+                    <version>${wildfly.build-tools.version}</version>
+                </plugin> 
+                <plugin>
+                    <groupId>org.wildfly.build</groupId>
+                    <artifactId>wildfly-server-provisioning-maven-plugin</artifactId>
+                    <version>${wildfly.build-tools.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-enforcer-plugin</artifactId>
+                    <version>${enforcer.plugin.version}</version>
+                    <executions>
+                        <execution>
+                            <id>enforce-maven</id>
+                            <goals>
+                                <goal>enforce</goal>
+                            </goals>
+                            <configuration>
+                                <rules>
+                                    <requireMavenVersion>
+                                        <version>3.1.1</version>
+                                    </requireMavenVersion>
+                                </rules>    
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>maven-bundle-plugin</artifactId>
+                    <version>${osgi.bundle.plugin.version}</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <profiles>
+        <!-- Configure the JBoss Early Access Maven repository -->
+        <profile>
+            <id>jboss-earlyaccess-repository</id>
+            <activation>
+                <property>
+                    <name>!no-jboss-ea-repo</name>
+                </property>
+            </activation>
+            <repositories>
+                <repository>
+                    <id>jboss-earlyaccess-repository</id>
+                    <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
+                    <releases>
+                        <enabled>true</enabled>
+                    </releases>
+                    <snapshots>
+                        <enabled>false</enabled>
+                    </snapshots>
+                </repository>
+            </repositories>
+            <pluginRepositories>
+                <pluginRepository>
+                    <id>jboss-earlyaccess-plugin-repository</id>
+                    <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
+                    <releases>
+                        <enabled>true</enabled>
+                    </releases>
+                    <snapshots>
+                        <enabled>false</enabled>
+                    </snapshots>
+                </pluginRepository>
+            </pluginRepositories>
+        </profile>
+        <profile>
+            <id>distribution</id>
+            <modules>
+                <module>distribution</module>
+                <module>testsuite/integration-arquillian</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>jboss-release</id>
+            <modules>
+                <module>docbook</module>
+                <module>distribution</module>
+                <module>testsuite/integration-arquillian</module>
+            </modules>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>aggregate</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>aggregate</goal>
+                                </goals>
+                                <configuration>
+                                    <minmemory>128m</minmemory>
+                                    <maxmemory>1024m</maxmemory>
+                                    <aggregate>true</aggregate>
+                                    <excludePackageNames>
+                                        se.unlogic.*:com.restfully.*:org.jboss.resteasy.examples.*:org.jboss.resteasy.tests.*
+                                    </excludePackageNames>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>          
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>doclint-java8-disable</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <configuration>
+                            <additionalparam>-Xdoclint:none</additionalparam>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/proxy/launcher/pom.xml b/proxy/launcher/pom.xml
index b1ed5aa..d03b94b 100755
--- a/proxy/launcher/pom.xml
+++ b/proxy/launcher/pom.xml
@@ -1,43 +1,43 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>launcher</artifactId>
-    <name>Keycloak Launcher</name>
-    <description/>
-
-    <dependencies>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifest>
-                            <mainClass>org.keycloak.Launcher</mainClass>
-                        </manifest>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>launcher</artifactId>
+    <name>Keycloak Launcher</name>
+    <description/>
+
+    <dependencies>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>org.keycloak.Launcher</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/proxy/launcher/src/main/java/org/keycloak/Launcher.java b/proxy/launcher/src/main/java/org/keycloak/Launcher.java
index 56eab1e..7437820 100755
--- a/proxy/launcher/src/main/java/org/keycloak/Launcher.java
+++ b/proxy/launcher/src/main/java/org/keycloak/Launcher.java
@@ -1,66 +1,66 @@
-package org.keycloak;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class Launcher {
-
-    public static File getHome() {
-        String launcherPath = Launcher.class.getName().replace('.', '/') + ".class";
-        URL jarfile = Launcher.class.getClassLoader().getResource(launcherPath);
-        if (jarfile != null) {
-            Matcher m = Pattern.compile("jar:(file:.*)!/" + launcherPath).matcher(jarfile.toString());
-            if (m.matches()) {
-                try {
-                    File jarPath = new File(new URI(m.group(1)));
-                    File libPath = jarPath.getParentFile().getParentFile();
-                    System.out.println("Home directory: " + libPath.toString());
-                    if (!libPath.exists()) {
-                        System.exit(1);
-
-                    }
-                    return libPath;
-                } catch (URISyntaxException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        } else {
-            System.err.println("jar file null: " + launcherPath);
-        }
-        return null;
-    }
-
-    public static void main(String[] args) throws Exception {
-
-        File home = getHome();
-        File lib = new File(home, "lib");
-        if (!lib.exists()) {
-            System.err.println("Could not find lib directory: " + lib.toString());
-            System.exit(1);
-        }
-        List<URL> jars = new ArrayList<URL>();
-        for (File file : lib.listFiles()) {
-            jars.add(file.toURI().toURL());
-        }
-        URL[] urls = jars.toArray(new URL[jars.size()]);
-        URLClassLoader loader = new URLClassLoader(urls, Launcher.class.getClassLoader());
-
-        Class mainClass = loader.loadClass("org.keycloak.proxy.Main");
-        Method mainMethod = null;
-        for (Method m : mainClass.getMethods()) if (m.getName().equals("main")) { mainMethod = m; break; }
-        Object obj = args;
-        mainMethod.invoke(null, obj);
-    }
-}
+package org.keycloak;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Launcher {
+
+    public static File getHome() {
+        String launcherPath = Launcher.class.getName().replace('.', '/') + ".class";
+        URL jarfile = Launcher.class.getClassLoader().getResource(launcherPath);
+        if (jarfile != null) {
+            Matcher m = Pattern.compile("jar:(file:.*)!/" + launcherPath).matcher(jarfile.toString());
+            if (m.matches()) {
+                try {
+                    File jarPath = new File(new URI(m.group(1)));
+                    File libPath = jarPath.getParentFile().getParentFile();
+                    System.out.println("Home directory: " + libPath.toString());
+                    if (!libPath.exists()) {
+                        System.exit(1);
+
+                    }
+                    return libPath;
+                } catch (URISyntaxException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        } else {
+            System.err.println("jar file null: " + launcherPath);
+        }
+        return null;
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        File home = getHome();
+        File lib = new File(home, "lib");
+        if (!lib.exists()) {
+            System.err.println("Could not find lib directory: " + lib.toString());
+            System.exit(1);
+        }
+        List<URL> jars = new ArrayList<URL>();
+        for (File file : lib.listFiles()) {
+            jars.add(file.toURI().toURL());
+        }
+        URL[] urls = jars.toArray(new URL[jars.size()]);
+        URLClassLoader loader = new URLClassLoader(urls, Launcher.class.getClassLoader());
+
+        Class mainClass = loader.loadClass("org.keycloak.proxy.Main");
+        Method mainMethod = null;
+        for (Method m : mainClass.getMethods()) if (m.getName().equals("main")) { mainMethod = m; break; }
+        Object obj = args;
+        mainMethod.invoke(null, obj);
+    }
+}

proxy/pom.xml 62(+31 -31)

diff --git a/proxy/pom.xml b/proxy/pom.xml
index f8d5e7d..c9dee1f 100755
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -1,31 +1,31 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <name>Model Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-proxy-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>launcher</module>
-        <module>proxy-server</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <name>Model Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-proxy-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>launcher</module>
+        <module>proxy-server</module>
+    </modules>
+</project>
diff --git a/proxy/proxy-server/pom.xml b/proxy/proxy-server/pom.xml
index efd01b0..a218ee9 100755
--- a/proxy/proxy-server/pom.xml
+++ b/proxy/proxy-server/pom.xml
@@ -1,80 +1,80 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-proxy-server</artifactId>
-    <name>Keycloak Proxy Server</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-undertow-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-adapter-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>net.iharder</groupId>
-            <artifactId>base64</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-proxy-server</artifactId>
+    <name>Keycloak Proxy Server</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-undertow-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.iharder</groupId>
+            <artifactId>base64</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
index 365feea..5740563 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java
@@ -1,107 +1,107 @@
-package org.keycloak.proxy;
-
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.util.HttpString;
-import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
-import org.keycloak.representations.IDToken;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ConstraintAuthorizationHandler implements HttpHandler {
-
-    public static final String KEYCLOAK_SUBJECT = "KEYCLOAK_SUBJECT";
-    public static final String KEYCLOAK_USERNAME = "KEYCLOAK_USERNAME";
-    public static final String KEYCLOAK_EMAIL = "KEYCLOAK_EMAIL";
-    public static final String KEYCLOAK_NAME = "KEYCLOAK_NAME";
-    public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN";
-    private final Map<String, HttpString> httpHeaderNames;
-
-    protected HttpHandler next;
-    protected String errorPage;
-    protected boolean sendAccessToken;
-
-    public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map<String, String> headerNames) {
-        this.next = next;
-        this.errorPage = errorPage;
-        this.sendAccessToken = sendAccessToken;
-
-        this.httpHeaderNames = new HashMap<>();
-        this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-subject", KEYCLOAK_SUBJECT)));
-        this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-username", KEYCLOAK_USERNAME)));
-        this.httpHeaderNames.put(KEYCLOAK_EMAIL, new HttpString(getOrDefault(headerNames, "keycloak-email", KEYCLOAK_EMAIL)));
-        this.httpHeaderNames.put(KEYCLOAK_NAME, new HttpString(getOrDefault(headerNames, "keycloak-name", KEYCLOAK_NAME)));
-        this.httpHeaderNames.put(KEYCLOAK_ACCESS_TOKEN, new HttpString(getOrDefault(headerNames, "keycloak-access-token", KEYCLOAK_ACCESS_TOKEN)));
-    }
-
-    private String getOrDefault(Map<String, String> map, String key, String defaultValue) {
-        return map.containsKey(key) ? map.get(key) : defaultValue;
-    }
-
-    @Override
-    public void handleRequest(HttpServerExchange exchange) throws Exception {
-
-        KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
-
-        SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY);
-        if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) {
-            authenticatedRequest(account, exchange);
-            return;
-        }
-
-        if (match != null) {
-            if(SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED.equals(match.getEmptyRoleSemantic())) {
-                authenticatedRequest(account, exchange);
-                return;
-            } else {
-                for (String role : match.getRequiredRoles()) {
-                    if (account.getRoles().contains(role)) {
-                        authenticatedRequest(account, exchange);
-                        return;
-                    }
-                }
-            }
-        }
-
-        if (errorPage != null) {
-            exchange.setRequestPath(errorPage);
-            exchange.setRelativePath(errorPage);
-            exchange.setResolvedPath(errorPage);
-            next.handleRequest(exchange);
-            return;
-
-        }
-        exchange.setResponseCode(403);
-        exchange.endExchange();
-
-    }
-
-    public void authenticatedRequest(KeycloakUndertowAccount account, HttpServerExchange exchange) throws Exception {
-        if (account != null) {
-            IDToken idToken = account.getKeycloakSecurityContext().getToken();
-            if (idToken == null) return;
-            if (idToken.getSubject() != null) {
-                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_SUBJECT), idToken.getSubject());
-            }
-
-            if (idToken.getPreferredUsername() != null) {
-                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_USERNAME), idToken.getPreferredUsername());
-            }
-            if (idToken.getEmail() != null) {
-                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_EMAIL), idToken.getEmail());
-            }
-            if (idToken.getName() != null) {
-                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_NAME), idToken.getName());
-            }
-            if (sendAccessToken) {
-                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_ACCESS_TOKEN), account.getKeycloakSecurityContext().getTokenString());
-            }
-        }
-        next.handleRequest(exchange);
-    }
-}
+package org.keycloak.proxy;
+
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.HttpString;
+import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
+import org.keycloak.representations.IDToken;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ConstraintAuthorizationHandler implements HttpHandler {
+
+    public static final String KEYCLOAK_SUBJECT = "KEYCLOAK_SUBJECT";
+    public static final String KEYCLOAK_USERNAME = "KEYCLOAK_USERNAME";
+    public static final String KEYCLOAK_EMAIL = "KEYCLOAK_EMAIL";
+    public static final String KEYCLOAK_NAME = "KEYCLOAK_NAME";
+    public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN";
+    private final Map<String, HttpString> httpHeaderNames;
+
+    protected HttpHandler next;
+    protected String errorPage;
+    protected boolean sendAccessToken;
+
+    public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map<String, String> headerNames) {
+        this.next = next;
+        this.errorPage = errorPage;
+        this.sendAccessToken = sendAccessToken;
+
+        this.httpHeaderNames = new HashMap<>();
+        this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-subject", KEYCLOAK_SUBJECT)));
+        this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-username", KEYCLOAK_USERNAME)));
+        this.httpHeaderNames.put(KEYCLOAK_EMAIL, new HttpString(getOrDefault(headerNames, "keycloak-email", KEYCLOAK_EMAIL)));
+        this.httpHeaderNames.put(KEYCLOAK_NAME, new HttpString(getOrDefault(headerNames, "keycloak-name", KEYCLOAK_NAME)));
+        this.httpHeaderNames.put(KEYCLOAK_ACCESS_TOKEN, new HttpString(getOrDefault(headerNames, "keycloak-access-token", KEYCLOAK_ACCESS_TOKEN)));
+    }
+
+    private String getOrDefault(Map<String, String> map, String key, String defaultValue) {
+        return map.containsKey(key) ? map.get(key) : defaultValue;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+
+        KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
+
+        SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY);
+        if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) {
+            authenticatedRequest(account, exchange);
+            return;
+        }
+
+        if (match != null) {
+            if(SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED.equals(match.getEmptyRoleSemantic())) {
+                authenticatedRequest(account, exchange);
+                return;
+            } else {
+                for (String role : match.getRequiredRoles()) {
+                    if (account.getRoles().contains(role)) {
+                        authenticatedRequest(account, exchange);
+                        return;
+                    }
+                }
+            }
+        }
+
+        if (errorPage != null) {
+            exchange.setRequestPath(errorPage);
+            exchange.setRelativePath(errorPage);
+            exchange.setResolvedPath(errorPage);
+            next.handleRequest(exchange);
+            return;
+
+        }
+        exchange.setResponseCode(403);
+        exchange.endExchange();
+
+    }
+
+    public void authenticatedRequest(KeycloakUndertowAccount account, HttpServerExchange exchange) throws Exception {
+        if (account != null) {
+            IDToken idToken = account.getKeycloakSecurityContext().getToken();
+            if (idToken == null) return;
+            if (idToken.getSubject() != null) {
+                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_SUBJECT), idToken.getSubject());
+            }
+
+            if (idToken.getPreferredUsername() != null) {
+                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_USERNAME), idToken.getPreferredUsername());
+            }
+            if (idToken.getEmail() != null) {
+                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_EMAIL), idToken.getEmail());
+            }
+            if (idToken.getName() != null) {
+                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_NAME), idToken.getName());
+            }
+            if (sendAccessToken) {
+                exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_ACCESS_TOKEN), account.getKeycloakSecurityContext().getTokenString());
+            }
+        }
+        next.handleRequest(exchange);
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java
index 31a187c..d359d97 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintMatcherHandler.java
@@ -1,89 +1,89 @@
-package org.keycloak.proxy;
-
-import io.undertow.security.api.AuthenticationMechanism;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.util.AttachmentKey;
-import org.jboss.logging.Logger;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ConstraintMatcherHandler implements HttpHandler {
-    protected static Logger log = Logger.getLogger(ConstraintMatcherHandler.class);
-    public static final AttachmentKey<SingleConstraintMatch> CONSTRAINT_KEY = AttachmentKey.create(SingleConstraintMatch.class);
-    protected SecurityPathMatches matcher;
-    protected HttpHandler securedHandler;
-    protected HttpHandler unsecuredHandler;
-    protected String errorPage;
-
-    public ConstraintMatcherHandler(SecurityPathMatches matcher, HttpHandler securedHandler, HttpHandler unsecuredHandler, String errorPage) {
-        this.matcher = matcher;
-        this.securedHandler = securedHandler;
-        this.unsecuredHandler = unsecuredHandler;
-        this.errorPage = errorPage;
-    }
-
-    @Override
-    public void handleRequest(HttpServerExchange exchange) throws Exception {
-        log.debugv("ConstraintMatcherHandler: {0}", exchange.getRelativePath());
-        SingleConstraintMatch match = matcher.getSecurityInfo(exchange.getRelativePath(), exchange.getRequestMethod().toString());
-        if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT)) {
-            unsecuredHandler.handleRequest(exchange);
-            return;
-        }
-
-        if (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.DENY) {
-            if (errorPage != null) {
-                exchange.setRequestPath(errorPage);
-                exchange.setRelativePath(errorPage);
-                exchange.setResolvedPath(errorPage);
-                unsecuredHandler.handleRequest(exchange);
-            } else {
-                exchange.setResponseCode(403);
-                exchange.endExchange();
-            }
-            return;
-        }
-
-        if (match.getRequiredRoles().isEmpty()
-                && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED) {
-
-            boolean successfulAuthenticatedMethodFound = isSuccessfulAuthenticatedMethodFound(exchange);
-
-            if(successfulAuthenticatedMethodFound) {
-                //in case of authenticated we go for injecting headers
-                exchange.putAttachment(CONSTRAINT_KEY, match);
-                securedHandler.handleRequest(exchange);
-                return;
-            } else {
-                //in case of not authenticated we just show the resource
-                unsecuredHandler.handleRequest(exchange);
-                return;
-            }
-        }
-
-        log.debug("found constraint");
-        exchange.getSecurityContext().setAuthenticationRequired();
-        exchange.putAttachment(CONSTRAINT_KEY, match);
-        securedHandler.handleRequest(exchange);
-
-    }
-
-    private boolean isSuccessfulAuthenticatedMethodFound(HttpServerExchange exchange) {
-        boolean successfulAuthenticatedMethodFound = false;
-        List<AuthenticationMechanism> authenticationMechanisms = exchange.getSecurityContext().getAuthenticationMechanisms();
-
-        for (AuthenticationMechanism authenticationMechanism : authenticationMechanisms) {
-            AuthenticationMechanism.AuthenticationMechanismOutcome authenticationMechanismOutcome =
-                    authenticationMechanism.authenticate(exchange, exchange.getSecurityContext());
-            if(authenticationMechanismOutcome.equals(AuthenticationMechanism.AuthenticationMechanismOutcome.AUTHENTICATED)) {
-                successfulAuthenticatedMethodFound = true;
-            }
-        }
-        return successfulAuthenticatedMethodFound;
-    }
-}
+package org.keycloak.proxy;
+
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.AttachmentKey;
+import org.jboss.logging.Logger;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ConstraintMatcherHandler implements HttpHandler {
+    protected static Logger log = Logger.getLogger(ConstraintMatcherHandler.class);
+    public static final AttachmentKey<SingleConstraintMatch> CONSTRAINT_KEY = AttachmentKey.create(SingleConstraintMatch.class);
+    protected SecurityPathMatches matcher;
+    protected HttpHandler securedHandler;
+    protected HttpHandler unsecuredHandler;
+    protected String errorPage;
+
+    public ConstraintMatcherHandler(SecurityPathMatches matcher, HttpHandler securedHandler, HttpHandler unsecuredHandler, String errorPage) {
+        this.matcher = matcher;
+        this.securedHandler = securedHandler;
+        this.unsecuredHandler = unsecuredHandler;
+        this.errorPage = errorPage;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        log.debugv("ConstraintMatcherHandler: {0}", exchange.getRelativePath());
+        SingleConstraintMatch match = matcher.getSecurityInfo(exchange.getRelativePath(), exchange.getRequestMethod().toString());
+        if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT)) {
+            unsecuredHandler.handleRequest(exchange);
+            return;
+        }
+
+        if (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.DENY) {
+            if (errorPage != null) {
+                exchange.setRequestPath(errorPage);
+                exchange.setRelativePath(errorPage);
+                exchange.setResolvedPath(errorPage);
+                unsecuredHandler.handleRequest(exchange);
+            } else {
+                exchange.setResponseCode(403);
+                exchange.endExchange();
+            }
+            return;
+        }
+
+        if (match.getRequiredRoles().isEmpty()
+                && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED) {
+
+            boolean successfulAuthenticatedMethodFound = isSuccessfulAuthenticatedMethodFound(exchange);
+
+            if(successfulAuthenticatedMethodFound) {
+                //in case of authenticated we go for injecting headers
+                exchange.putAttachment(CONSTRAINT_KEY, match);
+                securedHandler.handleRequest(exchange);
+                return;
+            } else {
+                //in case of not authenticated we just show the resource
+                unsecuredHandler.handleRequest(exchange);
+                return;
+            }
+        }
+
+        log.debug("found constraint");
+        exchange.getSecurityContext().setAuthenticationRequired();
+        exchange.putAttachment(CONSTRAINT_KEY, match);
+        securedHandler.handleRequest(exchange);
+
+    }
+
+    private boolean isSuccessfulAuthenticatedMethodFound(HttpServerExchange exchange) {
+        boolean successfulAuthenticatedMethodFound = false;
+        List<AuthenticationMechanism> authenticationMechanisms = exchange.getSecurityContext().getAuthenticationMechanisms();
+
+        for (AuthenticationMechanism authenticationMechanism : authenticationMechanisms) {
+            AuthenticationMechanism.AuthenticationMechanismOutcome authenticationMechanismOutcome =
+                    authenticationMechanism.authenticate(exchange, exchange.getSecurityContext());
+            if(authenticationMechanismOutcome.equals(AuthenticationMechanism.AuthenticationMechanismOutcome.AUTHENTICATED)) {
+                successfulAuthenticatedMethodFound = true;
+            }
+        }
+        return successfulAuthenticatedMethodFound;
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java
index 69dbbe0..1121c67 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/Main.java
@@ -1,28 +1,28 @@
-package org.keycloak.proxy;
-
-import io.undertow.Undertow;
-
-import java.io.File;
-import java.io.FileInputStream;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class Main {
-
-    public static void main(String[] args) throws Exception {
-        String jsonConfig = "proxy.json";
-        if (args.length > 0) jsonConfig = args[0];
-        File file = new File(jsonConfig);
-        if (!file.exists()) {
-            System.err.println("No proxy config argument and could not find default file proxy.json");
-            System.exit(1);
-            return;
-        }
-        FileInputStream fis = new FileInputStream(file);
-        Undertow proxyServer = ProxyServerBuilder.build(fis);
-        proxyServer.start();
-
-    }
-}
+package org.keycloak.proxy;
+
+import io.undertow.Undertow;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+        String jsonConfig = "proxy.json";
+        if (args.length > 0) jsonConfig = args[0];
+        File file = new File(jsonConfig);
+        if (!file.exists()) {
+            System.err.println("No proxy config argument and could not find default file proxy.json");
+            System.exit(1);
+            return;
+        }
+        FileInputStream fis = new FileInputStream(file);
+        Undertow proxyServer = ProxyServerBuilder.build(fis);
+        proxyServer.start();
+
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java
index 7246693..c082bb9 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyAuthenticationCallHandler.java
@@ -1,35 +1,35 @@
-package org.keycloak.proxy;
-
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProxyAuthenticationCallHandler implements HttpHandler {
-
-    private final HttpHandler next;
-
-    public ProxyAuthenticationCallHandler(final HttpHandler next) {
-        this.next = next;
-    }
-
-    /**
-     * Only allow the request through if successfully authenticated or if authentication is not required.
-     *
-     * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
-     */
-    @Override
-    public void handleRequest(final HttpServerExchange exchange) throws Exception {
-        SecurityContext context = exchange.getSecurityContext();
-        if (context.authenticate()) {
-            if(!exchange.isComplete()) {
-                next.handleRequest(exchange);
-            }
-        } else {
-            exchange.endExchange();
-        }
-    }
-}
+package org.keycloak.proxy;
+
+import io.undertow.security.api.SecurityContext;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProxyAuthenticationCallHandler implements HttpHandler {
+
+    private final HttpHandler next;
+
+    public ProxyAuthenticationCallHandler(final HttpHandler next) {
+        this.next = next;
+    }
+
+    /**
+     * Only allow the request through if successfully authenticated or if authentication is not required.
+     *
+     * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
+     */
+    @Override
+    public void handleRequest(final HttpServerExchange exchange) throws Exception {
+        SecurityContext context = exchange.getSecurityContext();
+        if (context.authenticate()) {
+            if(!exchange.isComplete()) {
+                next.handleRequest(exchange);
+            }
+        } else {
+            exchange.endExchange();
+        }
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java
index b211fde..e5010ed 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java
@@ -1,289 +1,289 @@
-package org.keycloak.proxy;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-
-import java.util.*;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProxyConfig {
-    @JsonProperty("bind-address")
-    protected String bindAddress = "localhost";
-    @JsonProperty("http-port")
-    protected Integer httpPort;
-    @JsonProperty("https-port")
-    protected Integer httpsPort;
-    @JsonProperty("keystore")
-    protected String keystore;
-    @JsonProperty("keystore-password")
-    protected String keystorePassword;
-    @JsonProperty("key-password")
-    protected String keyPassword;
-    @JsonProperty("buffer-size")
-    protected Integer bufferSize;
-    @JsonProperty("buffers-per-region")
-    protected Integer buffersPerRegion;
-    @JsonProperty("io-threads")
-    protected Integer ioThreads;
-    @JsonProperty("worker-threads")
-    protected Integer workerThreads;
-    @JsonProperty("direct-buffers")
-    protected Boolean directBuffers;
-    @JsonProperty("target-url")
-    protected String targetUrl;
-    @JsonProperty("send-access-token")
-    protected boolean sendAccessToken;
-    @JsonProperty("applications")
-    protected List<Application> applications = new LinkedList<Application>();
-    @JsonProperty("header-names")
-    private Map<String,String> headerNames = new HashMap<>();
-
-    public String getBindAddress() {
-        return bindAddress;
-    }
-
-    public void setBindAddress(String bindAddress) {
-        this.bindAddress = bindAddress;
-    }
-
-    public Integer getHttpPort() {
-        return httpPort;
-    }
-
-    public void setHttpPort(Integer httpPort) {
-        this.httpPort = httpPort;
-    }
-
-    public Integer getHttpsPort() {
-        return httpsPort;
-    }
-
-    public void setHttpsPort(Integer httpsPort) {
-        this.httpsPort = httpsPort;
-    }
-
-    public String getKeystore() {
-        return keystore;
-    }
-
-    public void setKeystore(String keystore) {
-        this.keystore = keystore;
-    }
-
-    public String getKeystorePassword() {
-        return keystorePassword;
-    }
-
-    public void setKeystorePassword(String keystorePassword) {
-        this.keystorePassword = keystorePassword;
-    }
-
-    public String getKeyPassword() {
-        return keyPassword;
-    }
-
-    public void setKeyPassword(String keyPassword) {
-        this.keyPassword = keyPassword;
-    }
-
-    public Integer getBufferSize() {
-        return bufferSize;
-    }
-
-    public void setBufferSize(Integer bufferSize) {
-        this.bufferSize = bufferSize;
-    }
-
-    public Integer getBuffersPerRegion() {
-        return buffersPerRegion;
-    }
-
-    public void setBuffersPerRegion(Integer buffersPerRegion) {
-        this.buffersPerRegion = buffersPerRegion;
-    }
-
-    public Integer getIoThreads() {
-        return ioThreads;
-    }
-
-    public void setIoThreads(Integer ioThreads) {
-        this.ioThreads = ioThreads;
-    }
-
-    public Integer getWorkerThreads() {
-        return workerThreads;
-    }
-
-    public void setWorkerThreads(Integer workerThreads) {
-        this.workerThreads = workerThreads;
-    }
-
-    public Boolean getDirectBuffers() {
-        return directBuffers;
-    }
-
-    public void setDirectBuffers(Boolean directBuffers) {
-        this.directBuffers = directBuffers;
-    }
-
-    public String getTargetUrl() {
-        return targetUrl;
-    }
-
-    public void setTargetUrl(String targetUrl) {
-        this.targetUrl = targetUrl;
-    }
-
-    public List<Application> getApplications() {
-        return applications;
-    }
-
-    public void setApplications(List<Application> applications) {
-        this.applications = applications;
-    }
-
-    public boolean isSendAccessToken() {
-        return sendAccessToken;
-    }
-
-    public void setSendAccessToken(boolean sendAccessToken) {
-        this.sendAccessToken = sendAccessToken;
-    }
-
-    public void setHeaderNames(Map<String, String> headerNames) {
-        this.headerNames = headerNames;
-    }
-
-    public Map<String, String> getHeaderNames() {
-        return headerNames;
-    }
-
-    public static class Application {
-        @JsonProperty("base-path")
-        protected String basePath;
-        @JsonProperty("adapter-config")
-        protected AdapterConfig adapterConfig;
-        @JsonProperty("error-page")
-        protected String errorPage;
-        @JsonProperty("constraints")
-        protected List<Constraint> constraints = new LinkedList<Constraint>();
-
-        public String getBasePath() {
-            return basePath;
-        }
-
-        public void setBasePath(String basePath) {
-            this.basePath = basePath;
-        }
-
-        public AdapterConfig getAdapterConfig() {
-            return adapterConfig;
-        }
-
-        public void setAdapterConfig(AdapterConfig adapterConfig) {
-            this.adapterConfig = adapterConfig;
-        }
-
-        public String getErrorPage() {
-            return errorPage;
-        }
-
-        public void setErrorPage(String errorPage) {
-            this.errorPage = errorPage;
-        }
-
-        public List<Constraint> getConstraints() {
-            return constraints;
-        }
-
-        public void setConstraints(List<Constraint> constraints) {
-            this.constraints = constraints;
-        }
-    }
-
-    public static class Constraint {
-        @JsonProperty("pattern")
-        protected String pattern;
-        @JsonProperty("roles-allowed")
-        protected Set<String> rolesAllowed = new HashSet<String>();
-        @JsonProperty("methods")
-        protected Set<String> methods = new HashSet<String>();
-        @JsonProperty("excluded-methods")
-        protected Set<String> excludedMethods = new HashSet<String>();
-        @JsonProperty("deny")
-        protected boolean deny;
-        @JsonProperty("permit")
-        protected boolean permit;
-        @JsonProperty("authenticate")
-        protected boolean authenticate;
-        @JsonProperty("permit-and-inject")
-        protected boolean permitAndInject;
-
-        public String getPattern() {
-            return pattern;
-        }
-
-        public void setPattern(String pattern) {
-            this.pattern = pattern;
-        }
-
-        public Set<String> getRolesAllowed() {
-            return rolesAllowed;
-        }
-
-        public void setRolesAllowed(Set<String> rolesAllowed) {
-            this.rolesAllowed = rolesAllowed;
-        }
-
-        public boolean isDeny() {
-            return deny;
-        }
-
-        public void setDeny(boolean deny) {
-            this.deny = deny;
-        }
-
-        public boolean isPermit() {
-            return permit;
-        }
-
-        public void setPermit(boolean permit) {
-            this.permit = permit;
-        }
-
-        public boolean isAuthenticate() {
-            return authenticate;
-        }
-
-        public void setAuthenticate(boolean authenticate) {
-            this.authenticate = authenticate;
-        }
-
-        public boolean isPermitAndInject() {
-            return permitAndInject;
-        }
-
-        public void setPermitAndInject(boolean permitAndInject) {
-            this.permitAndInject = permitAndInject;
-        }
-
-        public Set<String> getMethods() {
-            return methods;
-        }
-
-        public void setMethods(Set<String> methods) {
-            this.methods = methods;
-        }
-
-        public Set<String> getExcludedMethods() {
-            return excludedMethods;
-        }
-
-        public void setExcludedMethods(Set<String> excludedMethods) {
-            this.excludedMethods = excludedMethods;
-        }
-    }
-}
+package org.keycloak.proxy;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+
+import java.util.*;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProxyConfig {
+    @JsonProperty("bind-address")
+    protected String bindAddress = "localhost";
+    @JsonProperty("http-port")
+    protected Integer httpPort;
+    @JsonProperty("https-port")
+    protected Integer httpsPort;
+    @JsonProperty("keystore")
+    protected String keystore;
+    @JsonProperty("keystore-password")
+    protected String keystorePassword;
+    @JsonProperty("key-password")
+    protected String keyPassword;
+    @JsonProperty("buffer-size")
+    protected Integer bufferSize;
+    @JsonProperty("buffers-per-region")
+    protected Integer buffersPerRegion;
+    @JsonProperty("io-threads")
+    protected Integer ioThreads;
+    @JsonProperty("worker-threads")
+    protected Integer workerThreads;
+    @JsonProperty("direct-buffers")
+    protected Boolean directBuffers;
+    @JsonProperty("target-url")
+    protected String targetUrl;
+    @JsonProperty("send-access-token")
+    protected boolean sendAccessToken;
+    @JsonProperty("applications")
+    protected List<Application> applications = new LinkedList<Application>();
+    @JsonProperty("header-names")
+    private Map<String,String> headerNames = new HashMap<>();
+
+    public String getBindAddress() {
+        return bindAddress;
+    }
+
+    public void setBindAddress(String bindAddress) {
+        this.bindAddress = bindAddress;
+    }
+
+    public Integer getHttpPort() {
+        return httpPort;
+    }
+
+    public void setHttpPort(Integer httpPort) {
+        this.httpPort = httpPort;
+    }
+
+    public Integer getHttpsPort() {
+        return httpsPort;
+    }
+
+    public void setHttpsPort(Integer httpsPort) {
+        this.httpsPort = httpsPort;
+    }
+
+    public String getKeystore() {
+        return keystore;
+    }
+
+    public void setKeystore(String keystore) {
+        this.keystore = keystore;
+    }
+
+    public String getKeystorePassword() {
+        return keystorePassword;
+    }
+
+    public void setKeystorePassword(String keystorePassword) {
+        this.keystorePassword = keystorePassword;
+    }
+
+    public String getKeyPassword() {
+        return keyPassword;
+    }
+
+    public void setKeyPassword(String keyPassword) {
+        this.keyPassword = keyPassword;
+    }
+
+    public Integer getBufferSize() {
+        return bufferSize;
+    }
+
+    public void setBufferSize(Integer bufferSize) {
+        this.bufferSize = bufferSize;
+    }
+
+    public Integer getBuffersPerRegion() {
+        return buffersPerRegion;
+    }
+
+    public void setBuffersPerRegion(Integer buffersPerRegion) {
+        this.buffersPerRegion = buffersPerRegion;
+    }
+
+    public Integer getIoThreads() {
+        return ioThreads;
+    }
+
+    public void setIoThreads(Integer ioThreads) {
+        this.ioThreads = ioThreads;
+    }
+
+    public Integer getWorkerThreads() {
+        return workerThreads;
+    }
+
+    public void setWorkerThreads(Integer workerThreads) {
+        this.workerThreads = workerThreads;
+    }
+
+    public Boolean getDirectBuffers() {
+        return directBuffers;
+    }
+
+    public void setDirectBuffers(Boolean directBuffers) {
+        this.directBuffers = directBuffers;
+    }
+
+    public String getTargetUrl() {
+        return targetUrl;
+    }
+
+    public void setTargetUrl(String targetUrl) {
+        this.targetUrl = targetUrl;
+    }
+
+    public List<Application> getApplications() {
+        return applications;
+    }
+
+    public void setApplications(List<Application> applications) {
+        this.applications = applications;
+    }
+
+    public boolean isSendAccessToken() {
+        return sendAccessToken;
+    }
+
+    public void setSendAccessToken(boolean sendAccessToken) {
+        this.sendAccessToken = sendAccessToken;
+    }
+
+    public void setHeaderNames(Map<String, String> headerNames) {
+        this.headerNames = headerNames;
+    }
+
+    public Map<String, String> getHeaderNames() {
+        return headerNames;
+    }
+
+    public static class Application {
+        @JsonProperty("base-path")
+        protected String basePath;
+        @JsonProperty("adapter-config")
+        protected AdapterConfig adapterConfig;
+        @JsonProperty("error-page")
+        protected String errorPage;
+        @JsonProperty("constraints")
+        protected List<Constraint> constraints = new LinkedList<Constraint>();
+
+        public String getBasePath() {
+            return basePath;
+        }
+
+        public void setBasePath(String basePath) {
+            this.basePath = basePath;
+        }
+
+        public AdapterConfig getAdapterConfig() {
+            return adapterConfig;
+        }
+
+        public void setAdapterConfig(AdapterConfig adapterConfig) {
+            this.adapterConfig = adapterConfig;
+        }
+
+        public String getErrorPage() {
+            return errorPage;
+        }
+
+        public void setErrorPage(String errorPage) {
+            this.errorPage = errorPage;
+        }
+
+        public List<Constraint> getConstraints() {
+            return constraints;
+        }
+
+        public void setConstraints(List<Constraint> constraints) {
+            this.constraints = constraints;
+        }
+    }
+
+    public static class Constraint {
+        @JsonProperty("pattern")
+        protected String pattern;
+        @JsonProperty("roles-allowed")
+        protected Set<String> rolesAllowed = new HashSet<String>();
+        @JsonProperty("methods")
+        protected Set<String> methods = new HashSet<String>();
+        @JsonProperty("excluded-methods")
+        protected Set<String> excludedMethods = new HashSet<String>();
+        @JsonProperty("deny")
+        protected boolean deny;
+        @JsonProperty("permit")
+        protected boolean permit;
+        @JsonProperty("authenticate")
+        protected boolean authenticate;
+        @JsonProperty("permit-and-inject")
+        protected boolean permitAndInject;
+
+        public String getPattern() {
+            return pattern;
+        }
+
+        public void setPattern(String pattern) {
+            this.pattern = pattern;
+        }
+
+        public Set<String> getRolesAllowed() {
+            return rolesAllowed;
+        }
+
+        public void setRolesAllowed(Set<String> rolesAllowed) {
+            this.rolesAllowed = rolesAllowed;
+        }
+
+        public boolean isDeny() {
+            return deny;
+        }
+
+        public void setDeny(boolean deny) {
+            this.deny = deny;
+        }
+
+        public boolean isPermit() {
+            return permit;
+        }
+
+        public void setPermit(boolean permit) {
+            this.permit = permit;
+        }
+
+        public boolean isAuthenticate() {
+            return authenticate;
+        }
+
+        public void setAuthenticate(boolean authenticate) {
+            this.authenticate = authenticate;
+        }
+
+        public boolean isPermitAndInject() {
+            return permitAndInject;
+        }
+
+        public void setPermitAndInject(boolean permitAndInject) {
+            this.permitAndInject = permitAndInject;
+        }
+
+        public Set<String> getMethods() {
+            return methods;
+        }
+
+        public void setMethods(Set<String> methods) {
+            this.methods = methods;
+        }
+
+        public Set<String> getExcludedMethods() {
+            return excludedMethods;
+        }
+
+        public void setExcludedMethods(Set<String> excludedMethods) {
+            this.excludedMethods = excludedMethods;
+        }
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
index d689e59..b4ad9b9 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
@@ -1,462 +1,462 @@
-package org.keycloak.proxy;
-
-import io.undertow.Undertow;
-import io.undertow.security.api.AuthenticationMechanism;
-import io.undertow.security.api.AuthenticationMode;
-import io.undertow.security.handlers.AuthenticationMechanismsHandler;
-import io.undertow.security.handlers.SecurityInitialHandler;
-import io.undertow.security.idm.Account;
-import io.undertow.security.idm.Credential;
-import io.undertow.security.idm.IdentityManager;
-import io.undertow.security.impl.CachedAuthenticatedSessionMechanism;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.handlers.PathHandler;
-import io.undertow.server.handlers.ResponseCodeHandler;
-import io.undertow.server.handlers.proxy.ProxyHandler;
-import io.undertow.server.handlers.proxy.SimpleProxyClientProvider;
-import io.undertow.server.session.InMemorySessionManager;
-import io.undertow.server.session.SessionAttachmentHandler;
-import io.undertow.server.session.SessionCookieConfig;
-import io.undertow.server.session.SessionManager;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-import org.jboss.logging.Logger;
-import org.keycloak.adapters.AdapterDeploymentContext;
-import org.keycloak.util.FindFile;
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationManagement;
-import org.keycloak.adapters.undertow.UndertowAuthenticatedActionsHandler;
-import org.keycloak.adapters.undertow.UndertowAuthenticationMechanism;
-import org.keycloak.adapters.undertow.UndertowPreAuthActionsHandler;
-import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.CertificateUtils;
-import org.keycloak.util.SystemPropertiesJsonParserFactory;
-import org.xnio.Option;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.*;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProxyServerBuilder {
-    protected static Logger log = Logger.getLogger(ProxyServerBuilder.class);
-    public static final HttpHandler NOT_FOUND = new HttpHandler() {
-        @Override
-        public void handleRequest(HttpServerExchange exchange) throws Exception {
-            exchange.setResponseCode(404);
-            exchange.endExchange();
-        }
-    };
-
-    protected Undertow.Builder builder = Undertow.builder();
-
-    protected PathHandler root = new PathHandler(NOT_FOUND);
-    protected HttpHandler proxyHandler;
-    protected boolean sendAccessToken;
-
-    protected Map<String, String> headerNameConfig;
-
-    public ProxyServerBuilder target(String uri) {
-        SimpleProxyClientProvider provider = null;
-        try {
-            provider = new SimpleProxyClientProvider(new URI(uri));
-        } catch (URISyntaxException e) {
-            throw new RuntimeException(e);
-        }
-        final HttpHandler handler = new ProxyHandler(provider, 30000, ResponseCodeHandler.HANDLE_404);
-        proxyHandler = new HttpHandler() {
-            @Override
-            public void handleRequest(HttpServerExchange exchange) throws Exception {
-                exchange.setRelativePath(exchange.getRequestPath()); // need this otherwise proxy forwards to chopped off path
-                handler.handleRequest(exchange);
-            }
-        };
-        return this;
-    }
-
-    public ProxyServerBuilder sendAccessToken(boolean flag) {
-        this.sendAccessToken = flag;
-        return this;
-    }
-
-    public ProxyServerBuilder headerNameConfig(Map<String, String> headerNameConfig) {
-        this.headerNameConfig = headerNameConfig;
-        return this;
-    }
-
-    public ApplicationBuilder application(AdapterConfig config) {
-        return new ApplicationBuilder(config);
-    }
-
-    public class ApplicationBuilder {
-        protected NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
-        protected UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
-        protected AdapterDeploymentContext deploymentContext;
-        protected KeycloakDeployment deployment;
-        SessionManager sessionManager = new InMemorySessionManager(
-                "SESSION_MANAGER");
-        protected String base;
-        protected SecurityPathMatches.Builder constraintBuilder = new SecurityPathMatches.Builder();
-        protected SecurityPathMatches matches;
-        protected String errorPage;
-
-        public ApplicationBuilder base(String base) {
-            this.base = base;
-            return this;
-        }
-
-        public ApplicationBuilder errorPage(String errorPage) {
-            if (errorPage != null && errorPage.startsWith("/")) {
-                errorPage = errorPage.substring(1);
-            }
-            this.errorPage = errorPage;
-            return this;
-        }
-
-        public ApplicationBuilder(AdapterConfig config) {
-            this.deployment = KeycloakDeploymentBuilder.build(config);
-            this.deploymentContext = new AdapterDeploymentContext(deployment);
-        }
-
-        public ProxyServerBuilder add() {
-            matches = constraintBuilder.build();
-            HttpHandler handler = sessionHandling(addSecurity(proxyHandler));
-            root.addPrefixPath(base, handler);
-            return ProxyServerBuilder.this;
-        }
-
-        public ConstraintBuilder constraint(String pattern) {
-            log.debugv("add constraint: {0}", pattern);
-            return new ConstraintBuilder(pattern);
-        }
-
-        public class ConstraintBuilder {
-            protected String pattern;
-            protected Set<String> rolesAllowed = new HashSet<String>();
-            protected Set<String> methods = new HashSet<String>();
-            protected Set<String> excludedMethods = new HashSet<String>();
-            protected SecurityInfo.EmptyRoleSemantic semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE;
-
-            public ConstraintBuilder(String pattern) {
-                this.pattern = pattern;
-
-            }
-
-            public ConstraintBuilder deny() {
-                semantic = SecurityInfo.EmptyRoleSemantic.DENY;
-                return this;
-            }
-            public ConstraintBuilder permit() {
-                semantic = SecurityInfo.EmptyRoleSemantic.PERMIT;
-                return this;
-            }
-            public ConstraintBuilder authenticate() {
-                semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE;
-                return this;
-            }
-
-            public ConstraintBuilder injectIfAuthenticated() {
-                semantic = SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED;
-                return this;
-            }
-
-            public ConstraintBuilder excludedMethods(Set<String> excludedMethods) {
-                this.excludedMethods = excludedMethods;
-                return this;
-            }
-
-            public ConstraintBuilder methods(Set<String> methods) {
-                this.methods = methods;
-                return this;
-            }
-
-            public ConstraintBuilder method(String method) {
-                methods.add(method);
-                return this;
-            }
-
-            public ConstraintBuilder excludeMethod(String method) {
-                excludedMethods.add(method);
-                return this;
-            }
-
-
-            public ConstraintBuilder roles(String... roles) {
-                for (String role : roles) role(role);
-                return this;
-            }
-            public ConstraintBuilder roles(Set<String> roles) {
-                for (String role : roles) role(role);
-                return this;
-            }
-
-            public ConstraintBuilder role(String role) {
-                rolesAllowed.add(role);
-                return this;
-            }
-
-            public ApplicationBuilder add() {
-                constraintBuilder.addSecurityConstraint(rolesAllowed, semantic, pattern, methods, excludedMethods);
-                return ApplicationBuilder.this;
-            }
-
-
-        }
-
-        private HttpHandler addSecurity(final HttpHandler toWrap) {
-            HttpHandler handler = toWrap;
-            handler = new UndertowAuthenticatedActionsHandler(deploymentContext, toWrap);
-            if (errorPage != null) {
-                if (base.endsWith("/")) {
-                    errorPage = base + errorPage;
-                } else {
-                    errorPage = base + "/" + errorPage;
-                }
-            }
-            handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig);
-            handler = new ProxyAuthenticationCallHandler(handler);
-            handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
-            final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
-            mechanisms.add(new CachedAuthenticatedSessionMechanism());
-            mechanisms.add(new UndertowAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, -1, null));
-            handler = new AuthenticationMechanismsHandler(handler, mechanisms);
-            IdentityManager identityManager = new IdentityManager() {
-                @Override
-                public Account verify(Account account) {
-                    return account;
-                }
-
-                @Override
-                public Account verify(String id, Credential credential) {
-                    throw new IllegalStateException("Should never be called in Keycloak flow");
-                }
-
-                @Override
-                public Account verify(Credential credential) {
-                    throw new IllegalStateException("Should never be called in Keycloak flow");
-                }
-            };
-            handler = new UndertowPreAuthActionsHandler(deploymentContext, userSessionManagement, sessionManager, handler);
-            return new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler);
-        }
-
-        private HttpHandler sessionHandling(HttpHandler toWrap) {
-            SessionCookieConfig sessionConfig = new SessionCookieConfig();
-            sessionConfig.setCookieName("keycloak." + deployment.getResourceName() + ".session");
-            sessionConfig.setPath(base);
-            if (deployment.getSslRequired() == SslRequired.ALL) sessionConfig.setSecure(true);
-            toWrap = new SessionAttachmentHandler(
-                    toWrap, sessionManager, sessionConfig);
-            return toWrap;
-        }
-
-    }
-
-
-    public Undertow build() {
-        builder.setHandler(root);
-        return builder.build();
-    }
-
-    public ProxyServerBuilder addHttpListener(int port, String host) {
-        builder.addHttpListener(port, host);
-        return this;
-    }
-
-    public ProxyServerBuilder addHttpsListener(int port, String host, KeyManager[] keyManagers, TrustManager[] trustManagers) {
-        builder.addHttpsListener(port, host, keyManagers, trustManagers);
-        return this;
-    }
-
-    public ProxyServerBuilder addHttpsListener(int port, String host, SSLContext sslContext) {
-        builder.addHttpsListener(port, host, sslContext);
-        return this;
-    }
-
-    public ProxyServerBuilder setBufferSize(int bufferSize) {
-        builder.setBufferSize(bufferSize);
-        return this;
-    }
-
-    public ProxyServerBuilder setBuffersPerRegion(int buffersPerRegion) {
-        builder.setBuffersPerRegion(buffersPerRegion);
-        return this;
-    }
-
-    public ProxyServerBuilder setIoThreads(int ioThreads) {
-        builder.setIoThreads(ioThreads);
-        return this;
-    }
-
-    public ProxyServerBuilder setWorkerThreads(int workerThreads) {
-        builder.setWorkerThreads(workerThreads);
-        return this;
-    }
-
-    public ProxyServerBuilder setDirectBuffers(boolean directBuffers) {
-        builder.setDirectBuffers(directBuffers);
-        return this;
-    }
-
-    public <T> ProxyServerBuilder setServerOption(Option<T> option, T value) {
-        builder.setServerOption(option, value);
-        return this;
-    }
-
-    public <T> ProxyServerBuilder setSocketOption(Option<T> option, T value) {
-        builder.setSocketOption(option, value);
-        return this;
-    }
-
-    public <T> ProxyServerBuilder setWorkerOption(Option<T> option, T value) {
-        builder.setWorkerOption(option, value);
-        return this;
-    }
-
-    public static ProxyConfig loadConfig(InputStream is) {
-        ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
-        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
-        ProxyConfig proxyConfig;
-        try {
-            proxyConfig = mapper.readValue(is, ProxyConfig.class);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return proxyConfig;
-    }
-    public static Undertow build(InputStream configStream) {
-        ProxyConfig config = loadConfig(configStream);
-        return build(config);
-
-    }
-
-    public static Undertow build(ProxyConfig config) {
-        ProxyServerBuilder builder = new ProxyServerBuilder();
-        if (config.getTargetUrl() == null) {
-            log.error("Must set Target URL");
-            return null;
-        }
-        builder.target(config.getTargetUrl());
-        if (config.getApplications() == null || config.getApplications().size() == 0) {
-            log.error("No applications defined");
-            return null;
-        }
-        initConnections(config, builder);
-        initOptions(config, builder);
-
-        for (ProxyConfig.Application application : config.getApplications()) {
-            ApplicationBuilder applicationBuilder = builder.application(application.getAdapterConfig())
-                    .base(application.getBasePath())
-                    .errorPage(application.getErrorPage());
-
-            if (application.getConstraints() != null) {
-                for (ProxyConfig.Constraint constraint : application.getConstraints()) {
-                    ApplicationBuilder.ConstraintBuilder constraintBuilder = applicationBuilder.constraint(constraint.getPattern());
-                    if (constraint.getRolesAllowed() != null) {
-                        constraintBuilder.roles(constraint.getRolesAllowed());
-                    }
-                    if (constraint.getMethods() != null) {
-                        constraintBuilder.methods(constraint.getMethods());
-                    }
-                    if (constraint.getExcludedMethods() != null) {
-                        constraintBuilder.excludedMethods(constraint.getExcludedMethods());
-                    }
-                    if (constraint.isDeny()) constraintBuilder.deny();
-                    if (constraint.isPermit()) constraintBuilder.permit();
-                    if (constraint.isAuthenticate()) constraintBuilder.authenticate();
-                    if (constraint.isPermitAndInject()) constraintBuilder.injectIfAuthenticated();
-                    constraintBuilder.add();
-                }
-            }
-            applicationBuilder.add();
-        }
-        return builder.build();
-    }
-
-    public static void initOptions(ProxyConfig config, ProxyServerBuilder builder) {
-        builder.sendAccessToken(config.isSendAccessToken());
-        builder.headerNameConfig(config.getHeaderNames());
-        if (config.getBufferSize() != null) builder.setBufferSize(config.getBufferSize());
-        if (config.getBuffersPerRegion() != null) builder.setBuffersPerRegion(config.getBuffersPerRegion());
-        if (config.getIoThreads() != null) builder.setIoThreads(config.getIoThreads());
-        if (config.getWorkerThreads() != null) builder.setWorkerThreads(config.getWorkerThreads());
-        if (config.getDirectBuffers() != null) builder.setDirectBuffers(config.getDirectBuffers());
-    }
-
-    public static void initConnections(ProxyConfig config, ProxyServerBuilder builder) {
-        if (config.getHttpPort() == null && config.getHttpsPort() == null) {
-            log.warn("You have not set up HTTP or HTTPS");
-        }
-        if (config.getHttpPort() != null) {
-            String bindAddress = "localhost";
-            if (config.getBindAddress() != null) bindAddress = config.getBindAddress();
-            builder.addHttpListener(config.getHttpPort(), bindAddress);
-        }
-        if (config.getHttpsPort() != null) {
-            String bindAddress = "localhost";
-            if (config.getBindAddress() != null) bindAddress = config.getBindAddress();
-            if (config.getKeystore() != null) {
-                InputStream is = FindFile.findFile(config.getKeystore());
-                SSLContext sslContext = null;
-                try {
-                    KeyStore keystore = KeyStore.getInstance("jks");
-                    keystore.load(is, config.getKeystorePassword().toCharArray());
-                    sslContext = SslUtil.createSSLContext(keystore, config.getKeyPassword(), null);
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-                builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext);
-            } else {
-                log.warn("Generating temporary SSL cert");
-                KeyPair keyPair = null;
-                try {
-                    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
-                    generator.initialize(2048);
-                    keyPair = generator.generateKeyPair();
-                } catch (NoSuchAlgorithmException e) {
-                    throw new RuntimeException(e);
-                }
-                X509Certificate certificate = null;
-                try {
-                    certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, bindAddress);
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-
-                try {
-                    KeyStore keyStore = KeyStore.getInstance("JKS");
-                    keyStore.load(null, null);
-                    PrivateKey privateKey = keyPair.getPrivate();
-
-
-                    Certificate[] chain =  {certificate};
-
-                    keyStore.setKeyEntry(bindAddress, privateKey, "password".toCharArray(), chain);
-                    SSLContext sslContext = SslUtil.createSSLContext(keyStore, "password", null);
-                    builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext);
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-    }
-}
+package org.keycloak.proxy;
+
+import io.undertow.Undertow;
+import io.undertow.security.api.AuthenticationMechanism;
+import io.undertow.security.api.AuthenticationMode;
+import io.undertow.security.handlers.AuthenticationMechanismsHandler;
+import io.undertow.security.handlers.SecurityInitialHandler;
+import io.undertow.security.idm.Account;
+import io.undertow.security.idm.Credential;
+import io.undertow.security.idm.IdentityManager;
+import io.undertow.security.impl.CachedAuthenticatedSessionMechanism;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.handlers.PathHandler;
+import io.undertow.server.handlers.ResponseCodeHandler;
+import io.undertow.server.handlers.proxy.ProxyHandler;
+import io.undertow.server.handlers.proxy.SimpleProxyClientProvider;
+import io.undertow.server.session.InMemorySessionManager;
+import io.undertow.server.session.SessionAttachmentHandler;
+import io.undertow.server.session.SessionCookieConfig;
+import io.undertow.server.session.SessionManager;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.util.FindFile;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.adapters.undertow.UndertowAuthenticatedActionsHandler;
+import org.keycloak.adapters.undertow.UndertowAuthenticationMechanism;
+import org.keycloak.adapters.undertow.UndertowPreAuthActionsHandler;
+import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.CertificateUtils;
+import org.keycloak.util.SystemPropertiesJsonParserFactory;
+import org.xnio.Option;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.*;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProxyServerBuilder {
+    protected static Logger log = Logger.getLogger(ProxyServerBuilder.class);
+    public static final HttpHandler NOT_FOUND = new HttpHandler() {
+        @Override
+        public void handleRequest(HttpServerExchange exchange) throws Exception {
+            exchange.setResponseCode(404);
+            exchange.endExchange();
+        }
+    };
+
+    protected Undertow.Builder builder = Undertow.builder();
+
+    protected PathHandler root = new PathHandler(NOT_FOUND);
+    protected HttpHandler proxyHandler;
+    protected boolean sendAccessToken;
+
+    protected Map<String, String> headerNameConfig;
+
+    public ProxyServerBuilder target(String uri) {
+        SimpleProxyClientProvider provider = null;
+        try {
+            provider = new SimpleProxyClientProvider(new URI(uri));
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+        final HttpHandler handler = new ProxyHandler(provider, 30000, ResponseCodeHandler.HANDLE_404);
+        proxyHandler = new HttpHandler() {
+            @Override
+            public void handleRequest(HttpServerExchange exchange) throws Exception {
+                exchange.setRelativePath(exchange.getRequestPath()); // need this otherwise proxy forwards to chopped off path
+                handler.handleRequest(exchange);
+            }
+        };
+        return this;
+    }
+
+    public ProxyServerBuilder sendAccessToken(boolean flag) {
+        this.sendAccessToken = flag;
+        return this;
+    }
+
+    public ProxyServerBuilder headerNameConfig(Map<String, String> headerNameConfig) {
+        this.headerNameConfig = headerNameConfig;
+        return this;
+    }
+
+    public ApplicationBuilder application(AdapterConfig config) {
+        return new ApplicationBuilder(config);
+    }
+
+    public class ApplicationBuilder {
+        protected NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
+        protected UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
+        protected AdapterDeploymentContext deploymentContext;
+        protected KeycloakDeployment deployment;
+        SessionManager sessionManager = new InMemorySessionManager(
+                "SESSION_MANAGER");
+        protected String base;
+        protected SecurityPathMatches.Builder constraintBuilder = new SecurityPathMatches.Builder();
+        protected SecurityPathMatches matches;
+        protected String errorPage;
+
+        public ApplicationBuilder base(String base) {
+            this.base = base;
+            return this;
+        }
+
+        public ApplicationBuilder errorPage(String errorPage) {
+            if (errorPage != null && errorPage.startsWith("/")) {
+                errorPage = errorPage.substring(1);
+            }
+            this.errorPage = errorPage;
+            return this;
+        }
+
+        public ApplicationBuilder(AdapterConfig config) {
+            this.deployment = KeycloakDeploymentBuilder.build(config);
+            this.deploymentContext = new AdapterDeploymentContext(deployment);
+        }
+
+        public ProxyServerBuilder add() {
+            matches = constraintBuilder.build();
+            HttpHandler handler = sessionHandling(addSecurity(proxyHandler));
+            root.addPrefixPath(base, handler);
+            return ProxyServerBuilder.this;
+        }
+
+        public ConstraintBuilder constraint(String pattern) {
+            log.debugv("add constraint: {0}", pattern);
+            return new ConstraintBuilder(pattern);
+        }
+
+        public class ConstraintBuilder {
+            protected String pattern;
+            protected Set<String> rolesAllowed = new HashSet<String>();
+            protected Set<String> methods = new HashSet<String>();
+            protected Set<String> excludedMethods = new HashSet<String>();
+            protected SecurityInfo.EmptyRoleSemantic semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE;
+
+            public ConstraintBuilder(String pattern) {
+                this.pattern = pattern;
+
+            }
+
+            public ConstraintBuilder deny() {
+                semantic = SecurityInfo.EmptyRoleSemantic.DENY;
+                return this;
+            }
+            public ConstraintBuilder permit() {
+                semantic = SecurityInfo.EmptyRoleSemantic.PERMIT;
+                return this;
+            }
+            public ConstraintBuilder authenticate() {
+                semantic = SecurityInfo.EmptyRoleSemantic.AUTHENTICATE;
+                return this;
+            }
+
+            public ConstraintBuilder injectIfAuthenticated() {
+                semantic = SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED;
+                return this;
+            }
+
+            public ConstraintBuilder excludedMethods(Set<String> excludedMethods) {
+                this.excludedMethods = excludedMethods;
+                return this;
+            }
+
+            public ConstraintBuilder methods(Set<String> methods) {
+                this.methods = methods;
+                return this;
+            }
+
+            public ConstraintBuilder method(String method) {
+                methods.add(method);
+                return this;
+            }
+
+            public ConstraintBuilder excludeMethod(String method) {
+                excludedMethods.add(method);
+                return this;
+            }
+
+
+            public ConstraintBuilder roles(String... roles) {
+                for (String role : roles) role(role);
+                return this;
+            }
+            public ConstraintBuilder roles(Set<String> roles) {
+                for (String role : roles) role(role);
+                return this;
+            }
+
+            public ConstraintBuilder role(String role) {
+                rolesAllowed.add(role);
+                return this;
+            }
+
+            public ApplicationBuilder add() {
+                constraintBuilder.addSecurityConstraint(rolesAllowed, semantic, pattern, methods, excludedMethods);
+                return ApplicationBuilder.this;
+            }
+
+
+        }
+
+        private HttpHandler addSecurity(final HttpHandler toWrap) {
+            HttpHandler handler = toWrap;
+            handler = new UndertowAuthenticatedActionsHandler(deploymentContext, toWrap);
+            if (errorPage != null) {
+                if (base.endsWith("/")) {
+                    errorPage = base + errorPage;
+                } else {
+                    errorPage = base + "/" + errorPage;
+                }
+            }
+            handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig);
+            handler = new ProxyAuthenticationCallHandler(handler);
+            handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
+            final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
+            mechanisms.add(new CachedAuthenticatedSessionMechanism());
+            mechanisms.add(new UndertowAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, -1, null));
+            handler = new AuthenticationMechanismsHandler(handler, mechanisms);
+            IdentityManager identityManager = new IdentityManager() {
+                @Override
+                public Account verify(Account account) {
+                    return account;
+                }
+
+                @Override
+                public Account verify(String id, Credential credential) {
+                    throw new IllegalStateException("Should never be called in Keycloak flow");
+                }
+
+                @Override
+                public Account verify(Credential credential) {
+                    throw new IllegalStateException("Should never be called in Keycloak flow");
+                }
+            };
+            handler = new UndertowPreAuthActionsHandler(deploymentContext, userSessionManagement, sessionManager, handler);
+            return new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler);
+        }
+
+        private HttpHandler sessionHandling(HttpHandler toWrap) {
+            SessionCookieConfig sessionConfig = new SessionCookieConfig();
+            sessionConfig.setCookieName("keycloak." + deployment.getResourceName() + ".session");
+            sessionConfig.setPath(base);
+            if (deployment.getSslRequired() == SslRequired.ALL) sessionConfig.setSecure(true);
+            toWrap = new SessionAttachmentHandler(
+                    toWrap, sessionManager, sessionConfig);
+            return toWrap;
+        }
+
+    }
+
+
+    public Undertow build() {
+        builder.setHandler(root);
+        return builder.build();
+    }
+
+    public ProxyServerBuilder addHttpListener(int port, String host) {
+        builder.addHttpListener(port, host);
+        return this;
+    }
+
+    public ProxyServerBuilder addHttpsListener(int port, String host, KeyManager[] keyManagers, TrustManager[] trustManagers) {
+        builder.addHttpsListener(port, host, keyManagers, trustManagers);
+        return this;
+    }
+
+    public ProxyServerBuilder addHttpsListener(int port, String host, SSLContext sslContext) {
+        builder.addHttpsListener(port, host, sslContext);
+        return this;
+    }
+
+    public ProxyServerBuilder setBufferSize(int bufferSize) {
+        builder.setBufferSize(bufferSize);
+        return this;
+    }
+
+    public ProxyServerBuilder setBuffersPerRegion(int buffersPerRegion) {
+        builder.setBuffersPerRegion(buffersPerRegion);
+        return this;
+    }
+
+    public ProxyServerBuilder setIoThreads(int ioThreads) {
+        builder.setIoThreads(ioThreads);
+        return this;
+    }
+
+    public ProxyServerBuilder setWorkerThreads(int workerThreads) {
+        builder.setWorkerThreads(workerThreads);
+        return this;
+    }
+
+    public ProxyServerBuilder setDirectBuffers(boolean directBuffers) {
+        builder.setDirectBuffers(directBuffers);
+        return this;
+    }
+
+    public <T> ProxyServerBuilder setServerOption(Option<T> option, T value) {
+        builder.setServerOption(option, value);
+        return this;
+    }
+
+    public <T> ProxyServerBuilder setSocketOption(Option<T> option, T value) {
+        builder.setSocketOption(option, value);
+        return this;
+    }
+
+    public <T> ProxyServerBuilder setWorkerOption(Option<T> option, T value) {
+        builder.setWorkerOption(option, value);
+        return this;
+    }
+
+    public static ProxyConfig loadConfig(InputStream is) {
+        ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
+        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
+        ProxyConfig proxyConfig;
+        try {
+            proxyConfig = mapper.readValue(is, ProxyConfig.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return proxyConfig;
+    }
+    public static Undertow build(InputStream configStream) {
+        ProxyConfig config = loadConfig(configStream);
+        return build(config);
+
+    }
+
+    public static Undertow build(ProxyConfig config) {
+        ProxyServerBuilder builder = new ProxyServerBuilder();
+        if (config.getTargetUrl() == null) {
+            log.error("Must set Target URL");
+            return null;
+        }
+        builder.target(config.getTargetUrl());
+        if (config.getApplications() == null || config.getApplications().size() == 0) {
+            log.error("No applications defined");
+            return null;
+        }
+        initConnections(config, builder);
+        initOptions(config, builder);
+
+        for (ProxyConfig.Application application : config.getApplications()) {
+            ApplicationBuilder applicationBuilder = builder.application(application.getAdapterConfig())
+                    .base(application.getBasePath())
+                    .errorPage(application.getErrorPage());
+
+            if (application.getConstraints() != null) {
+                for (ProxyConfig.Constraint constraint : application.getConstraints()) {
+                    ApplicationBuilder.ConstraintBuilder constraintBuilder = applicationBuilder.constraint(constraint.getPattern());
+                    if (constraint.getRolesAllowed() != null) {
+                        constraintBuilder.roles(constraint.getRolesAllowed());
+                    }
+                    if (constraint.getMethods() != null) {
+                        constraintBuilder.methods(constraint.getMethods());
+                    }
+                    if (constraint.getExcludedMethods() != null) {
+                        constraintBuilder.excludedMethods(constraint.getExcludedMethods());
+                    }
+                    if (constraint.isDeny()) constraintBuilder.deny();
+                    if (constraint.isPermit()) constraintBuilder.permit();
+                    if (constraint.isAuthenticate()) constraintBuilder.authenticate();
+                    if (constraint.isPermitAndInject()) constraintBuilder.injectIfAuthenticated();
+                    constraintBuilder.add();
+                }
+            }
+            applicationBuilder.add();
+        }
+        return builder.build();
+    }
+
+    public static void initOptions(ProxyConfig config, ProxyServerBuilder builder) {
+        builder.sendAccessToken(config.isSendAccessToken());
+        builder.headerNameConfig(config.getHeaderNames());
+        if (config.getBufferSize() != null) builder.setBufferSize(config.getBufferSize());
+        if (config.getBuffersPerRegion() != null) builder.setBuffersPerRegion(config.getBuffersPerRegion());
+        if (config.getIoThreads() != null) builder.setIoThreads(config.getIoThreads());
+        if (config.getWorkerThreads() != null) builder.setWorkerThreads(config.getWorkerThreads());
+        if (config.getDirectBuffers() != null) builder.setDirectBuffers(config.getDirectBuffers());
+    }
+
+    public static void initConnections(ProxyConfig config, ProxyServerBuilder builder) {
+        if (config.getHttpPort() == null && config.getHttpsPort() == null) {
+            log.warn("You have not set up HTTP or HTTPS");
+        }
+        if (config.getHttpPort() != null) {
+            String bindAddress = "localhost";
+            if (config.getBindAddress() != null) bindAddress = config.getBindAddress();
+            builder.addHttpListener(config.getHttpPort(), bindAddress);
+        }
+        if (config.getHttpsPort() != null) {
+            String bindAddress = "localhost";
+            if (config.getBindAddress() != null) bindAddress = config.getBindAddress();
+            if (config.getKeystore() != null) {
+                InputStream is = FindFile.findFile(config.getKeystore());
+                SSLContext sslContext = null;
+                try {
+                    KeyStore keystore = KeyStore.getInstance("jks");
+                    keystore.load(is, config.getKeystorePassword().toCharArray());
+                    sslContext = SslUtil.createSSLContext(keystore, config.getKeyPassword(), null);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+                builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext);
+            } else {
+                log.warn("Generating temporary SSL cert");
+                KeyPair keyPair = null;
+                try {
+                    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+                    generator.initialize(2048);
+                    keyPair = generator.generateKeyPair();
+                } catch (NoSuchAlgorithmException e) {
+                    throw new RuntimeException(e);
+                }
+                X509Certificate certificate = null;
+                try {
+                    certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, bindAddress);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+
+                try {
+                    KeyStore keyStore = KeyStore.getInstance("JKS");
+                    keyStore.load(null, null);
+                    PrivateKey privateKey = keyPair.getPrivate();
+
+
+                    Certificate[] chain =  {certificate};
+
+                    keyStore.setKeyEntry(bindAddress, privateKey, "password".toCharArray(), chain);
+                    SSLContext sslContext = SslUtil.createSSLContext(keyStore, "password", null);
+                    builder.addHttpsListener(config.getHttpsPort().intValue(), bindAddress, sslContext);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java
index 8cc1bc1..959a8cf 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/SslUtil.java
@@ -1,36 +1,36 @@
-package org.keycloak.proxy;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import java.security.KeyStore;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SslUtil {
-    public static SSLContext createSSLContext(final KeyStore keyStore, String password, final KeyStore trustStore) throws Exception {
-        KeyManager[] keyManagers;
-        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-        keyManagerFactory.init(keyStore, password.toCharArray());
-        keyManagers = keyManagerFactory.getKeyManagers();
-
-        TrustManager[] trustManagers = null;
-        if (trustStore != null) {
-            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-            trustManagerFactory.init(trustStore);
-            trustManagers = trustManagerFactory.getTrustManagers();
-        }
-
-        SSLContext sslContext;
-        sslContext = SSLContext.getInstance("TLS");
-        sslContext.init(keyManagers, trustManagers, null);
-
-        return sslContext;
-    }
-
-
-}
+package org.keycloak.proxy;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import java.security.KeyStore;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SslUtil {
+    public static SSLContext createSSLContext(final KeyStore keyStore, String password, final KeyStore trustStore) throws Exception {
+        KeyManager[] keyManagers;
+        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        keyManagerFactory.init(keyStore, password.toCharArray());
+        keyManagers = keyManagerFactory.getKeyManagers();
+
+        TrustManager[] trustManagers = null;
+        if (trustStore != null) {
+            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            trustManagerFactory.init(trustStore);
+            trustManagers = trustManagerFactory.getTrustManagers();
+        }
+
+        SSLContext sslContext;
+        sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(keyManagers, trustManagers, null);
+
+        return sslContext;
+    }
+
+
+}

saml/pom.xml 40(+20 -20)

diff --git a/saml/pom.xml b/saml/pom.xml
index 03f03b9..3590760 100755
--- a/saml/pom.xml
+++ b/saml/pom.xml
@@ -1,20 +1,20 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <name>Keycloak SAML Integration</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-saml-pom</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>saml-core</module>
-        <module>saml-protocol</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <name>Keycloak SAML Integration</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-saml-pom</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>saml-core</module>
+        <module>saml-protocol</module>
+    </modules>
+</project>

saml/saml-core/pom.xml 110(+55 -55)

diff --git a/saml/saml-core/pom.xml b/saml/saml-core/pom.xml
index cbda574..dff8303 100755
--- a/saml/saml-core/pom.xml
+++ b/saml/saml-core/pom.xml
@@ -1,55 +1,55 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-saml-core</artifactId>
-    <name>Keycloak SAML Core</name>
-    <description/>
-
-    <properties>
-        <timestamp>${maven.build.timestamp}</timestamp>
-        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
-    </properties>
-    <dependencies>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.santuario</groupId>
-            <artifactId>xmlsec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-saml-core</artifactId>
+    <name>Keycloak SAML Core</name>
+    <description/>
+
+    <properties>
+        <timestamp>${maven.build.timestamp}</timestamp>
+        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.santuario</groupId>
+            <artifactId>xmlsec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/saml/saml-protocol/pom.xml b/saml/saml-protocol/pom.xml
index 32028fb..0669a31 100755
--- a/saml/saml-protocol/pom.xml
+++ b/saml/saml-protocol/pom.xml
@@ -1,130 +1,130 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-saml-protocol</artifactId>
-    <name>Keycloak SAML Protocol</name>
-    <description/>
-
-    <properties>
-        <timestamp>${maven.build.timestamp}</timestamp>
-        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
-    </properties>
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-http-client</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-account-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-login-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-saml-protocol</artifactId>
+    <name>Keycloak SAML Protocol</name>
+    <description/>
+
+    <properties>
+        <timestamp>${maven.build.timestamp}</timestamp>
+        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-account-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-login-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
index 1ad72bf..a46614a 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
@@ -1,21 +1,21 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.exportimport.ClientImporter;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.admin.RealmAuth;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class EntityDescriptorImporter implements ClientImporter {
-    @Override
-    public Object createJaxrsService(RealmModel realm, RealmAuth auth) {
-        return new EntityDescriptorImporterService(realm, auth);
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.resources.admin.RealmAuth;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class EntityDescriptorImporter implements ClientImporter {
+    @Override
+    public Object createJaxrsService(RealmModel realm, RealmAuth auth) {
+        return new EntityDescriptorImporterService(realm, auth);
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
index 14af685..ccd7890 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
@@ -1,42 +1,42 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.Config;
-import org.keycloak.exportimport.ClientImporter;
-import org.keycloak.exportimport.ClientImporterFactory;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class EntityDescriptorImporterFactory implements ClientImporterFactory {
-    @Override
-    public String getDisplayName() {
-        return "SAML 2.0 Entity Descriptor";
-    }
-
-    @Override
-    public ClientImporter create(KeycloakSession session) {
-        return new EntityDescriptorImporter();
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return "saml2-entity-descriptor";
-    }
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.Config;
+import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.exportimport.ClientImporterFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class EntityDescriptorImporterFactory implements ClientImporterFactory {
+    @Override
+    public String getDisplayName() {
+        return "SAML 2.0 Entity Descriptor";
+    }
+
+    @Override
+    public ClientImporter create(KeycloakSession session) {
+        return new EntityDescriptorImporter();
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getId() {
+        return "saml2-entity-descriptor";
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
index 4ef05ea..2b6a72c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
@@ -1,149 +1,149 @@
-package org.keycloak.protocol.saml;
-
-import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.services.resources.admin.RealmAuth;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ParsingException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
-import org.keycloak.saml.processing.core.saml.v2.util.SAMLMetadataUtil;
-import org.keycloak.saml.processing.core.util.CoreConfigUtil;
-import org.keycloak.dom.saml.v2.metadata.EndpointType;
-import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
-import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
-import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
-import org.keycloak.dom.saml.v2.metadata.KeyTypes;
-import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.cert.X509Certificate;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class EntityDescriptorImporterService {
-    protected RealmModel realm;
-    protected RealmAuth auth;
-
-    public EntityDescriptorImporterService(RealmModel realm, RealmAuth auth) {
-        this.realm = realm;
-        this.auth = auth;
-    }
-
-    @POST
-    @Path("upload")
-    @Consumes(MediaType.MULTIPART_FORM_DATA)
-    public void updateEntityDescriptor(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
-        auth.requireManage();
-
-        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
-        List<InputPart> inputParts = uploadForm.get("file");
-
-        InputStream is = inputParts.get(0).getBody(InputStream.class, null);
-
-        loadEntityDescriptors(is, realm);
-
-    }
-
-    public static void loadEntityDescriptors(InputStream is, RealmModel realm) {
-        Object metadata = null;
-        try {
-            metadata = new SAMLParser().parse(is);
-        } catch (ParsingException e) {
-            throw new RuntimeException(e);
-        }
-        EntitiesDescriptorType entities;
-
-        if (EntitiesDescriptorType.class.isInstance(metadata)) {
-            entities = (EntitiesDescriptorType) metadata;
-        } else {
-            entities = new EntitiesDescriptorType();
-            entities.addEntityDescriptor(metadata);
-        }
-
-        for (Object o : entities.getEntityDescriptor()) {
-            EntityDescriptorType entity = (EntityDescriptorType)o;
-            String entityId = entity.getEntityID();
-            ClientModel app = realm.addClient(entityId);
-            app.setFullScopeAllowed(true);
-            app.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
-            app.setAttribute(SamlProtocol.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true
-            app.setAttribute(SamlProtocol.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
-            app.setAttribute(SamlProtocol.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
-            SPSSODescriptorType spDescriptorType = CoreConfigUtil.getSPDescriptor(entity);
-            if (spDescriptorType.isWantAssertionsSigned()) {
-                app.setAttribute(SamlProtocol.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
-            }
-            String logoutPost = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
-            if (logoutPost != null) app.setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE, logoutPost);
-            String logoutRedirect = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
-            if (logoutPost != null) app.setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, logoutRedirect);
-
-            String assertionConsumerServicePostBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
-            if (assertionConsumerServicePostBinding != null) {
-                app.setAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE, assertionConsumerServicePostBinding);
-                app.addRedirectUri(assertionConsumerServicePostBinding);
-            }
-            String assertionConsumerServiceRedirectBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
-            if (assertionConsumerServiceRedirectBinding != null) {
-                app.setAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE, assertionConsumerServiceRedirectBinding);
-                app.addRedirectUri(assertionConsumerServiceRedirectBinding);
-            }
-
-            for (KeyDescriptorType keyDescriptor : spDescriptorType.getKeyDescriptor()) {
-                X509Certificate cert = null;
-                try {
-                    cert = SAMLMetadataUtil.getCertificate(keyDescriptor);
-                } catch (ConfigurationException e) {
-                    throw new RuntimeException(e);
-                } catch (ProcessingException e) {
-                    throw new RuntimeException(e);
-                }
-                String certPem = KeycloakModelUtils.getPemFromCertificate(cert);
-                if (keyDescriptor.getUse() == KeyTypes.SIGNING) {
-                    app.setAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
-                    app.setAttribute(SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, certPem);
-                } else if (keyDescriptor.getUse() == KeyTypes.ENCRYPTION) {
-                    app.setAttribute(SamlProtocol.SAML_ENCRYPT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
-                    app.setAttribute(SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, certPem);
-                }
-            }
-        }
-    }
-
-    public static String getLogoutLocation(SPSSODescriptorType idp, String bindingURI) {
-        String logoutResponseLocation = null;
-
-        List<EndpointType> endpoints = idp.getSingleLogoutService();
-        for (EndpointType endpoint : endpoints) {
-            if (endpoint.getBinding().toString().equals(bindingURI)) {
-                if (endpoint.getLocation() != null) {
-                    logoutResponseLocation = endpoint.getLocation().toString();
-                } else {
-                    logoutResponseLocation = null;
-                }
-
-                break;
-            }
-
-        }
-        return logoutResponseLocation;
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.jboss.resteasy.plugins.providers.multipart.InputPart;
+import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
+import org.keycloak.saml.processing.core.saml.v2.util.SAMLMetadataUtil;
+import org.keycloak.saml.processing.core.util.CoreConfigUtil;
+import org.keycloak.dom.saml.v2.metadata.EndpointType;
+import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class EntityDescriptorImporterService {
+    protected RealmModel realm;
+    protected RealmAuth auth;
+
+    public EntityDescriptorImporterService(RealmModel realm, RealmAuth auth) {
+        this.realm = realm;
+        this.auth = auth;
+    }
+
+    @POST
+    @Path("upload")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    public void updateEntityDescriptor(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
+        auth.requireManage();
+
+        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
+        List<InputPart> inputParts = uploadForm.get("file");
+
+        InputStream is = inputParts.get(0).getBody(InputStream.class, null);
+
+        loadEntityDescriptors(is, realm);
+
+    }
+
+    public static void loadEntityDescriptors(InputStream is, RealmModel realm) {
+        Object metadata = null;
+        try {
+            metadata = new SAMLParser().parse(is);
+        } catch (ParsingException e) {
+            throw new RuntimeException(e);
+        }
+        EntitiesDescriptorType entities;
+
+        if (EntitiesDescriptorType.class.isInstance(metadata)) {
+            entities = (EntitiesDescriptorType) metadata;
+        } else {
+            entities = new EntitiesDescriptorType();
+            entities.addEntityDescriptor(metadata);
+        }
+
+        for (Object o : entities.getEntityDescriptor()) {
+            EntityDescriptorType entity = (EntityDescriptorType)o;
+            String entityId = entity.getEntityID();
+            ClientModel app = realm.addClient(entityId);
+            app.setFullScopeAllowed(true);
+            app.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+            app.setAttribute(SamlProtocol.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true
+            app.setAttribute(SamlProtocol.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
+            app.setAttribute(SamlProtocol.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
+            SPSSODescriptorType spDescriptorType = CoreConfigUtil.getSPDescriptor(entity);
+            if (spDescriptorType.isWantAssertionsSigned()) {
+                app.setAttribute(SamlProtocol.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
+            }
+            String logoutPost = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
+            if (logoutPost != null) app.setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE, logoutPost);
+            String logoutRedirect = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
+            if (logoutPost != null) app.setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, logoutRedirect);
+
+            String assertionConsumerServicePostBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
+            if (assertionConsumerServicePostBinding != null) {
+                app.setAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE, assertionConsumerServicePostBinding);
+                app.addRedirectUri(assertionConsumerServicePostBinding);
+            }
+            String assertionConsumerServiceRedirectBinding = CoreConfigUtil.getServiceURL(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
+            if (assertionConsumerServiceRedirectBinding != null) {
+                app.setAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE, assertionConsumerServiceRedirectBinding);
+                app.addRedirectUri(assertionConsumerServiceRedirectBinding);
+            }
+
+            for (KeyDescriptorType keyDescriptor : spDescriptorType.getKeyDescriptor()) {
+                X509Certificate cert = null;
+                try {
+                    cert = SAMLMetadataUtil.getCertificate(keyDescriptor);
+                } catch (ConfigurationException e) {
+                    throw new RuntimeException(e);
+                } catch (ProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+                String certPem = KeycloakModelUtils.getPemFromCertificate(cert);
+                if (keyDescriptor.getUse() == KeyTypes.SIGNING) {
+                    app.setAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
+                    app.setAttribute(SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, certPem);
+                } else if (keyDescriptor.getUse() == KeyTypes.ENCRYPTION) {
+                    app.setAttribute(SamlProtocol.SAML_ENCRYPT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
+                    app.setAttribute(SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, certPem);
+                }
+            }
+        }
+    }
+
+    public static String getLogoutLocation(SPSSODescriptorType idp, String bindingURI) {
+        String logoutResponseLocation = null;
+
+        List<EndpointType> endpoints = idp.getSingleLogoutService();
+        for (EndpointType endpoint : endpoints) {
+            if (endpoint.getBinding().toString().equals(bindingURI)) {
+                if (endpoint.getLocation() != null) {
+                    logoutResponseLocation = endpoint.getLocation().toString();
+                } else {
+                    logoutResponseLocation = null;
+                }
+
+                break;
+            }
+
+        }
+        return logoutResponseLocation;
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.java
index 303aff3..986a192 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.java
@@ -1,39 +1,39 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.saml.SamlProtocol;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractSAMLProtocolMapper implements ProtocolMapper {
-
-
-    @Override
-    public String getProtocol() {
-        return SamlProtocol.LOGIN_PROTOCOL;
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public final ProtocolMapper create(KeycloakSession session) {
-        throw new RuntimeException("UNSUPPORTED METHOD");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.saml.SamlProtocol;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractSAMLProtocolMapper implements ProtocolMapper {
+
+
+    @Override
+    public String getProtocol() {
+        return SamlProtocol.LOGIN_PROTOCOL;
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public final ProtocolMapper create(KeycloakSession session) {
+        throw new RuntimeException("UNSUPPORTED METHOD");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
index c854619..7de2b29 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
@@ -1,94 +1,94 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.protocol.saml.SamlProtocol;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AttributeStatementHelper {
-    public static final String SAML_ATTRIBUTE_NAME = "attribute.name";
-    public static final String ATTRIBUTE_STATEMENT_CATEGORY = "AttributeStatement Mapper";
-    public static final String FRIENDLY_NAME = "friendly.name";
-    public static final String FRIENDLY_NAME_LABEL = "Friendly Name";
-    public static final String FRIENDLY_NAME_HELP_TEXT = "Standard SAML attribute setting.  An optional, more human-readable form of the attribute's name that can be provided if the actual attribute name is cryptic.";
-    public static final String SAML_ATTRIBUTE_NAMEFORMAT = "attribute.nameformat";
-    public static final String BASIC = "Basic";
-    public static final String URI_REFERENCE = "URI Reference";
-    public static final String UNSPECIFIED = "Unspecified";
-
-    public static void addAttribute(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel,
-                                    String attributeValue) {
-        AttributeType attribute = createAttributeType(mappingModel);
-        attribute.addAttributeValue(attributeValue);
-        attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attribute));
-    }
-
-    public static AttributeType createAttributeType(ProtocolMapperModel mappingModel) {
-        String attributeName = mappingModel.getConfig().get(SAML_ATTRIBUTE_NAME);
-        AttributeType attribute = new AttributeType(attributeName);
-        String attributeType = mappingModel.getConfig().get(SAML_ATTRIBUTE_NAMEFORMAT);
-        String attributeNameFormat = JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC.get();
-        if ("URI Reference".equals(attributeType)) attributeNameFormat = JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get();
-        else if ("Unspecified".equals(attributeType)) attributeNameFormat = "urn:oasis:names:tc:SAML2.0:attrname-format:unspecified";
-        attribute.setNameFormat(attributeNameFormat);
-        String friendlyName = mappingModel.getConfig().get(FRIENDLY_NAME);
-        if (friendlyName != null && !friendlyName.trim().equals("")) attribute.setFriendlyName(friendlyName);
-        return attribute;
-    }
-
-    public static void setConfigProperties(List<ProviderConfigProperty> configProperties) {
-        ProviderConfigProperty property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.FRIENDLY_NAME);
-        property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
-        property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
-        property.setLabel("SAML Attribute Name");
-        property.setHelpText("SAML Attribute Name");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
-        property.setLabel("SAML Attribute NameFormat");
-        property.setHelpText("SAML Attribute NameFormat.  Can be basic, URI reference, or unspecified.");
-        List<String> types = new ArrayList(3);
-        types.add(AttributeStatementHelper.BASIC);
-        types.add(AttributeStatementHelper.URI_REFERENCE);
-        types.add(AttributeStatementHelper.UNSPECIFIED);
-        property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
-        configProperties.add(property);
-
-    }
-    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute, String samlAttributeName, String nameFormat,  String friendlyName, boolean consentRequired, String consentText, String mapperId) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(consentRequired);
-        mapper.setConsentText(consentText);
-        Map<String, String> config = new HashMap<String, String>();
-        if (userAttribute != null) config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
-        config.put(SAML_ATTRIBUTE_NAME, samlAttributeName);
-        if (friendlyName != null) {
-            config.put(FRIENDLY_NAME, friendlyName);
-        }
-        if (nameFormat != null) {
-            config.put(SAML_ATTRIBUTE_NAMEFORMAT, nameFormat);
-        }
-        mapper.setConfig(config);
-        return mapper;
-    }
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AttributeStatementHelper {
+    public static final String SAML_ATTRIBUTE_NAME = "attribute.name";
+    public static final String ATTRIBUTE_STATEMENT_CATEGORY = "AttributeStatement Mapper";
+    public static final String FRIENDLY_NAME = "friendly.name";
+    public static final String FRIENDLY_NAME_LABEL = "Friendly Name";
+    public static final String FRIENDLY_NAME_HELP_TEXT = "Standard SAML attribute setting.  An optional, more human-readable form of the attribute's name that can be provided if the actual attribute name is cryptic.";
+    public static final String SAML_ATTRIBUTE_NAMEFORMAT = "attribute.nameformat";
+    public static final String BASIC = "Basic";
+    public static final String URI_REFERENCE = "URI Reference";
+    public static final String UNSPECIFIED = "Unspecified";
+
+    public static void addAttribute(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel,
+                                    String attributeValue) {
+        AttributeType attribute = createAttributeType(mappingModel);
+        attribute.addAttributeValue(attributeValue);
+        attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attribute));
+    }
+
+    public static AttributeType createAttributeType(ProtocolMapperModel mappingModel) {
+        String attributeName = mappingModel.getConfig().get(SAML_ATTRIBUTE_NAME);
+        AttributeType attribute = new AttributeType(attributeName);
+        String attributeType = mappingModel.getConfig().get(SAML_ATTRIBUTE_NAMEFORMAT);
+        String attributeNameFormat = JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC.get();
+        if ("URI Reference".equals(attributeType)) attributeNameFormat = JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get();
+        else if ("Unspecified".equals(attributeType)) attributeNameFormat = "urn:oasis:names:tc:SAML2.0:attrname-format:unspecified";
+        attribute.setNameFormat(attributeNameFormat);
+        String friendlyName = mappingModel.getConfig().get(FRIENDLY_NAME);
+        if (friendlyName != null && !friendlyName.trim().equals("")) attribute.setFriendlyName(friendlyName);
+        return attribute;
+    }
+
+    public static void setConfigProperties(List<ProviderConfigProperty> configProperties) {
+        ProviderConfigProperty property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.FRIENDLY_NAME);
+        property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
+        property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
+        property.setLabel("SAML Attribute Name");
+        property.setHelpText("SAML Attribute Name");
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
+        property.setLabel("SAML Attribute NameFormat");
+        property.setHelpText("SAML Attribute NameFormat.  Can be basic, URI reference, or unspecified.");
+        List<String> types = new ArrayList(3);
+        types.add(AttributeStatementHelper.BASIC);
+        types.add(AttributeStatementHelper.URI_REFERENCE);
+        types.add(AttributeStatementHelper.UNSPECIFIED);
+        property.setType(ProviderConfigProperty.LIST_TYPE);
+        property.setDefaultValue(types);
+        configProperties.add(property);
+
+    }
+    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute, String samlAttributeName, String nameFormat,  String friendlyName, boolean consentRequired, String consentText, String mapperId) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(consentRequired);
+        mapper.setConsentText(consentText);
+        Map<String, String> config = new HashMap<String, String>();
+        if (userAttribute != null) config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
+        config.put(SAML_ATTRIBUTE_NAME, samlAttributeName);
+        if (friendlyName != null) {
+            config.put(FRIENDLY_NAME, friendlyName);
+        }
+        if (nameFormat != null) {
+            config.put(SAML_ATTRIBUTE_NAMEFORMAT, nameFormat);
+        }
+        mapper.setConfig(config);
+        return mapper;
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
index 5aa2d0a..086597d 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
@@ -1,79 +1,79 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
-    public static final String PROVIDER_ID = "saml-hardcode-attribute-mapper";
-    public static final String ATTRIBUTE_VALUE = "attribute.value";
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        AttributeStatementHelper.setConfigProperties(configProperties);
-        property = new ProviderConfigProperty();
-        property.setName(ATTRIBUTE_VALUE);
-        property.setLabel("Attribute value");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText("Value of the attribute you want to hard code.");
-        configProperties.add(property);
-
-    }
-
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Hardcoded attribute";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Hardcode an attribute into the SAML Assertion.";
-    }
-
-    @Override
-    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        String attributeValue = mappingModel.getConfig().get(ATTRIBUTE_VALUE);
-        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
-
-    }
-
-    public static ProtocolMapperModel create(String name,
-                                             String samlAttributeName, String nameFormat, String friendlyName, String value,
-                                             boolean consentRequired, String consentText) {
-        String mapperId = PROVIDER_ID;
-        ProtocolMapperModel model = AttributeStatementHelper.createAttributeMapper(name, null, samlAttributeName, nameFormat, friendlyName,
-                consentRequired, consentText, mapperId);
-        model.getConfig().put(ATTRIBUTE_VALUE, value);
-        return model;
-
-    }
-
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
+    public static final String PROVIDER_ID = "saml-hardcode-attribute-mapper";
+    public static final String ATTRIBUTE_VALUE = "attribute.value";
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        AttributeStatementHelper.setConfigProperties(configProperties);
+        property = new ProviderConfigProperty();
+        property.setName(ATTRIBUTE_VALUE);
+        property.setLabel("Attribute value");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setHelpText("Value of the attribute you want to hard code.");
+        configProperties.add(property);
+
+    }
+
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded attribute";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Hardcode an attribute into the SAML Assertion.";
+    }
+
+    @Override
+    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        String attributeValue = mappingModel.getConfig().get(ATTRIBUTE_VALUE);
+        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
+
+    }
+
+    public static ProtocolMapperModel create(String name,
+                                             String samlAttributeName, String nameFormat, String friendlyName, String value,
+                                             boolean consentRequired, String consentText) {
+        String mapperId = PROVIDER_ID;
+        ProtocolMapperModel model = AttributeStatementHelper.createAttributeMapper(name, null, samlAttributeName, nameFormat, friendlyName,
+                consentRequired, consentText, mapperId);
+        model.getConfig().put(ATTRIBUTE_VALUE, value);
+        return model;
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java
index a4ac579..e312281 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java
@@ -1,72 +1,72 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.protocol.saml.SamlProtocol;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HardcodedRole extends AbstractSAMLProtocolMapper {
-    public static final String PROVIDER_ID = "saml-hardcode-role-mapper";
-    public static final String ATTRIBUTE_VALUE = "attribute.value";
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName("role");
-        property.setLabel("Role");
-        property.setHelpText("Arbitrary role name you want to hardcode.  This role does not have to exist in current realm and can be just any string you need");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Hardcoded role";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Hardcode role into SAML Assertion.";
-    }
-
-    public static ProtocolMapperModel create(String name,
-                                             String role) {
-        String mapperId = PROVIDER_ID;
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
-       Map<String, String> config = new HashMap<String, String>();
-        config.put("role", role);
-        mapper.setConfig(config);
-        return mapper;
-
-    }
-
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.protocol.saml.SamlProtocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedRole extends AbstractSAMLProtocolMapper {
+    public static final String PROVIDER_ID = "saml-hardcode-role-mapper";
+    public static final String ATTRIBUTE_VALUE = "attribute.value";
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName("role");
+        property.setLabel("Role");
+        property.setHelpText("Arbitrary role name you want to hardcode.  This role does not have to exist in current realm and can be just any string you need");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded role";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Hardcode role into SAML Assertion.";
+    }
+
+    public static ProtocolMapperModel create(String name,
+                                             String role) {
+        String mapperId = PROVIDER_ID;
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+       Map<String, String> config = new HashMap<String, String>();
+        config.put("role", role);
+        mapper.setConfig(config);
+        return mapper;
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
index f4d5bd4..d59fc48 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
@@ -1,172 +1,172 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.protocol.saml.SamlProtocol;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.services.managers.ClientSessionCode;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRoleListMapper {
-    public static final String PROVIDER_ID = "saml-role-list-mapper";
-    public static final String SINGLE_ROLE_ATTRIBUTE = "single";
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
-        property.setLabel("Role attribute name");
-        property.setDefaultValue("Role");
-        property.setHelpText("Name of the SAML attribute you want to put your roles into.  i.e. 'Role', 'memberOf'.");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.FRIENDLY_NAME);
-        property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
-        property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
-        property.setLabel("SAML Attribute NameFormat");
-        property.setHelpText("SAML Attribute NameFormat.  Can be basic, URI reference, or unspecified.");
-        List<String> types = new ArrayList(3);
-        types.add(AttributeStatementHelper.BASIC);
-        types.add(AttributeStatementHelper.URI_REFERENCE);
-        types.add(AttributeStatementHelper.UNSPECIFIED);
-        property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(SINGLE_ROLE_ATTRIBUTE);
-        property.setLabel("Single Role Attribute");
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText("If true, all roles will be stored under one attribute with multiple attribute values.");
-        configProperties.add(property);
-
-    }
-
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Mapper";
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Role list";
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Role names are stored in an attribute value.  There is either one attribute with multiple attribute values, or an attribute per role name depending on how you configure it.  You can also specify the attribute name i.e. 'Role' or 'memberOf' being examples.";
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
-        boolean singleAttribute = Boolean.parseBoolean(single);
-
-        List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
-        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
-        AttributeType singleAttributeType = null;
-        Set<ProtocolMapperModel> requestedProtocolMappers = new ClientSessionCode(clientSession.getRealm(), clientSession).getRequestedProtocolMappers();
-        for (ProtocolMapperModel mapping : requestedProtocolMappers) {
-
-            ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
-            if (mapper == null) continue;
-            if (mapper instanceof SAMLRoleNameMapper) {
-                roleNameMappers.add(new SamlProtocol.ProtocolMapperProcessor<>((SAMLRoleNameMapper) mapper,mapping));
-            }
-            if (mapper instanceof HardcodedRole) {
-                AttributeType attributeType = null;
-                if (singleAttribute) {
-                    if (singleAttributeType == null) {
-                        singleAttributeType = AttributeStatementHelper.createAttributeType(mappingModel);
-                        roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType));
-                    }
-                    attributeType = singleAttributeType;
-                } else {
-                    attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
-                    roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
-                }
-                attributeType.addAttributeValue(mapping.getConfig().get("role"));
-            }
-        }
-
-        for (String roleId : clientSession.getRoles()) {
-            // todo need a role mapping
-            RoleModel roleModel = clientSession.getRealm().getRoleById(roleId);
-            AttributeType attributeType = null;
-            if (singleAttribute) {
-                if (singleAttributeType == null) {
-                    singleAttributeType = AttributeStatementHelper.createAttributeType(mappingModel);
-                    roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType));
-                }
-                attributeType = singleAttributeType;
-            } else {
-                attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
-                roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
-            }
-            String roleName = roleModel.getName();
-            for (SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper> entry : roleNameMappers) {
-                String newName = entry.mapper.mapName(entry.model, roleModel);
-                if (newName != null) {
-                    roleName = newName;
-                    break;
-                }
-            }
-            attributeType.addAttributeValue(roleName);
-        }
-
-    }
-
-    public static ProtocolMapperModel create(String name, String samlAttributeName, String nameFormat, String friendlyName, boolean singleAttribute) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(PROVIDER_ID);
-        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(false);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, samlAttributeName);
-        if (friendlyName != null) {
-            config.put(AttributeStatementHelper.FRIENDLY_NAME, friendlyName);
-        }
-        if (nameFormat != null) {
-            config.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, nameFormat);
-        }
-        config.put(SINGLE_ROLE_ATTRIBUTE, Boolean.toString(singleAttribute));
-        mapper.setConfig(config);
-
-        return mapper;
-    }
-
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.services.managers.ClientSessionCode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRoleListMapper {
+    public static final String PROVIDER_ID = "saml-role-list-mapper";
+    public static final String SINGLE_ROLE_ATTRIBUTE = "single";
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
+        property.setLabel("Role attribute name");
+        property.setDefaultValue("Role");
+        property.setHelpText("Name of the SAML attribute you want to put your roles into.  i.e. 'Role', 'memberOf'.");
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.FRIENDLY_NAME);
+        property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
+        property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
+        property.setLabel("SAML Attribute NameFormat");
+        property.setHelpText("SAML Attribute NameFormat.  Can be basic, URI reference, or unspecified.");
+        List<String> types = new ArrayList(3);
+        types.add(AttributeStatementHelper.BASIC);
+        types.add(AttributeStatementHelper.URI_REFERENCE);
+        types.add(AttributeStatementHelper.UNSPECIFIED);
+        property.setType(ProviderConfigProperty.LIST_TYPE);
+        property.setDefaultValue(types);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(SINGLE_ROLE_ATTRIBUTE);
+        property.setLabel("Single Role Attribute");
+        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText("If true, all roles will be stored under one attribute with multiple attribute values.");
+        configProperties.add(property);
+
+    }
+
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Mapper";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Role list";
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Role names are stored in an attribute value.  There is either one attribute with multiple attribute values, or an attribute per role name depending on how you configure it.  You can also specify the attribute name i.e. 'Role' or 'memberOf' being examples.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
+        boolean singleAttribute = Boolean.parseBoolean(single);
+
+        List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
+        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+        AttributeType singleAttributeType = null;
+        Set<ProtocolMapperModel> requestedProtocolMappers = new ClientSessionCode(clientSession.getRealm(), clientSession).getRequestedProtocolMappers();
+        for (ProtocolMapperModel mapping : requestedProtocolMappers) {
+
+            ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
+            if (mapper == null) continue;
+            if (mapper instanceof SAMLRoleNameMapper) {
+                roleNameMappers.add(new SamlProtocol.ProtocolMapperProcessor<>((SAMLRoleNameMapper) mapper,mapping));
+            }
+            if (mapper instanceof HardcodedRole) {
+                AttributeType attributeType = null;
+                if (singleAttribute) {
+                    if (singleAttributeType == null) {
+                        singleAttributeType = AttributeStatementHelper.createAttributeType(mappingModel);
+                        roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType));
+                    }
+                    attributeType = singleAttributeType;
+                } else {
+                    attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
+                    roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
+                }
+                attributeType.addAttributeValue(mapping.getConfig().get("role"));
+            }
+        }
+
+        for (String roleId : clientSession.getRoles()) {
+            // todo need a role mapping
+            RoleModel roleModel = clientSession.getRealm().getRoleById(roleId);
+            AttributeType attributeType = null;
+            if (singleAttribute) {
+                if (singleAttributeType == null) {
+                    singleAttributeType = AttributeStatementHelper.createAttributeType(mappingModel);
+                    roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType));
+                }
+                attributeType = singleAttributeType;
+            } else {
+                attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
+                roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
+            }
+            String roleName = roleModel.getName();
+            for (SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper> entry : roleNameMappers) {
+                String newName = entry.mapper.mapName(entry.model, roleModel);
+                if (newName != null) {
+                    roleName = newName;
+                    break;
+                }
+            }
+            attributeType.addAttributeValue(roleName);
+        }
+
+    }
+
+    public static ProtocolMapperModel create(String name, String samlAttributeName, String nameFormat, String friendlyName, boolean singleAttribute) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(PROVIDER_ID);
+        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(false);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, samlAttributeName);
+        if (friendlyName != null) {
+            config.put(AttributeStatementHelper.FRIENDLY_NAME, friendlyName);
+        }
+        if (nameFormat != null) {
+            config.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, nameFormat);
+        }
+        config.put(SINGLE_ROLE_ATTRIBUTE, Boolean.toString(singleAttribute));
+        mapper.setConfig(config);
+
+        return mapper;
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
index 38a42ad..a6a295c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
@@ -1,112 +1,112 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
-import org.keycloak.protocol.saml.SamlProtocol;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Map an assigned role to a different position and name in the token
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRoleNameMapper {
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String ROLE_CONFIG = "role";
-    public static String NEW_ROLE_NAME = "new.role.name";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ROLE_CONFIG);
-        property.setLabel("Role");
-        property.setHelpText("Role name you want changed.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(NEW_ROLE_NAME);
-        property.setLabel("New Role Name");
-        property.setHelpText("The new role name.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "saml-role-name-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Role Name Mapper";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return "Role Mapper";
-
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Map an assigned role to a new name";
-    }
-
-    @Override
-    public String mapName(ProtocolMapperModel model, RoleModel roleModel) {
-        RoleContainerModel container = roleModel.getContainer();
-        ClientModel app = null;
-        if (container instanceof ClientModel) {
-            app = ((ClientModel) container);
-        }
-        String role = model.getConfig().get(ROLE_CONFIG);
-        String newName = model.getConfig().get(NEW_ROLE_NAME);
-        String appName = null;
-        int scopeIndex = role.indexOf('.');
-        if (scopeIndex > -1) {
-            if (app == null) return null;
-            appName = role.substring(0, scopeIndex);
-            if (!app.getClientId().equals(appName)) return null;
-            role = role.substring(scopeIndex + 1);
-        } else {
-            if (app != null) return null;
-        }
-        if (roleModel.getName().equals(role)) return newName;
-        return null;
-   }
-
-    public static ProtocolMapperModel create(String name,
-                                             String role,
-                                             String newName) {
-        String mapperId = PROVIDER_ID;
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(ROLE_CONFIG, role);
-        config.put(NEW_ROLE_NAME, newName);
-        mapper.setConfig(config);
-        return mapper;
-
-    }
-
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
+import org.keycloak.protocol.saml.SamlProtocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Map an assigned role to a different position and name in the token
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRoleNameMapper {
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String ROLE_CONFIG = "role";
+    public static String NEW_ROLE_NAME = "new.role.name";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ROLE_CONFIG);
+        property.setLabel("Role");
+        property.setHelpText("Role name you want changed.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(NEW_ROLE_NAME);
+        property.setLabel("New Role Name");
+        property.setHelpText("The new role name.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "saml-role-name-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Role Name Mapper";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return "Role Mapper";
+
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Map an assigned role to a new name";
+    }
+
+    @Override
+    public String mapName(ProtocolMapperModel model, RoleModel roleModel) {
+        RoleContainerModel container = roleModel.getContainer();
+        ClientModel app = null;
+        if (container instanceof ClientModel) {
+            app = ((ClientModel) container);
+        }
+        String role = model.getConfig().get(ROLE_CONFIG);
+        String newName = model.getConfig().get(NEW_ROLE_NAME);
+        String appName = null;
+        int scopeIndex = role.indexOf('.');
+        if (scopeIndex > -1) {
+            if (app == null) return null;
+            appName = role.substring(0, scopeIndex);
+            if (!app.getClientId().equals(appName)) return null;
+            role = role.substring(scopeIndex + 1);
+        } else {
+            if (app != null) return null;
+        }
+        if (roleModel.getName().equals(role)) return newName;
+        return null;
+   }
+
+    public static ProtocolMapperModel create(String name,
+                                             String role,
+                                             String newName) {
+        String mapperId = PROVIDER_ID;
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(ROLE_CONFIG, role);
+        config.put(NEW_ROLE_NAME, newName);
+        mapper.setConfig(config);
+        return mapper;
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
index 4a7dbfb..09b9b10 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
@@ -1,17 +1,17 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface SAMLAttributeStatementMapper {
-
-    void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                        UserSessionModel userSession, ClientSessionModel clientSession);
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface SAMLAttributeStatementMapper {
+
+    void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                        UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
index 5f17893..1fcb5df 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
@@ -1,17 +1,17 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface SAMLLoginResponseMapper {
-
-    ResponseType transformLoginResponse(ResponseType response, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                        UserSessionModel userSession, ClientSessionModel clientSession);
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface SAMLLoginResponseMapper {
+
+    ResponseType transformLoginResponse(ResponseType response, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                        UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
index 160b3ac..16347c6 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
@@ -1,17 +1,17 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface SAMLRoleListMapper {
-
-    void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                     UserSessionModel userSession, ClientSessionModel clientSession);
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface SAMLRoleListMapper {
+
+    void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                     UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleNameMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleNameMapper.java
index caf2e4d..f3ecbd4 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleNameMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleNameMapper.java
@@ -1,12 +1,12 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RoleModel;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface SAMLRoleNameMapper {
-    public String mapName(ProtocolMapperModel model, RoleModel role);
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RoleModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface SAMLRoleNameMapper {
+    public String mapName(ProtocolMapperModel model, RoleModel role);
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
index b5f59ad..dc80760 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
@@ -1,80 +1,80 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Mappings UserModel attribute (not property name of a getter method) to an AttributeStatement.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
-        property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
-        property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
-        configProperties.add(property);
-        AttributeStatementHelper.setConfigProperties(configProperties);
-
-    }
-
-    public static final String PROVIDER_ID = "saml-user-attribute-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Attribute";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Map a custom user attribute to a to a SAML attribute.";
-    }
-
-    @Override
-    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        UserModel user = userSession.getUser();
-        String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
-        String attributeValue = user.getFirstAttribute(attributeName);
-        if (attributeValue == null) return;
-        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
-
-    }
-
-    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute,
-                                                            String samlAttributeName, String nameFormat, String friendlyName,
-                                                            boolean consentRequired, String consentText) {
-        String mapperId = PROVIDER_ID;
-        return AttributeStatementHelper.createAttributeMapper(name, userAttribute, samlAttributeName, nameFormat, friendlyName,
-                consentRequired, consentText, mapperId);
-
-    }
-
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserModel attribute (not property name of a getter method) to an AttributeStatement.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
+        property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
+        property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
+        configProperties.add(property);
+        AttributeStatementHelper.setConfigProperties(configProperties);
+
+    }
+
+    public static final String PROVIDER_ID = "saml-user-attribute-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Attribute";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Map a custom user attribute to a to a SAML attribute.";
+    }
+
+    @Override
+    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        UserModel user = userSession.getUser();
+        String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
+        String attributeValue = user.getFirstAttribute(attributeName);
+        if (attributeValue == null) return;
+        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
+
+    }
+
+    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute,
+                                                            String samlAttributeName, String nameFormat, String friendlyName,
+                                                            boolean consentRequired, String consentText) {
+        String mapperId = PROVIDER_ID;
+        return AttributeStatementHelper.createAttributeMapper(name, userAttribute, samlAttributeName, nameFormat, friendlyName,
+                consentRequired, consentText, mapperId);
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
index 095608d..e0518bc 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
@@ -1,79 +1,79 @@
-package org.keycloak.protocol.saml.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
-        property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
-        property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
-        configProperties.add(property);
-        AttributeStatementHelper.setConfigProperties(configProperties);
-
-    }
-
-    public static final String PROVIDER_ID = "saml-user-property-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Property";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Map a built in user property to a SAML attribute type.";
-    }
-
-    @Override
-    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        UserModel user = userSession.getUser();
-        String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
-        String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
-        if (propertyValue == null) return;
-        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, propertyValue);
-
-    }
-
-    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute,
-                                                            String samlAttributeName, String nameFormat, String friendlyName,
-                                          boolean consentRequired, String consentText) {
-        String mapperId = PROVIDER_ID;
-        return AttributeStatementHelper.createAttributeMapper(name, userAttribute, samlAttributeName, nameFormat, friendlyName,
-                consentRequired, consentText, mapperId);
-
-    }
-}
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
+        property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
+        property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
+        configProperties.add(property);
+        AttributeStatementHelper.setConfigProperties(configProperties);
+
+    }
+
+    public static final String PROVIDER_ID = "saml-user-property-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Property";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Map a built in user property to a SAML attribute type.";
+    }
+
+    @Override
+    public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        UserModel user = userSession.getUser();
+        String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
+        String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
+        if (propertyValue == null) return;
+        AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, propertyValue);
+
+    }
+
+    public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute,
+                                                            String samlAttributeName, String nameFormat, String friendlyName,
+                                          boolean consentRequired, String consentText) {
+        String mapperId = PROVIDER_ID;
+        return AttributeStatementHelper.createAttributeMapper(name, userAttribute, samlAttributeName, nameFormat, friendlyName,
+                consentRequired, consentText, mapperId);
+
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
index 7fe2fb3..c59cd34 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
@@ -1,382 +1,382 @@
-package org.keycloak.protocol.saml;
-
-import org.jboss.logging.Logger;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
-import org.keycloak.saml.processing.core.saml.v2.util.DocumentUtil;
-import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import javax.ws.rs.core.CacheControl;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.xml.namespace.QName;
-import java.io.IOException;
-import java.net.URI;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.cert.X509Certificate;
-
-import static org.keycloak.util.HtmlUtils.escapeAttribute;
-import static org.keycloak.saml.common.util.StringUtil.isNotNull;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
-    protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder.class);
-    public static final String RELAY_STATE = "RelayState";
-
-    protected KeyPair signingKeyPair;
-    protected X509Certificate signingCertificate;
-    protected boolean sign;
-    protected boolean signAssertions;
-    protected SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA1;
-    protected String relayState;
-    protected String destination;
-    protected String issuer;
-    protected int encryptionKeySize = 128;
-    protected PublicKey encryptionPublicKey;
-    protected String encryptionAlgorithm = "AES";
-    protected boolean encrypt;
-
-    public T signDocument() {
-        this.sign = true;
-        return (T)this;
-    }
-
-    public T signAssertions() {
-        this.signAssertions = true;
-        return (T)this;
-    }
-
-    public T signWith(KeyPair keyPair) {
-        this.signingKeyPair = keyPair;
-        return (T)this;
-    }
-
-    public T signWith(PrivateKey privateKey, PublicKey publicKey) {
-        this.signingKeyPair = new KeyPair(publicKey, privateKey);
-        return (T)this;
-    }
-
-    public T signWith(KeyPair keyPair, X509Certificate cert) {
-        this.signingKeyPair = keyPair;
-        this.signingCertificate = cert;
-        return (T)this;
-    }
-
-    public T signWith(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) {
-        this.signingKeyPair = new KeyPair(publicKey, privateKey);
-        this.signingCertificate = cert;
-        return (T)this;
-    }
-
-    public T signatureAlgorithm(SignatureAlgorithm alg) {
-        this.signatureAlgorithm = alg;
-        return (T)this;
-    }
-
-    public T encrypt(PublicKey publicKey) {
-        encrypt = true;
-        encryptionPublicKey = publicKey;
-        return (T)this;
-    }
-
-    public T encryptionAlgorithm(String alg) {
-        this.encryptionAlgorithm = alg;
-        return (T)this;
-    }
-
-    public T encryptionKeySize(int size) {
-        this.encryptionKeySize = size;
-        return (T)this;
-    }
-
-    public T destination(String destination) {
-        this.destination = destination;
-        return (T)this;
-    }
-
-    public T issuer(String issuer) {
-        this.issuer = issuer;
-        return (T)this;
-    }
-
-    public T relayState(String relayState) {
-        this.relayState = relayState;
-        return (T)this;
-    }
-
-    public class PostBindingBuilder {
-        protected Document document;
-
-        public PostBindingBuilder(Document document) throws ProcessingException {
-            this.document = document;
-            if (signAssertions) {
-                signAssertion(document);
-            }
-            if (sign) {
-                signDocument(document);
-            }
-        }
-
-        public String encoded() throws ProcessingException, ConfigurationException, IOException {
-            byte[] responseBytes = DocumentUtil.getDocumentAsString(document).getBytes("UTF-8");
-            return PostBindingUtil.base64Encode(new String(responseBytes));
-        }
-        public Document getDocument() {
-            return document;
-        }
-
-        public Response request() throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, destination, true);
-        }
-        public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, actionUrl, true);
-        }
-        public Response response() throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, destination, false);
-        }
-        public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, actionUrl, false);
-        }
-    }
-
-
-    public class RedirectBindingBuilder {
-        protected Document document;
-
-        public RedirectBindingBuilder(Document document) throws ProcessingException {
-            this.document = document;
-            if (signAssertions) {
-                signAssertion(document);
-            }
-        }
-
-        public Document getDocument() {
-            return document;
-        }
-        public URI responseUri(String redirectUri, boolean asRequest) throws ConfigurationException, ProcessingException, IOException {
-            String samlParameterName = GeneralConstants.SAML_RESPONSE_KEY;
-
-            if (asRequest) {
-                samlParameterName = GeneralConstants.SAML_REQUEST_KEY;
-            }
-
-            return generateRedirectUri(samlParameterName, redirectUri, document);
-        }
-        public Response response() throws ProcessingException, ConfigurationException, IOException {
-            return response(destination, false);
-        }
-        public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException {
-            return response(redirectUri, false);
-        }
-
-        public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException {
-            return response(redirect, true);
-        }
-        public Response request() throws ProcessingException, ConfigurationException, IOException {
-            return response(destination, true);
-        }
-
-        private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-            URI uri = responseUri(redirectUri, asRequest);
-            if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString());
-            CacheControl cacheControl = new CacheControl();
-            cacheControl.setNoCache(true);
-            return Response.status(302).location(uri)
-                    .header("Pragma", "no-cache")
-                    .header("Cache-Control", "no-cache, no-store").build();
-        }
-
-    }
-
-
-
-    private String getSAMLNSPrefix(Document samlResponseDocument) {
-        Node assertionElement = samlResponseDocument.getDocumentElement()
-                .getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()).item(0);
-
-        if (assertionElement == null) {
-            throw new IllegalStateException("Unable to find assertion in saml response document");
-        }
-
-        return assertionElement.getPrefix();
-    }
-
-    protected void encryptDocument(Document samlDocument) throws ProcessingException {
-        String samlNSPrefix = getSAMLNSPrefix(samlDocument);
-
-        try {
-            QName encryptedAssertionElementQName = new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
-                    JBossSAMLConstants.ENCRYPTED_ASSERTION.get(), samlNSPrefix);
-
-            byte[] secret = SamlProtocolUtils.createRandomSecret(encryptionKeySize / 8);
-            SecretKey secretKey = new SecretKeySpec(secret, encryptionAlgorithm);
-
-            // encrypt the Assertion element and replace it with a EncryptedAssertion element.
-            XMLEncryptionUtil.encryptElement(new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
-                            JBossSAMLConstants.ASSERTION.get(), samlNSPrefix), samlDocument, encryptionPublicKey,
-                    secretKey, encryptionKeySize, encryptedAssertionElementQName, true);
-        } catch (Exception e) {
-            throw new ProcessingException("failed to encrypt", e);
-        }
-
-    }
-
-    protected void signDocument(Document samlDocument) throws ProcessingException {
-        String signatureMethod = signatureAlgorithm.getXmlSignatureMethod();
-        String signatureDigestMethod = signatureAlgorithm.getXmlSignatureDigestMethod();
-        SAML2Signature samlSignature = new SAML2Signature();
-
-        if (signatureMethod != null) {
-            samlSignature.setSignatureMethod(signatureMethod);
-        }
-
-        if (signatureDigestMethod != null) {
-            samlSignature.setDigestMethod(signatureDigestMethod);
-        }
-
-        Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument);
-
-        samlSignature.setNextSibling(nextSibling);
-
-        if (signingCertificate != null) {
-            samlSignature.setX509Certificate(signingCertificate);
-        }
-
-        samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
-    }
-
-    protected void signAssertion(Document samlDocument) throws ProcessingException {
-        Element originalAssertionElement = org.keycloak.saml.common.util.DocumentUtil.getChildElement(samlDocument.getDocumentElement(), new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()));
-        if (originalAssertionElement == null) return;
-        Node clonedAssertionElement = originalAssertionElement.cloneNode(true);
-        Document temporaryDocument;
-
-        try {
-            temporaryDocument = org.keycloak.saml.common.util.DocumentUtil.createDocument();
-        } catch (ConfigurationException e) {
-            throw new ProcessingException(e);
-        }
-
-        temporaryDocument.adoptNode(clonedAssertionElement);
-        temporaryDocument.appendChild(clonedAssertionElement);
-
-        signDocument(temporaryDocument);
-
-        samlDocument.adoptNode(clonedAssertionElement);
-
-        Element parentNode = (Element) originalAssertionElement.getParentNode();
-
-        parentNode.replaceChild(clonedAssertionElement, originalAssertionElement);
-    }
-
-
-    protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-        String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest);
-
-        CacheControl cacheControl = new CacheControl();
-        cacheControl.setNoCache(true);
-        return Response.ok(str, MediaType.TEXT_HTML_TYPE)
-                       .header("Pragma", "no-cache")
-                       .header("Cache-Control", "no-cache, no-store").build();
-    }
-
-    protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-        byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
-        String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
-
-        return buildHtml(samlResponse, actionUrl, asRequest);
-    }
-
-    protected String buildHtml(String samlResponse, String actionUrl, boolean asRequest) {
-        if (destination == null) {
-            throw SAML2LoginResponseBuilder.logger.nullValueError("Destination is null");
-        }
-
-        StringBuilder builder = new StringBuilder();
-
-        String key = GeneralConstants.SAML_RESPONSE_KEY;
-
-        if (asRequest) {
-            key = GeneralConstants.SAML_REQUEST_KEY;
-        }
-
-        builder.append("<HTML>");
-        builder.append("<HEAD>");
-
-        builder.append("<TITLE>HTTP Post Binding Response (Response)</TITLE>");
-        builder.append("</HEAD>");
-        builder.append("<BODY Onload=\"document.forms[0].submit()\">");
-
-        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + actionUrl + "\">");
-        builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + " VALUE=\"" + samlResponse + "\"/>");
-
-        if (isNotNull(relayState)) {
-            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + RELAY_STATE + "\" " + "VALUE=\"" + escapeAttribute(relayState) + "\"/>");
-        }
-
-        builder.append("<NOSCRIPT>");
-        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>");
-        builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
-        builder.append("</NOSCRIPT>");
-
-        builder.append("</FORM></BODY></HTML>");
-
-        return builder.toString();
-    }
-
-    protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException  {
-        String documentAsString = DocumentUtil.getDocumentAsString(document);
-        logger.debugv("saml docment: {0}", documentAsString);
-        byte[] responseBytes = documentAsString.getBytes("UTF-8");
-
-        return RedirectBindingUtil.deflateBase64URLEncode(responseBytes);
-    }
-
-
-    protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException {
-        UriBuilder builder = UriBuilder.fromUri(redirectUri)
-                .replaceQuery(null)
-                .queryParam(samlParameterName, base64Encoded(document));
-        if (relayState != null) {
-            builder.queryParam(RELAY_STATE, relayState);
-        }
-
-        if (sign) {
-            builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
-            URI uri = builder.build();
-            String rawQuery = uri.getRawQuery();
-            Signature signature = signatureAlgorithm.createSignature();
-            byte[] sig = new byte[0];
-            try {
-                signature.initSign(signingKeyPair.getPrivate());
-                signature.update(rawQuery.getBytes("UTF-8"));
-                sig = signature.sign();
-            } catch (Exception e) {
-                throw new ProcessingException(e);
-            }
-            String encodedSig = RedirectBindingUtil.base64URLEncode(sig);
-            builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
-        }
-        return builder.build();
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.jboss.logging.Logger;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
+import org.keycloak.saml.processing.core.saml.v2.util.DocumentUtil;
+import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.net.URI;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
+
+import static org.keycloak.util.HtmlUtils.escapeAttribute;
+import static org.keycloak.saml.common.util.StringUtil.isNotNull;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
+    protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder.class);
+    public static final String RELAY_STATE = "RelayState";
+
+    protected KeyPair signingKeyPair;
+    protected X509Certificate signingCertificate;
+    protected boolean sign;
+    protected boolean signAssertions;
+    protected SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA1;
+    protected String relayState;
+    protected String destination;
+    protected String issuer;
+    protected int encryptionKeySize = 128;
+    protected PublicKey encryptionPublicKey;
+    protected String encryptionAlgorithm = "AES";
+    protected boolean encrypt;
+
+    public T signDocument() {
+        this.sign = true;
+        return (T)this;
+    }
+
+    public T signAssertions() {
+        this.signAssertions = true;
+        return (T)this;
+    }
+
+    public T signWith(KeyPair keyPair) {
+        this.signingKeyPair = keyPair;
+        return (T)this;
+    }
+
+    public T signWith(PrivateKey privateKey, PublicKey publicKey) {
+        this.signingKeyPair = new KeyPair(publicKey, privateKey);
+        return (T)this;
+    }
+
+    public T signWith(KeyPair keyPair, X509Certificate cert) {
+        this.signingKeyPair = keyPair;
+        this.signingCertificate = cert;
+        return (T)this;
+    }
+
+    public T signWith(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) {
+        this.signingKeyPair = new KeyPair(publicKey, privateKey);
+        this.signingCertificate = cert;
+        return (T)this;
+    }
+
+    public T signatureAlgorithm(SignatureAlgorithm alg) {
+        this.signatureAlgorithm = alg;
+        return (T)this;
+    }
+
+    public T encrypt(PublicKey publicKey) {
+        encrypt = true;
+        encryptionPublicKey = publicKey;
+        return (T)this;
+    }
+
+    public T encryptionAlgorithm(String alg) {
+        this.encryptionAlgorithm = alg;
+        return (T)this;
+    }
+
+    public T encryptionKeySize(int size) {
+        this.encryptionKeySize = size;
+        return (T)this;
+    }
+
+    public T destination(String destination) {
+        this.destination = destination;
+        return (T)this;
+    }
+
+    public T issuer(String issuer) {
+        this.issuer = issuer;
+        return (T)this;
+    }
+
+    public T relayState(String relayState) {
+        this.relayState = relayState;
+        return (T)this;
+    }
+
+    public class PostBindingBuilder {
+        protected Document document;
+
+        public PostBindingBuilder(Document document) throws ProcessingException {
+            this.document = document;
+            if (signAssertions) {
+                signAssertion(document);
+            }
+            if (sign) {
+                signDocument(document);
+            }
+        }
+
+        public String encoded() throws ProcessingException, ConfigurationException, IOException {
+            byte[] responseBytes = DocumentUtil.getDocumentAsString(document).getBytes("UTF-8");
+            return PostBindingUtil.base64Encode(new String(responseBytes));
+        }
+        public Document getDocument() {
+            return document;
+        }
+
+        public Response request() throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, destination, true);
+        }
+        public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, actionUrl, true);
+        }
+        public Response response() throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, destination, false);
+        }
+        public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, actionUrl, false);
+        }
+    }
+
+
+    public class RedirectBindingBuilder {
+        protected Document document;
+
+        public RedirectBindingBuilder(Document document) throws ProcessingException {
+            this.document = document;
+            if (signAssertions) {
+                signAssertion(document);
+            }
+        }
+
+        public Document getDocument() {
+            return document;
+        }
+        public URI responseUri(String redirectUri, boolean asRequest) throws ConfigurationException, ProcessingException, IOException {
+            String samlParameterName = GeneralConstants.SAML_RESPONSE_KEY;
+
+            if (asRequest) {
+                samlParameterName = GeneralConstants.SAML_REQUEST_KEY;
+            }
+
+            return generateRedirectUri(samlParameterName, redirectUri, document);
+        }
+        public Response response() throws ProcessingException, ConfigurationException, IOException {
+            return response(destination, false);
+        }
+        public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException {
+            return response(redirectUri, false);
+        }
+
+        public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException {
+            return response(redirect, true);
+        }
+        public Response request() throws ProcessingException, ConfigurationException, IOException {
+            return response(destination, true);
+        }
+
+        private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+            URI uri = responseUri(redirectUri, asRequest);
+            if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString());
+            CacheControl cacheControl = new CacheControl();
+            cacheControl.setNoCache(true);
+            return Response.status(302).location(uri)
+                    .header("Pragma", "no-cache")
+                    .header("Cache-Control", "no-cache, no-store").build();
+        }
+
+    }
+
+
+
+    private String getSAMLNSPrefix(Document samlResponseDocument) {
+        Node assertionElement = samlResponseDocument.getDocumentElement()
+                .getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()).item(0);
+
+        if (assertionElement == null) {
+            throw new IllegalStateException("Unable to find assertion in saml response document");
+        }
+
+        return assertionElement.getPrefix();
+    }
+
+    protected void encryptDocument(Document samlDocument) throws ProcessingException {
+        String samlNSPrefix = getSAMLNSPrefix(samlDocument);
+
+        try {
+            QName encryptedAssertionElementQName = new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
+                    JBossSAMLConstants.ENCRYPTED_ASSERTION.get(), samlNSPrefix);
+
+            byte[] secret = SamlProtocolUtils.createRandomSecret(encryptionKeySize / 8);
+            SecretKey secretKey = new SecretKeySpec(secret, encryptionAlgorithm);
+
+            // encrypt the Assertion element and replace it with a EncryptedAssertion element.
+            XMLEncryptionUtil.encryptElement(new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
+                            JBossSAMLConstants.ASSERTION.get(), samlNSPrefix), samlDocument, encryptionPublicKey,
+                    secretKey, encryptionKeySize, encryptedAssertionElementQName, true);
+        } catch (Exception e) {
+            throw new ProcessingException("failed to encrypt", e);
+        }
+
+    }
+
+    protected void signDocument(Document samlDocument) throws ProcessingException {
+        String signatureMethod = signatureAlgorithm.getXmlSignatureMethod();
+        String signatureDigestMethod = signatureAlgorithm.getXmlSignatureDigestMethod();
+        SAML2Signature samlSignature = new SAML2Signature();
+
+        if (signatureMethod != null) {
+            samlSignature.setSignatureMethod(signatureMethod);
+        }
+
+        if (signatureDigestMethod != null) {
+            samlSignature.setDigestMethod(signatureDigestMethod);
+        }
+
+        Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument);
+
+        samlSignature.setNextSibling(nextSibling);
+
+        if (signingCertificate != null) {
+            samlSignature.setX509Certificate(signingCertificate);
+        }
+
+        samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
+    }
+
+    protected void signAssertion(Document samlDocument) throws ProcessingException {
+        Element originalAssertionElement = org.keycloak.saml.common.util.DocumentUtil.getChildElement(samlDocument.getDocumentElement(), new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()));
+        if (originalAssertionElement == null) return;
+        Node clonedAssertionElement = originalAssertionElement.cloneNode(true);
+        Document temporaryDocument;
+
+        try {
+            temporaryDocument = org.keycloak.saml.common.util.DocumentUtil.createDocument();
+        } catch (ConfigurationException e) {
+            throw new ProcessingException(e);
+        }
+
+        temporaryDocument.adoptNode(clonedAssertionElement);
+        temporaryDocument.appendChild(clonedAssertionElement);
+
+        signDocument(temporaryDocument);
+
+        samlDocument.adoptNode(clonedAssertionElement);
+
+        Element parentNode = (Element) originalAssertionElement.getParentNode();
+
+        parentNode.replaceChild(clonedAssertionElement, originalAssertionElement);
+    }
+
+
+    protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+        String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest);
+
+        CacheControl cacheControl = new CacheControl();
+        cacheControl.setNoCache(true);
+        return Response.ok(str, MediaType.TEXT_HTML_TYPE)
+                       .header("Pragma", "no-cache")
+                       .header("Cache-Control", "no-cache, no-store").build();
+    }
+
+    protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+        byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
+        String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
+
+        return buildHtml(samlResponse, actionUrl, asRequest);
+    }
+
+    protected String buildHtml(String samlResponse, String actionUrl, boolean asRequest) {
+        if (destination == null) {
+            throw SAML2LoginResponseBuilder.logger.nullValueError("Destination is null");
+        }
+
+        StringBuilder builder = new StringBuilder();
+
+        String key = GeneralConstants.SAML_RESPONSE_KEY;
+
+        if (asRequest) {
+            key = GeneralConstants.SAML_REQUEST_KEY;
+        }
+
+        builder.append("<HTML>");
+        builder.append("<HEAD>");
+
+        builder.append("<TITLE>HTTP Post Binding Response (Response)</TITLE>");
+        builder.append("</HEAD>");
+        builder.append("<BODY Onload=\"document.forms[0].submit()\">");
+
+        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + actionUrl + "\">");
+        builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + " VALUE=\"" + samlResponse + "\"/>");
+
+        if (isNotNull(relayState)) {
+            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + RELAY_STATE + "\" " + "VALUE=\"" + escapeAttribute(relayState) + "\"/>");
+        }
+
+        builder.append("<NOSCRIPT>");
+        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>");
+        builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
+        builder.append("</NOSCRIPT>");
+
+        builder.append("</FORM></BODY></HTML>");
+
+        return builder.toString();
+    }
+
+    protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException  {
+        String documentAsString = DocumentUtil.getDocumentAsString(document);
+        logger.debugv("saml docment: {0}", documentAsString);
+        byte[] responseBytes = documentAsString.getBytes("UTF-8");
+
+        return RedirectBindingUtil.deflateBase64URLEncode(responseBytes);
+    }
+
+
+    protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException {
+        UriBuilder builder = UriBuilder.fromUri(redirectUri)
+                .replaceQuery(null)
+                .queryParam(samlParameterName, base64Encoded(document));
+        if (relayState != null) {
+            builder.queryParam(RELAY_STATE, relayState);
+        }
+
+        if (sign) {
+            builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
+            URI uri = builder.build();
+            String rawQuery = uri.getRawQuery();
+            Signature signature = signatureAlgorithm.createSignature();
+            byte[] sig = new byte[0];
+            try {
+                signature.initSign(signingKeyPair.getPrivate());
+                signature.update(rawQuery.getBytes("UTF-8"));
+                sig = signature.sign();
+            } catch (Exception e) {
+                throw new ProcessingException(e);
+            }
+            String encodedSig = RedirectBindingUtil.base64URLEncode(sig);
+            builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
+        }
+        return builder.build();
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
index 79506df..56c94ca 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
@@ -1,363 +1,363 @@
-package org.keycloak.protocol.saml;
-
-import org.jboss.logging.Logger;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
-import org.keycloak.saml.processing.core.saml.v2.util.DocumentUtil;
-import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import javax.ws.rs.core.CacheControl;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.xml.namespace.QName;
-import java.io.IOException;
-import java.net.URI;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.cert.X509Certificate;
-
-import static org.keycloak.util.HtmlUtils.escapeAttribute;
-import static org.keycloak.saml.common.util.StringUtil.isNotNull;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
-    protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder2.class);
-
-    protected KeyPair signingKeyPair;
-    protected X509Certificate signingCertificate;
-    protected boolean sign;
-    protected boolean signAssertions;
-    protected SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA1;
-    protected String relayState;
-    protected int encryptionKeySize = 128;
-    protected PublicKey encryptionPublicKey;
-    protected String encryptionAlgorithm = "AES";
-    protected boolean encrypt;
-
-    public T signDocument() {
-        this.sign = true;
-        return (T)this;
-    }
-
-    public T signAssertions() {
-        this.signAssertions = true;
-        return (T)this;
-    }
-
-    public T signWith(KeyPair keyPair) {
-        this.signingKeyPair = keyPair;
-        return (T)this;
-    }
-
-    public T signWith(PrivateKey privateKey, PublicKey publicKey) {
-        this.signingKeyPair = new KeyPair(publicKey, privateKey);
-        return (T)this;
-    }
-
-    public T signWith(KeyPair keyPair, X509Certificate cert) {
-        this.signingKeyPair = keyPair;
-        this.signingCertificate = cert;
-        return (T)this;
-    }
-
-    public T signWith(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) {
-        this.signingKeyPair = new KeyPair(publicKey, privateKey);
-        this.signingCertificate = cert;
-        return (T)this;
-    }
-
-    public T signatureAlgorithm(SignatureAlgorithm alg) {
-        this.signatureAlgorithm = alg;
-        return (T)this;
-    }
-
-    public T encrypt(PublicKey publicKey) {
-        encrypt = true;
-        encryptionPublicKey = publicKey;
-        return (T)this;
-    }
-
-    public T encryptionAlgorithm(String alg) {
-        this.encryptionAlgorithm = alg;
-        return (T)this;
-    }
-
-    public T encryptionKeySize(int size) {
-        this.encryptionKeySize = size;
-        return (T)this;
-    }
-
-    public T relayState(String relayState) {
-        this.relayState = relayState;
-        return (T)this;
-    }
-
-    public class PostBindingBuilder {
-        protected Document document;
-
-        public PostBindingBuilder(Document document) throws ProcessingException {
-            if (encrypt) encryptDocument(document);
-            this.document = document;
-            if (signAssertions) {
-                signAssertion(document);
-            }
-            if (sign) {
-                signDocument(document);
-            }
-        }
-
-        public String encoded() throws ProcessingException, ConfigurationException, IOException {
-            byte[] responseBytes = DocumentUtil.getDocumentAsString(document).getBytes("UTF-8");
-            return PostBindingUtil.base64Encode(new String(responseBytes));
-        }
-        public Document getDocument() {
-            return document;
-        }
-
-        public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, actionUrl, true);
-        }
-        public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
-            return buildResponse(document, actionUrl, false);
-        }
-    }
-
-
-    public class RedirectBindingBuilder {
-        protected Document document;
-
-        public RedirectBindingBuilder(Document document) throws ProcessingException {
-            if (encrypt) encryptDocument(document);
-            this.document = document;
-            if (signAssertions) {
-                signAssertion(document);
-            }
-        }
-
-        public Document getDocument() {
-            return document;
-        }
-        public URI responseUri(String redirectUri, boolean asRequest) throws ConfigurationException, ProcessingException, IOException {
-            String samlParameterName = GeneralConstants.SAML_RESPONSE_KEY;
-
-            if (asRequest) {
-                samlParameterName = GeneralConstants.SAML_REQUEST_KEY;
-            }
-
-            return generateRedirectUri(samlParameterName, redirectUri, document);
-        }
-        public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException {
-            return response(redirectUri, false);
-        }
-
-        public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException {
-            return response(redirect, true);
-        }
-
-        private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-            URI uri = responseUri(redirectUri, asRequest);
-            if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString());
-            CacheControl cacheControl = new CacheControl();
-            cacheControl.setNoCache(true);
-            return Response.status(302).location(uri)
-                    .header("Pragma", "no-cache")
-                    .header("Cache-Control", "no-cache, no-store").build();
-        }
-
-    }
-
-
-
-    private String getSAMLNSPrefix(Document samlResponseDocument) {
-        Node assertionElement = samlResponseDocument.getDocumentElement()
-                .getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()).item(0);
-
-        if (assertionElement == null) {
-            throw new IllegalStateException("Unable to find assertion in saml response document");
-        }
-
-        return assertionElement.getPrefix();
-    }
-
-    protected void encryptDocument(Document samlDocument) throws ProcessingException {
-        String samlNSPrefix = getSAMLNSPrefix(samlDocument);
-
-        try {
-            QName encryptedAssertionElementQName = new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
-                    JBossSAMLConstants.ENCRYPTED_ASSERTION.get(), samlNSPrefix);
-
-            byte[] secret = SamlProtocolUtils.createRandomSecret(encryptionKeySize / 8);
-            SecretKey secretKey = new SecretKeySpec(secret, encryptionAlgorithm);
-
-            // encrypt the Assertion element and replace it with a EncryptedAssertion element.
-            XMLEncryptionUtil.encryptElement(new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
-                            JBossSAMLConstants.ASSERTION.get(), samlNSPrefix), samlDocument, encryptionPublicKey,
-                    secretKey, encryptionKeySize, encryptedAssertionElementQName, true);
-        } catch (Exception e) {
-            throw new ProcessingException("failed to encrypt", e);
-        }
-
-    }
-
-    protected void signDocument(Document samlDocument) throws ProcessingException {
-        String signatureMethod = signatureAlgorithm.getXmlSignatureMethod();
-        String signatureDigestMethod = signatureAlgorithm.getXmlSignatureDigestMethod();
-        SAML2Signature samlSignature = new SAML2Signature();
-
-        if (signatureMethod != null) {
-            samlSignature.setSignatureMethod(signatureMethod);
-        }
-
-        if (signatureDigestMethod != null) {
-            samlSignature.setDigestMethod(signatureDigestMethod);
-        }
-
-        Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument);
-
-        samlSignature.setNextSibling(nextSibling);
-
-        if (signingCertificate != null) {
-            samlSignature.setX509Certificate(signingCertificate);
-        }
-
-        samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
-    }
-
-    protected void signAssertion(Document samlDocument) throws ProcessingException {
-        Element originalAssertionElement = org.keycloak.saml.common.util.DocumentUtil.getChildElement(samlDocument.getDocumentElement(), new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()));
-        if (originalAssertionElement == null) return;
-        Node clonedAssertionElement = originalAssertionElement.cloneNode(true);
-        Document temporaryDocument;
-
-        try {
-            temporaryDocument = org.keycloak.saml.common.util.DocumentUtil.createDocument();
-        } catch (ConfigurationException e) {
-            throw new ProcessingException(e);
-        }
-
-        temporaryDocument.adoptNode(clonedAssertionElement);
-        temporaryDocument.appendChild(clonedAssertionElement);
-
-        signDocument(temporaryDocument);
-
-        samlDocument.adoptNode(clonedAssertionElement);
-
-        Element parentNode = (Element) originalAssertionElement.getParentNode();
-
-        parentNode.replaceChild(clonedAssertionElement, originalAssertionElement);
-    }
-
-
-    protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-        String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest);
-
-        CacheControl cacheControl = new CacheControl();
-        cacheControl.setNoCache(true);
-        return Response.ok(str, MediaType.TEXT_HTML_TYPE)
-                       .header("Pragma", "no-cache")
-                       .header("Cache-Control", "no-cache, no-store").build();
-    }
-
-    protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
-        byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
-        String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
-
-        return buildHtml(samlResponse, actionUrl, asRequest);
-    }
-
-    protected String buildHtml(String samlResponse, String actionUrl, boolean asRequest) {
-        StringBuilder builder = new StringBuilder();
-
-        String key = GeneralConstants.SAML_RESPONSE_KEY;
-
-        if (asRequest) {
-            key = GeneralConstants.SAML_REQUEST_KEY;
-        }
-
-        builder.append("<HTML>");
-        builder.append("<HEAD>");
-
-        builder.append("<TITLE>HTTP Post Binding Response (Response)</TITLE>");
-        builder.append("</HEAD>");
-        builder.append("<BODY Onload=\"document.forms[0].submit()\">");
-
-        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + actionUrl + "\">");
-        builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + " VALUE=\"" + samlResponse + "\"/>");
-
-        if (isNotNull(relayState)) {
-            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"RelayState\" " + "VALUE=\"" + escapeAttribute(relayState) + "\"/>");
-        }
-
-        builder.append("<NOSCRIPT>");
-        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>");
-        builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
-        builder.append("</NOSCRIPT>");
-
-        builder.append("</FORM></BODY></HTML>");
-
-        return builder.toString();
-    }
-
-    protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException  {
-        String documentAsString = DocumentUtil.getDocumentAsString(document);
-        logger.debugv("saml docment: {0}", documentAsString);
-        byte[] responseBytes = documentAsString.getBytes("UTF-8");
-
-        return RedirectBindingUtil.deflateBase64URLEncode(responseBytes);
-    }
-
-
-    protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException {
-        UriBuilder builder = UriBuilder.fromUri(redirectUri)
-                .replaceQuery(null)
-                .queryParam(samlParameterName, base64Encoded(document));
-        if (relayState != null) {
-            builder.queryParam("RelayState", relayState);
-        }
-
-        if (sign) {
-            builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
-            URI uri = builder.build();
-            String rawQuery = uri.getRawQuery();
-            Signature signature = signatureAlgorithm.createSignature();
-            byte[] sig = new byte[0];
-            try {
-                signature.initSign(signingKeyPair.getPrivate());
-                signature.update(rawQuery.getBytes("UTF-8"));
-                sig = signature.sign();
-            } catch (Exception e) {
-                throw new ProcessingException(e);
-            }
-            String encodedSig = RedirectBindingUtil.base64URLEncode(sig);
-            builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
-        }
-        return builder.build();
-    }
-
-    public RedirectBindingBuilder redirectBinding(Document document) throws ProcessingException  {
-        return new RedirectBindingBuilder(document);
-    }
-
-    public PostBindingBuilder postBinding(Document document) throws ProcessingException  {
-        return new PostBindingBuilder(document);
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.jboss.logging.Logger;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
+import org.keycloak.saml.processing.core.saml.v2.util.DocumentUtil;
+import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.net.URI;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
+
+import static org.keycloak.util.HtmlUtils.escapeAttribute;
+import static org.keycloak.saml.common.util.StringUtil.isNotNull;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
+    protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder2.class);
+
+    protected KeyPair signingKeyPair;
+    protected X509Certificate signingCertificate;
+    protected boolean sign;
+    protected boolean signAssertions;
+    protected SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA1;
+    protected String relayState;
+    protected int encryptionKeySize = 128;
+    protected PublicKey encryptionPublicKey;
+    protected String encryptionAlgorithm = "AES";
+    protected boolean encrypt;
+
+    public T signDocument() {
+        this.sign = true;
+        return (T)this;
+    }
+
+    public T signAssertions() {
+        this.signAssertions = true;
+        return (T)this;
+    }
+
+    public T signWith(KeyPair keyPair) {
+        this.signingKeyPair = keyPair;
+        return (T)this;
+    }
+
+    public T signWith(PrivateKey privateKey, PublicKey publicKey) {
+        this.signingKeyPair = new KeyPair(publicKey, privateKey);
+        return (T)this;
+    }
+
+    public T signWith(KeyPair keyPair, X509Certificate cert) {
+        this.signingKeyPair = keyPair;
+        this.signingCertificate = cert;
+        return (T)this;
+    }
+
+    public T signWith(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) {
+        this.signingKeyPair = new KeyPair(publicKey, privateKey);
+        this.signingCertificate = cert;
+        return (T)this;
+    }
+
+    public T signatureAlgorithm(SignatureAlgorithm alg) {
+        this.signatureAlgorithm = alg;
+        return (T)this;
+    }
+
+    public T encrypt(PublicKey publicKey) {
+        encrypt = true;
+        encryptionPublicKey = publicKey;
+        return (T)this;
+    }
+
+    public T encryptionAlgorithm(String alg) {
+        this.encryptionAlgorithm = alg;
+        return (T)this;
+    }
+
+    public T encryptionKeySize(int size) {
+        this.encryptionKeySize = size;
+        return (T)this;
+    }
+
+    public T relayState(String relayState) {
+        this.relayState = relayState;
+        return (T)this;
+    }
+
+    public class PostBindingBuilder {
+        protected Document document;
+
+        public PostBindingBuilder(Document document) throws ProcessingException {
+            if (encrypt) encryptDocument(document);
+            this.document = document;
+            if (signAssertions) {
+                signAssertion(document);
+            }
+            if (sign) {
+                signDocument(document);
+            }
+        }
+
+        public String encoded() throws ProcessingException, ConfigurationException, IOException {
+            byte[] responseBytes = DocumentUtil.getDocumentAsString(document).getBytes("UTF-8");
+            return PostBindingUtil.base64Encode(new String(responseBytes));
+        }
+        public Document getDocument() {
+            return document;
+        }
+
+        public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, actionUrl, true);
+        }
+        public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+            return buildResponse(document, actionUrl, false);
+        }
+    }
+
+
+    public class RedirectBindingBuilder {
+        protected Document document;
+
+        public RedirectBindingBuilder(Document document) throws ProcessingException {
+            if (encrypt) encryptDocument(document);
+            this.document = document;
+            if (signAssertions) {
+                signAssertion(document);
+            }
+        }
+
+        public Document getDocument() {
+            return document;
+        }
+        public URI responseUri(String redirectUri, boolean asRequest) throws ConfigurationException, ProcessingException, IOException {
+            String samlParameterName = GeneralConstants.SAML_RESPONSE_KEY;
+
+            if (asRequest) {
+                samlParameterName = GeneralConstants.SAML_REQUEST_KEY;
+            }
+
+            return generateRedirectUri(samlParameterName, redirectUri, document);
+        }
+        public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException {
+            return response(redirectUri, false);
+        }
+
+        public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException {
+            return response(redirect, true);
+        }
+
+        private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+            URI uri = responseUri(redirectUri, asRequest);
+            if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString());
+            CacheControl cacheControl = new CacheControl();
+            cacheControl.setNoCache(true);
+            return Response.status(302).location(uri)
+                    .header("Pragma", "no-cache")
+                    .header("Cache-Control", "no-cache, no-store").build();
+        }
+
+    }
+
+
+
+    private String getSAMLNSPrefix(Document samlResponseDocument) {
+        Node assertionElement = samlResponseDocument.getDocumentElement()
+                .getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()).item(0);
+
+        if (assertionElement == null) {
+            throw new IllegalStateException("Unable to find assertion in saml response document");
+        }
+
+        return assertionElement.getPrefix();
+    }
+
+    protected void encryptDocument(Document samlDocument) throws ProcessingException {
+        String samlNSPrefix = getSAMLNSPrefix(samlDocument);
+
+        try {
+            QName encryptedAssertionElementQName = new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
+                    JBossSAMLConstants.ENCRYPTED_ASSERTION.get(), samlNSPrefix);
+
+            byte[] secret = SamlProtocolUtils.createRandomSecret(encryptionKeySize / 8);
+            SecretKey secretKey = new SecretKeySpec(secret, encryptionAlgorithm);
+
+            // encrypt the Assertion element and replace it with a EncryptedAssertion element.
+            XMLEncryptionUtil.encryptElement(new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
+                            JBossSAMLConstants.ASSERTION.get(), samlNSPrefix), samlDocument, encryptionPublicKey,
+                    secretKey, encryptionKeySize, encryptedAssertionElementQName, true);
+        } catch (Exception e) {
+            throw new ProcessingException("failed to encrypt", e);
+        }
+
+    }
+
+    protected void signDocument(Document samlDocument) throws ProcessingException {
+        String signatureMethod = signatureAlgorithm.getXmlSignatureMethod();
+        String signatureDigestMethod = signatureAlgorithm.getXmlSignatureDigestMethod();
+        SAML2Signature samlSignature = new SAML2Signature();
+
+        if (signatureMethod != null) {
+            samlSignature.setSignatureMethod(signatureMethod);
+        }
+
+        if (signatureDigestMethod != null) {
+            samlSignature.setDigestMethod(signatureDigestMethod);
+        }
+
+        Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument);
+
+        samlSignature.setNextSibling(nextSibling);
+
+        if (signingCertificate != null) {
+            samlSignature.setX509Certificate(signingCertificate);
+        }
+
+        samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
+    }
+
+    protected void signAssertion(Document samlDocument) throws ProcessingException {
+        Element originalAssertionElement = org.keycloak.saml.common.util.DocumentUtil.getChildElement(samlDocument.getDocumentElement(), new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()));
+        if (originalAssertionElement == null) return;
+        Node clonedAssertionElement = originalAssertionElement.cloneNode(true);
+        Document temporaryDocument;
+
+        try {
+            temporaryDocument = org.keycloak.saml.common.util.DocumentUtil.createDocument();
+        } catch (ConfigurationException e) {
+            throw new ProcessingException(e);
+        }
+
+        temporaryDocument.adoptNode(clonedAssertionElement);
+        temporaryDocument.appendChild(clonedAssertionElement);
+
+        signDocument(temporaryDocument);
+
+        samlDocument.adoptNode(clonedAssertionElement);
+
+        Element parentNode = (Element) originalAssertionElement.getParentNode();
+
+        parentNode.replaceChild(clonedAssertionElement, originalAssertionElement);
+    }
+
+
+    protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+        String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest);
+
+        CacheControl cacheControl = new CacheControl();
+        cacheControl.setNoCache(true);
+        return Response.ok(str, MediaType.TEXT_HTML_TYPE)
+                       .header("Pragma", "no-cache")
+                       .header("Cache-Control", "no-cache, no-store").build();
+    }
+
+    protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException {
+        byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
+        String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
+
+        return buildHtml(samlResponse, actionUrl, asRequest);
+    }
+
+    protected String buildHtml(String samlResponse, String actionUrl, boolean asRequest) {
+        StringBuilder builder = new StringBuilder();
+
+        String key = GeneralConstants.SAML_RESPONSE_KEY;
+
+        if (asRequest) {
+            key = GeneralConstants.SAML_REQUEST_KEY;
+        }
+
+        builder.append("<HTML>");
+        builder.append("<HEAD>");
+
+        builder.append("<TITLE>HTTP Post Binding Response (Response)</TITLE>");
+        builder.append("</HEAD>");
+        builder.append("<BODY Onload=\"document.forms[0].submit()\">");
+
+        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + actionUrl + "\">");
+        builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + " VALUE=\"" + samlResponse + "\"/>");
+
+        if (isNotNull(relayState)) {
+            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"RelayState\" " + "VALUE=\"" + escapeAttribute(relayState) + "\"/>");
+        }
+
+        builder.append("<NOSCRIPT>");
+        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>");
+        builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
+        builder.append("</NOSCRIPT>");
+
+        builder.append("</FORM></BODY></HTML>");
+
+        return builder.toString();
+    }
+
+    protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException  {
+        String documentAsString = DocumentUtil.getDocumentAsString(document);
+        logger.debugv("saml docment: {0}", documentAsString);
+        byte[] responseBytes = documentAsString.getBytes("UTF-8");
+
+        return RedirectBindingUtil.deflateBase64URLEncode(responseBytes);
+    }
+
+
+    protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException {
+        UriBuilder builder = UriBuilder.fromUri(redirectUri)
+                .replaceQuery(null)
+                .queryParam(samlParameterName, base64Encoded(document));
+        if (relayState != null) {
+            builder.queryParam("RelayState", relayState);
+        }
+
+        if (sign) {
+            builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm());
+            URI uri = builder.build();
+            String rawQuery = uri.getRawQuery();
+            Signature signature = signatureAlgorithm.createSignature();
+            byte[] sig = new byte[0];
+            try {
+                signature.initSign(signingKeyPair.getPrivate());
+                signature.update(rawQuery.getBytes("UTF-8"));
+                sig = signature.sign();
+            } catch (Exception e) {
+                throw new ProcessingException(e);
+            }
+            String encodedSig = RedirectBindingUtil.base64URLEncode(sig);
+            builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
+        }
+        return builder.build();
+    }
+
+    public RedirectBindingBuilder redirectBinding(Document document) throws ProcessingException  {
+        return new RedirectBindingBuilder(document);
+    }
+
+    public PostBindingBuilder postBinding(Document document) throws ProcessingException  {
+        return new PostBindingBuilder(document);
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java
index e35c537..750f70c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java
@@ -1,69 +1,69 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
-import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
-import org.keycloak.saml.processing.core.saml.v2.factories.JBossSAMLAuthnResponseFactory;
-import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder;
-import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder;
-import org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.w3c.dom.Document;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAML2ErrorResponseBuilder extends SAML2BindingBuilder<SAML2ErrorResponseBuilder> {
-
-    protected String status;
-
-    public SAML2ErrorResponseBuilder status(String status) {
-        this.status = status;
-        return this;
-    }
-
-    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException {
-        Document samlResponseDocument = buildDocument();
-        return new RedirectBindingBuilder(samlResponseDocument);
-
-    }
-
-    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException {
-        Document samlResponseDocument = buildDocument();
-        return new PostBindingBuilder(samlResponseDocument);
-
-    }
-
-
-    public Document buildDocument() throws ProcessingException {
-        Document samlResponse = null;
-        ResponseType responseType = null;
-
-        SAML2Response saml2Response = new SAML2Response();
-
-        // Create a response type
-        String id = IDGenerator.create("ID_");
-
-        IssuerInfoHolder issuerHolder = new IssuerInfoHolder(issuer);
-        issuerHolder.setStatusCode(status);
-
-        IDPInfoHolder idp = new IDPInfoHolder();
-        idp.setNameIDFormatValue(null);
-        idp.setNameIDFormat(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get());
-
-        SPInfoHolder sp = new SPInfoHolder();
-        sp.setResponseDestinationURI(destination);
-
-        responseType = saml2Response.createResponseType(id);
-        responseType.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status));
-        responseType.setDestination(destination);
-
-        if (encrypt) encryptDocument(samlResponse);
-        return samlResponse;
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.factories.JBossSAMLAuthnResponseFactory;
+import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2ErrorResponseBuilder extends SAML2BindingBuilder<SAML2ErrorResponseBuilder> {
+
+    protected String status;
+
+    public SAML2ErrorResponseBuilder status(String status) {
+        this.status = status;
+        return this;
+    }
+
+    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException {
+        Document samlResponseDocument = buildDocument();
+        return new RedirectBindingBuilder(samlResponseDocument);
+
+    }
+
+    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException {
+        Document samlResponseDocument = buildDocument();
+        return new PostBindingBuilder(samlResponseDocument);
+
+    }
+
+
+    public Document buildDocument() throws ProcessingException {
+        Document samlResponse = null;
+        ResponseType responseType = null;
+
+        SAML2Response saml2Response = new SAML2Response();
+
+        // Create a response type
+        String id = IDGenerator.create("ID_");
+
+        IssuerInfoHolder issuerHolder = new IssuerInfoHolder(issuer);
+        issuerHolder.setStatusCode(status);
+
+        IDPInfoHolder idp = new IDPInfoHolder();
+        idp.setNameIDFormatValue(null);
+        idp.setNameIDFormat(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get());
+
+        SPInfoHolder sp = new SPInfoHolder();
+        sp.setResponseDestinationURI(destination);
+
+        responseType = saml2Response.createResponseType(id);
+        responseType.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status));
+        responseType.setDestination(destination);
+
+        if (encrypt) encryptDocument(samlResponse);
+        return samlResponse;
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
index 9cbfa44..c59f56c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
@@ -1,87 +1,87 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ParsingException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
-import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
-import org.keycloak.dom.saml.v2.assertion.NameIDType;
-import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
-import org.w3c.dom.Document;
-
-import java.net.URI;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder<SAML2LogoutRequestBuilder> {
-    protected String userPrincipal;
-    protected String userPrincipalFormat;
-    protected String sessionIndex;
-    protected long assertionExpiration;
-
-    /**
-     * Length of time in seconds the assertion is valid for
-     * See SAML core specification 2.5.1.2 NotOnOrAfter
-     *
-     * @param assertionExpiration Number of seconds the assertion should be valid
-     * @return
-     */
-    public SAML2LogoutRequestBuilder assertionExpiration(int assertionExpiration) {
-        this.assertionExpiration = assertionExpiration;
-        return this;
-    }
-
-
-    public SAML2LogoutRequestBuilder userPrincipal(String nameID, String nameIDformat) {
-        this.userPrincipal = nameID;
-        this.userPrincipalFormat = nameIDformat;
-        return this;
-    }
-
-    public SAML2LogoutRequestBuilder sessionIndex(String index) {
-        this.sessionIndex = index;
-        return this;
-    }
-
-    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException, ParsingException {
-        Document samlResponseDocument = buildDocument();
-        return new RedirectBindingBuilder(samlResponseDocument);
-
-    }
-
-    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException, ParsingException {
-        Document samlResponseDocument = buildDocument();
-        return new PostBindingBuilder(samlResponseDocument);
-
-    }
-    public Document buildDocument() throws ProcessingException, ConfigurationException, ParsingException {
-        Document document = new SAML2Request().convert(createLogoutRequest());
-        if (encrypt) encryptDocument(document);
-        return document;
-    }
-
-    private LogoutRequestType createLogoutRequest() throws ConfigurationException {
-        LogoutRequestType lort = new SAML2Request().createLogoutRequest(issuer);
-
-        NameIDType nameID = new NameIDType();
-        nameID.setValue(userPrincipal);
-        //Deal with NameID Format
-        String nameIDFormat = userPrincipalFormat;
-        nameID.setFormat(URI.create(nameIDFormat));
-        lort.setNameID(nameID);
-
-        if (issuer != null) {
-            NameIDType issuerID = new NameIDType();
-            issuerID.setValue(issuer);
-            lort.setIssuer(issuerID);
-        }
-        if (sessionIndex != null) lort.addSessionIndex(sessionIndex);
-
-
-        if (assertionExpiration > 0) lort.setNotOnOrAfter(XMLTimeUtil.add(lort.getIssueInstant(), assertionExpiration * 1000));
-        lort.setDestination(URI.create(destination));
-        return lort;
-    }
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.w3c.dom.Document;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder<SAML2LogoutRequestBuilder> {
+    protected String userPrincipal;
+    protected String userPrincipalFormat;
+    protected String sessionIndex;
+    protected long assertionExpiration;
+
+    /**
+     * Length of time in seconds the assertion is valid for
+     * See SAML core specification 2.5.1.2 NotOnOrAfter
+     *
+     * @param assertionExpiration Number of seconds the assertion should be valid
+     * @return
+     */
+    public SAML2LogoutRequestBuilder assertionExpiration(int assertionExpiration) {
+        this.assertionExpiration = assertionExpiration;
+        return this;
+    }
+
+
+    public SAML2LogoutRequestBuilder userPrincipal(String nameID, String nameIDformat) {
+        this.userPrincipal = nameID;
+        this.userPrincipalFormat = nameIDformat;
+        return this;
+    }
+
+    public SAML2LogoutRequestBuilder sessionIndex(String index) {
+        this.sessionIndex = index;
+        return this;
+    }
+
+    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException, ParsingException {
+        Document samlResponseDocument = buildDocument();
+        return new RedirectBindingBuilder(samlResponseDocument);
+
+    }
+
+    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException, ParsingException {
+        Document samlResponseDocument = buildDocument();
+        return new PostBindingBuilder(samlResponseDocument);
+
+    }
+    public Document buildDocument() throws ProcessingException, ConfigurationException, ParsingException {
+        Document document = new SAML2Request().convert(createLogoutRequest());
+        if (encrypt) encryptDocument(document);
+        return document;
+    }
+
+    private LogoutRequestType createLogoutRequest() throws ConfigurationException {
+        LogoutRequestType lort = new SAML2Request().createLogoutRequest(issuer);
+
+        NameIDType nameID = new NameIDType();
+        nameID.setValue(userPrincipal);
+        //Deal with NameID Format
+        String nameIDFormat = userPrincipalFormat;
+        nameID.setFormat(URI.create(nameIDFormat));
+        lort.setNameID(nameID);
+
+        if (issuer != null) {
+            NameIDType issuerID = new NameIDType();
+            issuerID.setValue(issuer);
+            lort.setIssuer(issuerID);
+        }
+        if (sessionIndex != null) lort.addSessionIndex(sessionIndex);
+
+
+        if (assertionExpiration > 0) lort.setNotOnOrAfter(XMLTimeUtil.add(lort.getIssueInstant(), assertionExpiration * 1000));
+        lort.setDestination(URI.create(destination));
+        return lort;
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java
index f172910..2d65716 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java
@@ -1,76 +1,76 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ParsingException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
-import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
-import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
-import org.keycloak.dom.saml.v2.assertion.NameIDType;
-import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
-import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
-import org.keycloak.dom.saml.v2.protocol.StatusType;
-import org.w3c.dom.Document;
-
-import java.net.URI;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAML2LogoutResponseBuilder extends SAML2BindingBuilder<SAML2LogoutResponseBuilder> {
-
-    protected String logoutRequestID;
-
-    public SAML2LogoutResponseBuilder logoutRequestID(String logoutRequestID) {
-        this.logoutRequestID = logoutRequestID;
-        return this;
-    }
-
-    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException {
-        Document samlResponseDocument = buildDocument();
-        return new RedirectBindingBuilder(samlResponseDocument);
-
-    }
-
-    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException {
-        Document samlResponseDocument = buildDocument();
-        return new PostBindingBuilder(samlResponseDocument);
-
-    }
-
-
-    public Document buildDocument() throws ProcessingException {
-        Document samlResponse = null;
-        try {
-            StatusResponseType statusResponse = new StatusResponseType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
-
-            // Status
-            StatusType statusType = new StatusType();
-            StatusCodeType statusCodeType = new StatusCodeType();
-            statusCodeType.setValue(URI.create(JBossSAMLURIConstants.STATUS_SUCCESS.get()));
-            statusType.setStatusCode(statusCodeType);
-
-            statusResponse.setStatus(statusType);
-            statusResponse.setInResponseTo(logoutRequestID);
-            NameIDType issuer = new NameIDType();
-            issuer.setValue(this.issuer);
-
-            statusResponse.setIssuer(issuer);
-            statusResponse.setDestination(destination);
-
-            SAML2Response saml2Response = new SAML2Response();
-            samlResponse = saml2Response.convert(statusResponse);
-        } catch (ConfigurationException e) {
-            throw new ProcessingException(e);
-        } catch (ParsingException e) {
-            throw new ProcessingException(e);
-        }
-        if (encrypt) encryptDocument(samlResponse);
-        return samlResponse;
-
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+import org.keycloak.dom.saml.v2.protocol.StatusType;
+import org.w3c.dom.Document;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2LogoutResponseBuilder extends SAML2BindingBuilder<SAML2LogoutResponseBuilder> {
+
+    protected String logoutRequestID;
+
+    public SAML2LogoutResponseBuilder logoutRequestID(String logoutRequestID) {
+        this.logoutRequestID = logoutRequestID;
+        return this;
+    }
+
+    public RedirectBindingBuilder redirectBinding()  throws ConfigurationException, ProcessingException {
+        Document samlResponseDocument = buildDocument();
+        return new RedirectBindingBuilder(samlResponseDocument);
+
+    }
+
+    public PostBindingBuilder postBinding()  throws ConfigurationException, ProcessingException {
+        Document samlResponseDocument = buildDocument();
+        return new PostBindingBuilder(samlResponseDocument);
+
+    }
+
+
+    public Document buildDocument() throws ProcessingException {
+        Document samlResponse = null;
+        try {
+            StatusResponseType statusResponse = new StatusResponseType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
+
+            // Status
+            StatusType statusType = new StatusType();
+            StatusCodeType statusCodeType = new StatusCodeType();
+            statusCodeType.setValue(URI.create(JBossSAMLURIConstants.STATUS_SUCCESS.get()));
+            statusType.setStatusCode(statusCodeType);
+
+            statusResponse.setStatus(statusType);
+            statusResponse.setInResponseTo(logoutRequestID);
+            NameIDType issuer = new NameIDType();
+            issuer.setValue(this.issuer);
+
+            statusResponse.setIssuer(issuer);
+            statusResponse.setDestination(destination);
+
+            SAML2Response saml2Response = new SAML2Response();
+            samlResponse = saml2Response.convert(statusResponse);
+        } catch (ConfigurationException e) {
+            throw new ProcessingException(e);
+        } catch (ParsingException e) {
+            throw new ProcessingException(e);
+        }
+        if (encrypt) encryptDocument(samlResponse);
+        return samlResponse;
+
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 15ff6f2..6746d9d 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -1,620 +1,620 @@
-package org.keycloak.protocol.saml;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-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.connections.httpclient.HttpClientProvider;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper;
-import org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper;
-import org.keycloak.protocol.saml.mappers.SAMLRoleListMapper;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ParsingException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.managers.ResourceAdminManager;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
-import org.keycloak.services.ErrorPage;
-import org.w3c.dom.Document;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SamlProtocol implements LoginProtocol {
-    protected static final Logger logger = Logger.getLogger(SamlProtocol.class);
-
-
-    public static final String ATTRIBUTE_TRUE_VALUE = "true";
-    public static final String ATTRIBUTE_FALSE_VALUE = "false";
-    public static final String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE;
-    public static final String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE;
-    public static final String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature";
-    public static final String SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE = "saml_assertion_consumer_url_post";
-    public static final String SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE = "saml_assertion_consumer_url_redirect";
-    public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE = "saml_single_logout_service_url_post";
-    public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE = "saml_single_logout_service_url_redirect";
-    public static final String SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE = "saml_force_name_id_format";
-    public static final String SAML_NAME_ID_FORMAT_ATTRIBUTE = "saml_name_id_format";
-    public static final String LOGIN_PROTOCOL = "saml";
-    public static final String SAML_BINDING = "saml_binding";
-    public static final String SAML_IDP_INITIATED_LOGIN = "saml_idp_initiated_login";
-    public static final String SAML_POST_BINDING = "post";
-    public static final String SAML_REDIRECT_BINDING = "get";
-    public static final String SAML_SERVER_SIGNATURE = "saml.server.signature";
-    public static final String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature";
-    public static final String SAML_AUTHNSTATEMENT = "saml.authnstatement";
-    public static final String SAML_SIGNATURE_ALGORITHM = "saml.signature.algorithm";
-    public static final String SAML_ENCRYPT = "saml.encrypt";
-    public static final String SAML_FORCE_POST_BINDING = "saml.force.post.binding";
-    public static final String SAML_REQUEST_ID = "SAML_REQUEST_ID";
-    public static final String SAML_LOGOUT_BINDING = "saml.logout.binding";
-    public static final String SAML_LOGOUT_REQUEST_ID = "SAML_LOGOUT_REQUEST_ID";
-    public static final String SAML_LOGOUT_RELAY_STATE = "SAML_LOGOUT_RELAY_STATE";
-    public static final String SAML_LOGOUT_BINDING_URI = "SAML_LOGOUT_BINDING_URI";
-    public static final String SAML_LOGOUT_SIGNATURE_ALGORITHM = "saml.logout.signature.algorithm";
-    public static final String SAML_NAME_ID = "SAML_NAME_ID";
-    public static final String SAML_NAME_ID_FORMAT = "SAML_NAME_ID_FORMAT";
-    public static final String SAML_DEFAULT_NAMEID_FORMAT = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
-    public static final String SAML_PERSISTENT_NAME_ID_FOR = "saml.persistent.name.id.for";
-    public static final String SAML_IDP_INITIATED_SSO_RELAY_STATE = "saml_idp_initiated_sso_relay_state";
-    public static final String SAML_IDP_INITIATED_SSO_URL_NAME = "saml_idp_initiated_sso_url_name";
-
-    protected KeycloakSession session;
-
-    protected RealmModel realm;
-
-    protected UriInfo uriInfo;
-
-    protected HttpHeaders headers;
-
-    protected EventBuilder event;
-
-
-    @Override
-    public SamlProtocol setSession(KeycloakSession session) {
-        this.session = session;
-        return this;
-    }
-
-    @Override
-    public SamlProtocol setRealm(RealmModel realm) {
-        this.realm = realm;
-        return this;
-    }
-
-    @Override
-    public SamlProtocol setUriInfo(UriInfo uriInfo) {
-        this.uriInfo = uriInfo;
-        return this;
-    }
-
-    @Override
-    public SamlProtocol setHttpHeaders(HttpHeaders headers){
-        this.headers = headers;
-        return this;
-    }
-
-    @Override
-    public SamlProtocol setEventBuilder(EventBuilder event) {
-        this.event = event;
-        return this;
-    }
-
-
-    @Override
-    public Response cancelLogin(ClientSessionModel clientSession) {
-        if ("true".equals(clientSession.getClient().getAttribute(SAML_IDP_INITIATED_LOGIN))) {
-            UriBuilder builder = RealmsResource.protocolUrl(uriInfo).path(SamlService.class, "idpInitiatedSSO");
-            Map<String, String> params = new HashMap<>();
-            params.put("realm", realm.getName());
-            params.put("protocol", LOGIN_PROTOCOL);
-            params.put("client", clientSession.getClient().getAttribute(SAML_IDP_INITIATED_SSO_URL_NAME));
-            session.sessions().removeClientSession(realm, clientSession);
-            URI redirect = builder.buildFromMap(params);
-            return Response.status(302).location(redirect).build();
-        } else {
-            session.sessions().removeClientSession(realm, clientSession);
-            return getErrorResponse(clientSession, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get());
-        }
-    }
-
-    protected String getResponseIssuer(RealmModel realm) {
-        return RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString();
-    }
-
-    protected Response getErrorResponse(ClientSessionModel clientSession, String status) {
-        SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder()
-                .relayState(clientSession.getNote(GeneralConstants.RELAY_STATE))
-                .destination(clientSession.getRedirectUri())
-                .issuer(getResponseIssuer(realm))
-                .status(status);
-      try {
-          if (isPostBinding(clientSession)) {
-              return builder.postBinding().response();
-          } else {
-              return builder.redirectBinding().response();
-          }
-        } catch (Exception e) {
-            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
-        }
-    }
-
-    protected boolean isPostBinding(ClientSessionModel clientSession) {
-        ClientModel client = clientSession.getClient();
-        return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || forcePostBinding(client);
-    }
-
-    public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) {
-        String note = session.getNote(SamlProtocol.SAML_LOGOUT_BINDING);
-        return SamlProtocol.SAML_POST_BINDING.equals(note);
-    }
-
-
-
-    protected boolean isLogoutPostBindingForClient(ClientSessionModel clientSession) {
-        ClientModel client = clientSession.getClient();
-        String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
-        String logoutRedirectUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
-
-        if (logoutPostUrl == null) {
-            // if we don't have a redirect uri either, return true and default to the admin url + POST binding
-            if (logoutRedirectUrl == null) return true;
-            return false;
-        }
-
-        if (forcePostBinding(client)) {
-            return true; // configured to force a post binding and post binding logout url is not null
-        }
-
-        String bindingType = clientSession.getNote(SAML_BINDING);
-
-        // if the login binding was POST, return true
-        if (SAML_POST_BINDING.equals(bindingType)) return true;
-
-        if (logoutRedirectUrl == null) return true; // we don't have a redirect binding url, so use post binding
-
-        return false;  // redirect binding
-
-    }
-
-    public static boolean forcePostBinding(ClientModel client) {
-        return "true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING));
-    }
-
-    protected String getNameIdFormat(ClientSessionModel clientSession) {
-        String nameIdFormat = clientSession.getNote(GeneralConstants.NAMEID_FORMAT);
-        ClientModel client = clientSession.getClient();
-        boolean forceFormat = forceNameIdFormat(client);
-        String configuredNameIdFormat = client.getAttribute(SAML_NAME_ID_FORMAT_ATTRIBUTE);
-        if ((nameIdFormat == null || forceFormat) && configuredNameIdFormat != null) {
-            if (configuredNameIdFormat.equals("email")) {
-                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get();
-            } else if (configuredNameIdFormat.equals("persistent")) {
-                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
-            } else if (configuredNameIdFormat.equals("transient")) {
-                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get();
-            } else if (configuredNameIdFormat.equals("username")) {
-                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
-            } else {
-                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
-            }
-        }
-        if(nameIdFormat == null) return SAML_DEFAULT_NAMEID_FORMAT;
-        return nameIdFormat;
-    }
-
-    public static boolean forceNameIdFormat(ClientModel client) {
-        return "true".equals(client.getAttribute(SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
-    }
-
-    protected String getNameId(String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
-        if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
-            return userSession.getUser().getEmail();
-        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get())) {
-            // "G-" stands for "generated" Add this for the slight possibility of collisions.
-            return "G-" + UUID.randomUUID().toString();
-        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get())) {
-            // generate a persistent user id specifically for each client.
-            UserModel user = userSession.getUser();
-            String name = SAML_PERSISTENT_NAME_ID_FOR + "." + clientSession.getClient().getClientId();
-            String samlPersistentId = user.getFirstAttribute(name);
-            if (samlPersistentId != null) return samlPersistentId;
-            // "G-" stands for "generated"
-            samlPersistentId = "G-" + UUID.randomUUID().toString();
-            user.setSingleAttribute(name, samlPersistentId);
-            return samlPersistentId;
-        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())){
-            // TODO: Support for persistent NameID (pseudo-random identifier persisted in user object)
-            return userSession.getUser().getUsername();
-        } else {
-            return userSession.getUser().getUsername();
-        }
-    }
-
-    @Override
-    public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
-        ClientSessionModel clientSession = accessCode.getClientSession();
-        ClientModel client = clientSession.getClient();
-        String requestID = clientSession.getNote(SAML_REQUEST_ID);
-        String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE);
-        String redirectUri = clientSession.getRedirectUri();
-        String responseIssuer = getResponseIssuer(realm);
-        String nameIdFormat = getNameIdFormat(clientSession);
-        String nameId = getNameId(nameIdFormat, clientSession, userSession);
-
-        // save NAME_ID and format in clientSession as they may be persistent or transient or email and not username
-        // we'll need to send this back on a logout
-        clientSession.setNote(SAML_NAME_ID, nameId);
-        clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
-
-        SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
-        builder.requestID(requestID)
-               .destination(redirectUri)
-               .issuer(responseIssuer)
-               .assertionExpiration(realm.getAccessCodeLifespan())
-               .subjectExpiration(realm.getAccessTokenLifespan())
-               .sessionIndex(clientSession.getId())
-               .requestIssuer(clientSession.getClient().getClientId())
-               .nameIdentifier(nameIdFormat, nameId)
-               .authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
-        if (!includeAuthnStatement(client)) {
-            builder.disableAuthnStatement(true);
-        }
-
-        List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>();
-        List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
-        ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null;
-
-        Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers();
-        for (ProtocolMapperModel mapping : mappings) {
-
-            ProtocolMapper mapper = (ProtocolMapper)session.getKeycloakSessionFactory().getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
-            if (mapper == null) continue;
-            if (mapper instanceof SAMLAttributeStatementMapper) {
-                attributeStatementMappers.add(new ProtocolMapperProcessor<SAMLAttributeStatementMapper>((SAMLAttributeStatementMapper)mapper, mapping));
-            }
-            if (mapper instanceof SAMLLoginResponseMapper) {
-                loginResponseMappers.add(new ProtocolMapperProcessor<SAMLLoginResponseMapper>((SAMLLoginResponseMapper)mapper, mapping));
-            }
-            if (mapper instanceof SAMLRoleListMapper) {
-                roleListMapper = new ProtocolMapperProcessor<SAMLRoleListMapper>((SAMLRoleListMapper)mapper, mapping);
-            }
-        }
-
-
-        Document samlDocument = null;
-        try {
-            ResponseType samlModel = builder.buildModel();
-            transformAttributeStatement(attributeStatementMappers, samlModel, session, userSession, clientSession);
-            populateRoles(roleListMapper, samlModel, session, userSession, clientSession);
-            samlModel = transformLoginResponse(loginResponseMappers, samlModel, session, userSession, clientSession);
-            samlDocument = builder.buildDocument(samlModel);
-        } catch (Exception e) {
-            logger.error("failed", e);
-            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
-        }
-
-        SAML2BindingBuilder2 bindingBuilder = new SAML2BindingBuilder2();
-        bindingBuilder.relayState(relayState);
-
-        if (requiresRealmSignature(client)) {
-            bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
-                   .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                   .signDocument();
-        }
-        if (requiresAssertionSignature(client)) {
-            bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
-                    .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                    .signAssertions();
-        }
-        if (requiresEncryption(client)) {
-            PublicKey publicKey = null;
-            try {
-                publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
-            } catch (Exception e) {
-                logger.error("failed", e);
-                return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
-            }
-            bindingBuilder.encrypt(publicKey);
-        }
-        try {
-            if (isPostBinding(clientSession)) {
-                return bindingBuilder.postBinding(samlDocument).response(redirectUri);
-            } else {
-                return bindingBuilder.redirectBinding(samlDocument).response(redirectUri);
-            }
-        } catch (Exception e) {
-            logger.error("failed", e);
-            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
-        }
-    }
-
-    public static boolean requiresRealmSignature(ClientModel client) {
-        return "true".equals(client.getAttribute(SAML_SERVER_SIGNATURE));
-    }
-
-    public static boolean requiresAssertionSignature(ClientModel client) {
-        return "true".equals(client.getAttribute(SAML_ASSERTION_SIGNATURE));
-    }
-
-    public static boolean includeAuthnStatement(ClientModel client) {
-        return "true".equals(client.getAttribute(SAML_AUTHNSTATEMENT));
-    }
-
-    public static SignatureAlgorithm getSignatureAlgorithm(ClientModel client) {
-        String alg = client.getAttribute(SAML_SIGNATURE_ALGORITHM);
-        if (alg != null) {
-            SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
-            if (algorithm != null) return algorithm;
-        }
-        return SignatureAlgorithm.RSA_SHA256;
-    }
-
-    private boolean requiresEncryption(ClientModel client) {
-        return "true".equals(client.getAttribute(SAML_ENCRYPT));
-    }
-
-    public static class ProtocolMapperProcessor<T> {
-        final public T mapper;
-        final public ProtocolMapperModel model;
-
-        public ProtocolMapperProcessor(T mapper, ProtocolMapperModel model) {
-            this.mapper = mapper;
-            this.model = model;
-        }
-    }
-
-    public void transformAttributeStatement(List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers,
-                                            ResponseType response,
-                                            KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        AssertionType assertion = response.getAssertions().get(0).getAssertion();
-        AttributeStatementType attributeStatement = new AttributeStatementType();
-
-        for (ProtocolMapperProcessor<SAMLAttributeStatementMapper> processor : attributeStatementMappers) {
-            processor.mapper.transformAttributeStatement(attributeStatement, processor.model, session, userSession, clientSession);
-        }
-
-        //SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
-        if(attributeStatement.getAttributes().size() > 0) {
-            assertion.addStatement(attributeStatement);
-        }
-    }
-
-    public ResponseType transformLoginResponse(List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> mappers,
-                                            ResponseType response,
-                                            KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        for (ProtocolMapperProcessor<SAMLLoginResponseMapper> processor : mappers) {
-            response = processor.mapper.transformLoginResponse(response, processor.model, session, userSession, clientSession);
-        }
-        return response;
-    }
-
-    public void populateRoles(ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper,
-                              ResponseType response,
-                              KeycloakSession session,
-                              UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (roleListMapper == null) return;
-        AssertionType assertion = response.getAssertions().get(0).getAssertion();
-        AttributeStatementType attributeStatement = new AttributeStatementType();
-        assertion.addStatement(attributeStatement);
-        roleListMapper.mapper.mapRoles(attributeStatement, roleListMapper.model, session, userSession, clientSession);
-    }
-
-
-    @Override
-    public Response consentDenied(ClientSessionModel clientSession) {
-        if ("true".equals(clientSession.getClient().getAttribute(SAML_IDP_INITIATED_LOGIN))) {
-            return ErrorPage.error(session, Messages.CONSENT_DENIED);
-        } else {
-            return getErrorResponse(clientSession, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get());
-        }
-    }
-
-    public static String getLogoutServiceUrl(UriInfo uriInfo, ClientModel client, String bindingType) {
-        String logoutServiceUrl = null;
-        if (SAML_POST_BINDING.equals(bindingType)) {
-            logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
-        } else {
-            logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
-        }
-        if (logoutServiceUrl == null && client instanceof ClientModel) logoutServiceUrl = ((ClientModel)client).getManagementUrl();
-        if (logoutServiceUrl == null || logoutServiceUrl.trim().equals("")) return null;
-        return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), logoutServiceUrl);
-
-    }
-
-    @Override
-    public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
-        ClientModel client = clientSession.getClient();
-        if (!(client instanceof ClientModel)) return null;
-        try {
-            if (isLogoutPostBindingForClient(clientSession)) {
-                String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
-                SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
-                return logoutBuilder.postBinding().request(bindingUri);
-            } else {
-                logger.debug("frontchannel redirect binding");
-                String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_REDIRECT_BINDING);
-                SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
-                return logoutBuilder.redirectBinding().request(bindingUri);
-            }
-        } catch (ConfigurationException e) {
-            throw new RuntimeException(e);
-        } catch (ProcessingException e) {
-            throw new RuntimeException(e);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        } catch (ParsingException e) {
-            throw new RuntimeException(e);
-        }
-
-    }
-
-    @Override
-    public Response finishLogout(UserSessionModel userSession) {
-        logger.debug("finishLogout");
-        String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
-        if (logoutBindingUri == null) {
-            logger.error("Can't finish SAML logout as there is no logout binding set");
-            return ErrorPage.error(session, Messages.FAILED_LOGOUT);
-
-        }
-        String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
-        SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
-        builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
-        builder.destination(logoutBindingUri);
-        builder.issuer(getResponseIssuer(realm));
-        builder.relayState(logoutRelayState);
-        String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
-        if (signingAlgorithm != null) {
-            SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
-            builder.signatureAlgorithm(algorithm)
-                    .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                    .signDocument();
-        }
-
-        try {
-            if (isLogoutPostBindingForInitiator(userSession)) {
-                return builder.postBinding().response(logoutBindingUri);
-            } else {
-                return builder.redirectBinding().response(logoutBindingUri);
-            }
-        } catch (ConfigurationException e) {
-            throw new RuntimeException(e);
-        } catch (ProcessingException e) {
-            throw new RuntimeException(e);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-
-    @Override
-    public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
-        ClientModel client = clientSession.getClient();
-        String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
-        if (logoutUrl == null) {
-            logger.warnv("Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}", client.getClientId());
-            return;
-        }
-        SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(logoutUrl, clientSession, client);
-
-
-        String logoutRequestString = null;
-        try {
-            logoutRequestString = logoutBuilder.postBinding().encoded();
-        } catch (Exception e) {
-            logger.warn("failed to send saml logout", e);
-            return;
-        }
-
-
-        HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
-        for (int i = 0; i < 2; i++) { // follow redirects once
-            try {
-                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-                formparams.add(new BasicNameValuePair(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString));
-                formparams.add(new BasicNameValuePair("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT")); // for Picketlink todo remove this
-                UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-                HttpPost post = new HttpPost(logoutUrl);
-                post.setEntity(form);
-                HttpResponse response = httpClient.execute(post);
-                try {
-                    int status = response.getStatusLine().getStatusCode();
-                    if (status == 302  && !logoutUrl.endsWith("/")) {
-                        String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
-                        String withSlash = logoutUrl + "/";
-                        if (withSlash.equals(redirect)) {
-                            logoutUrl = withSlash;
-                            continue;
-                        }
-                    }
-                } finally {
-                    HttpEntity entity = response.getEntity();
-                    if (entity != null) {
-                        InputStream is = entity.getContent();
-                        if (is != null) is.close();
-                    }
-
-                }
-            } catch (IOException e) {
-                logger.warn("failed to send saml logout", e);
-            }
-            break;
-        }
-
-    }
-
-    protected SAML2LogoutRequestBuilder createLogoutRequest(String logoutUrl, ClientSessionModel clientSession, ClientModel client) {
-        // build userPrincipal with subject used at login
-        SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder()
-                                         .assertionExpiration(realm.getAccessCodeLifespan())
-                                         .issuer(getResponseIssuer(realm))
-                                         .userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT))
-                                         .destination(logoutUrl);
-        if (requiresRealmSignature(client)) {
-            logoutBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
-                         .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                         .signDocument();
-        }
-        /*
-        if (requiresEncryption(client)) {
-            PublicKey publicKey = null;
-            try {
-                publicKey = PemUtils.decodePublicKey(client.getAttribute(ClientModel.PUBLIC_KEY));
-            } catch (Exception e) {
-                logger.error("failed", e);
-                return;
-            }
-            logoutBuilder.encrypt(publicKey);
-        }
-        */
-        return logoutBuilder;
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.protocol.saml;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+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.connections.httpclient.HttpClientProvider;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper;
+import org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper;
+import org.keycloak.protocol.saml.mappers.SAMLRoleListMapper;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
+import org.keycloak.services.ErrorPage;
+import org.w3c.dom.Document;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlProtocol implements LoginProtocol {
+    protected static final Logger logger = Logger.getLogger(SamlProtocol.class);
+
+
+    public static final String ATTRIBUTE_TRUE_VALUE = "true";
+    public static final String ATTRIBUTE_FALSE_VALUE = "false";
+    public static final String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE;
+    public static final String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE;
+    public static final String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature";
+    public static final String SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE = "saml_assertion_consumer_url_post";
+    public static final String SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE = "saml_assertion_consumer_url_redirect";
+    public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE = "saml_single_logout_service_url_post";
+    public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE = "saml_single_logout_service_url_redirect";
+    public static final String SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE = "saml_force_name_id_format";
+    public static final String SAML_NAME_ID_FORMAT_ATTRIBUTE = "saml_name_id_format";
+    public static final String LOGIN_PROTOCOL = "saml";
+    public static final String SAML_BINDING = "saml_binding";
+    public static final String SAML_IDP_INITIATED_LOGIN = "saml_idp_initiated_login";
+    public static final String SAML_POST_BINDING = "post";
+    public static final String SAML_REDIRECT_BINDING = "get";
+    public static final String SAML_SERVER_SIGNATURE = "saml.server.signature";
+    public static final String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature";
+    public static final String SAML_AUTHNSTATEMENT = "saml.authnstatement";
+    public static final String SAML_SIGNATURE_ALGORITHM = "saml.signature.algorithm";
+    public static final String SAML_ENCRYPT = "saml.encrypt";
+    public static final String SAML_FORCE_POST_BINDING = "saml.force.post.binding";
+    public static final String SAML_REQUEST_ID = "SAML_REQUEST_ID";
+    public static final String SAML_LOGOUT_BINDING = "saml.logout.binding";
+    public static final String SAML_LOGOUT_REQUEST_ID = "SAML_LOGOUT_REQUEST_ID";
+    public static final String SAML_LOGOUT_RELAY_STATE = "SAML_LOGOUT_RELAY_STATE";
+    public static final String SAML_LOGOUT_BINDING_URI = "SAML_LOGOUT_BINDING_URI";
+    public static final String SAML_LOGOUT_SIGNATURE_ALGORITHM = "saml.logout.signature.algorithm";
+    public static final String SAML_NAME_ID = "SAML_NAME_ID";
+    public static final String SAML_NAME_ID_FORMAT = "SAML_NAME_ID_FORMAT";
+    public static final String SAML_DEFAULT_NAMEID_FORMAT = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
+    public static final String SAML_PERSISTENT_NAME_ID_FOR = "saml.persistent.name.id.for";
+    public static final String SAML_IDP_INITIATED_SSO_RELAY_STATE = "saml_idp_initiated_sso_relay_state";
+    public static final String SAML_IDP_INITIATED_SSO_URL_NAME = "saml_idp_initiated_sso_url_name";
+
+    protected KeycloakSession session;
+
+    protected RealmModel realm;
+
+    protected UriInfo uriInfo;
+
+    protected HttpHeaders headers;
+
+    protected EventBuilder event;
+
+
+    @Override
+    public SamlProtocol setSession(KeycloakSession session) {
+        this.session = session;
+        return this;
+    }
+
+    @Override
+    public SamlProtocol setRealm(RealmModel realm) {
+        this.realm = realm;
+        return this;
+    }
+
+    @Override
+    public SamlProtocol setUriInfo(UriInfo uriInfo) {
+        this.uriInfo = uriInfo;
+        return this;
+    }
+
+    @Override
+    public SamlProtocol setHttpHeaders(HttpHeaders headers){
+        this.headers = headers;
+        return this;
+    }
+
+    @Override
+    public SamlProtocol setEventBuilder(EventBuilder event) {
+        this.event = event;
+        return this;
+    }
+
+
+    @Override
+    public Response cancelLogin(ClientSessionModel clientSession) {
+        if ("true".equals(clientSession.getClient().getAttribute(SAML_IDP_INITIATED_LOGIN))) {
+            UriBuilder builder = RealmsResource.protocolUrl(uriInfo).path(SamlService.class, "idpInitiatedSSO");
+            Map<String, String> params = new HashMap<>();
+            params.put("realm", realm.getName());
+            params.put("protocol", LOGIN_PROTOCOL);
+            params.put("client", clientSession.getClient().getAttribute(SAML_IDP_INITIATED_SSO_URL_NAME));
+            session.sessions().removeClientSession(realm, clientSession);
+            URI redirect = builder.buildFromMap(params);
+            return Response.status(302).location(redirect).build();
+        } else {
+            session.sessions().removeClientSession(realm, clientSession);
+            return getErrorResponse(clientSession, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get());
+        }
+    }
+
+    protected String getResponseIssuer(RealmModel realm) {
+        return RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString();
+    }
+
+    protected Response getErrorResponse(ClientSessionModel clientSession, String status) {
+        SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder()
+                .relayState(clientSession.getNote(GeneralConstants.RELAY_STATE))
+                .destination(clientSession.getRedirectUri())
+                .issuer(getResponseIssuer(realm))
+                .status(status);
+      try {
+          if (isPostBinding(clientSession)) {
+              return builder.postBinding().response();
+          } else {
+              return builder.redirectBinding().response();
+          }
+        } catch (Exception e) {
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
+        }
+    }
+
+    protected boolean isPostBinding(ClientSessionModel clientSession) {
+        ClientModel client = clientSession.getClient();
+        return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || forcePostBinding(client);
+    }
+
+    public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) {
+        String note = session.getNote(SamlProtocol.SAML_LOGOUT_BINDING);
+        return SamlProtocol.SAML_POST_BINDING.equals(note);
+    }
+
+
+
+    protected boolean isLogoutPostBindingForClient(ClientSessionModel clientSession) {
+        ClientModel client = clientSession.getClient();
+        String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
+        String logoutRedirectUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
+
+        if (logoutPostUrl == null) {
+            // if we don't have a redirect uri either, return true and default to the admin url + POST binding
+            if (logoutRedirectUrl == null) return true;
+            return false;
+        }
+
+        if (forcePostBinding(client)) {
+            return true; // configured to force a post binding and post binding logout url is not null
+        }
+
+        String bindingType = clientSession.getNote(SAML_BINDING);
+
+        // if the login binding was POST, return true
+        if (SAML_POST_BINDING.equals(bindingType)) return true;
+
+        if (logoutRedirectUrl == null) return true; // we don't have a redirect binding url, so use post binding
+
+        return false;  // redirect binding
+
+    }
+
+    public static boolean forcePostBinding(ClientModel client) {
+        return "true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING));
+    }
+
+    protected String getNameIdFormat(ClientSessionModel clientSession) {
+        String nameIdFormat = clientSession.getNote(GeneralConstants.NAMEID_FORMAT);
+        ClientModel client = clientSession.getClient();
+        boolean forceFormat = forceNameIdFormat(client);
+        String configuredNameIdFormat = client.getAttribute(SAML_NAME_ID_FORMAT_ATTRIBUTE);
+        if ((nameIdFormat == null || forceFormat) && configuredNameIdFormat != null) {
+            if (configuredNameIdFormat.equals("email")) {
+                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get();
+            } else if (configuredNameIdFormat.equals("persistent")) {
+                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
+            } else if (configuredNameIdFormat.equals("transient")) {
+                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get();
+            } else if (configuredNameIdFormat.equals("username")) {
+                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
+            } else {
+                nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
+            }
+        }
+        if(nameIdFormat == null) return SAML_DEFAULT_NAMEID_FORMAT;
+        return nameIdFormat;
+    }
+
+    public static boolean forceNameIdFormat(ClientModel client) {
+        return "true".equals(client.getAttribute(SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
+    }
+
+    protected String getNameId(String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
+        if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
+            return userSession.getUser().getEmail();
+        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get())) {
+            // "G-" stands for "generated" Add this for the slight possibility of collisions.
+            return "G-" + UUID.randomUUID().toString();
+        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get())) {
+            // generate a persistent user id specifically for each client.
+            UserModel user = userSession.getUser();
+            String name = SAML_PERSISTENT_NAME_ID_FOR + "." + clientSession.getClient().getClientId();
+            String samlPersistentId = user.getFirstAttribute(name);
+            if (samlPersistentId != null) return samlPersistentId;
+            // "G-" stands for "generated"
+            samlPersistentId = "G-" + UUID.randomUUID().toString();
+            user.setSingleAttribute(name, samlPersistentId);
+            return samlPersistentId;
+        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())){
+            // TODO: Support for persistent NameID (pseudo-random identifier persisted in user object)
+            return userSession.getUser().getUsername();
+        } else {
+            return userSession.getUser().getUsername();
+        }
+    }
+
+    @Override
+    public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
+        ClientSessionModel clientSession = accessCode.getClientSession();
+        ClientModel client = clientSession.getClient();
+        String requestID = clientSession.getNote(SAML_REQUEST_ID);
+        String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE);
+        String redirectUri = clientSession.getRedirectUri();
+        String responseIssuer = getResponseIssuer(realm);
+        String nameIdFormat = getNameIdFormat(clientSession);
+        String nameId = getNameId(nameIdFormat, clientSession, userSession);
+
+        // save NAME_ID and format in clientSession as they may be persistent or transient or email and not username
+        // we'll need to send this back on a logout
+        clientSession.setNote(SAML_NAME_ID, nameId);
+        clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
+
+        SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
+        builder.requestID(requestID)
+               .destination(redirectUri)
+               .issuer(responseIssuer)
+               .assertionExpiration(realm.getAccessCodeLifespan())
+               .subjectExpiration(realm.getAccessTokenLifespan())
+               .sessionIndex(clientSession.getId())
+               .requestIssuer(clientSession.getClient().getClientId())
+               .nameIdentifier(nameIdFormat, nameId)
+               .authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
+        if (!includeAuthnStatement(client)) {
+            builder.disableAuthnStatement(true);
+        }
+
+        List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>();
+        List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
+        ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null;
+
+        Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers();
+        for (ProtocolMapperModel mapping : mappings) {
+
+            ProtocolMapper mapper = (ProtocolMapper)session.getKeycloakSessionFactory().getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
+            if (mapper == null) continue;
+            if (mapper instanceof SAMLAttributeStatementMapper) {
+                attributeStatementMappers.add(new ProtocolMapperProcessor<SAMLAttributeStatementMapper>((SAMLAttributeStatementMapper)mapper, mapping));
+            }
+            if (mapper instanceof SAMLLoginResponseMapper) {
+                loginResponseMappers.add(new ProtocolMapperProcessor<SAMLLoginResponseMapper>((SAMLLoginResponseMapper)mapper, mapping));
+            }
+            if (mapper instanceof SAMLRoleListMapper) {
+                roleListMapper = new ProtocolMapperProcessor<SAMLRoleListMapper>((SAMLRoleListMapper)mapper, mapping);
+            }
+        }
+
+
+        Document samlDocument = null;
+        try {
+            ResponseType samlModel = builder.buildModel();
+            transformAttributeStatement(attributeStatementMappers, samlModel, session, userSession, clientSession);
+            populateRoles(roleListMapper, samlModel, session, userSession, clientSession);
+            samlModel = transformLoginResponse(loginResponseMappers, samlModel, session, userSession, clientSession);
+            samlDocument = builder.buildDocument(samlModel);
+        } catch (Exception e) {
+            logger.error("failed", e);
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
+        }
+
+        SAML2BindingBuilder2 bindingBuilder = new SAML2BindingBuilder2();
+        bindingBuilder.relayState(relayState);
+
+        if (requiresRealmSignature(client)) {
+            bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
+                   .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                   .signDocument();
+        }
+        if (requiresAssertionSignature(client)) {
+            bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
+                    .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                    .signAssertions();
+        }
+        if (requiresEncryption(client)) {
+            PublicKey publicKey = null;
+            try {
+                publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
+            } catch (Exception e) {
+                logger.error("failed", e);
+                return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
+            }
+            bindingBuilder.encrypt(publicKey);
+        }
+        try {
+            if (isPostBinding(clientSession)) {
+                return bindingBuilder.postBinding(samlDocument).response(redirectUri);
+            } else {
+                return bindingBuilder.redirectBinding(samlDocument).response(redirectUri);
+            }
+        } catch (Exception e) {
+            logger.error("failed", e);
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
+        }
+    }
+
+    public static boolean requiresRealmSignature(ClientModel client) {
+        return "true".equals(client.getAttribute(SAML_SERVER_SIGNATURE));
+    }
+
+    public static boolean requiresAssertionSignature(ClientModel client) {
+        return "true".equals(client.getAttribute(SAML_ASSERTION_SIGNATURE));
+    }
+
+    public static boolean includeAuthnStatement(ClientModel client) {
+        return "true".equals(client.getAttribute(SAML_AUTHNSTATEMENT));
+    }
+
+    public static SignatureAlgorithm getSignatureAlgorithm(ClientModel client) {
+        String alg = client.getAttribute(SAML_SIGNATURE_ALGORITHM);
+        if (alg != null) {
+            SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
+            if (algorithm != null) return algorithm;
+        }
+        return SignatureAlgorithm.RSA_SHA256;
+    }
+
+    private boolean requiresEncryption(ClientModel client) {
+        return "true".equals(client.getAttribute(SAML_ENCRYPT));
+    }
+
+    public static class ProtocolMapperProcessor<T> {
+        final public T mapper;
+        final public ProtocolMapperModel model;
+
+        public ProtocolMapperProcessor(T mapper, ProtocolMapperModel model) {
+            this.mapper = mapper;
+            this.model = model;
+        }
+    }
+
+    public void transformAttributeStatement(List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers,
+                                            ResponseType response,
+                                            KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        AssertionType assertion = response.getAssertions().get(0).getAssertion();
+        AttributeStatementType attributeStatement = new AttributeStatementType();
+
+        for (ProtocolMapperProcessor<SAMLAttributeStatementMapper> processor : attributeStatementMappers) {
+            processor.mapper.transformAttributeStatement(attributeStatement, processor.model, session, userSession, clientSession);
+        }
+
+        //SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
+        if(attributeStatement.getAttributes().size() > 0) {
+            assertion.addStatement(attributeStatement);
+        }
+    }
+
+    public ResponseType transformLoginResponse(List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> mappers,
+                                            ResponseType response,
+                                            KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        for (ProtocolMapperProcessor<SAMLLoginResponseMapper> processor : mappers) {
+            response = processor.mapper.transformLoginResponse(response, processor.model, session, userSession, clientSession);
+        }
+        return response;
+    }
+
+    public void populateRoles(ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper,
+                              ResponseType response,
+                              KeycloakSession session,
+                              UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (roleListMapper == null) return;
+        AssertionType assertion = response.getAssertions().get(0).getAssertion();
+        AttributeStatementType attributeStatement = new AttributeStatementType();
+        assertion.addStatement(attributeStatement);
+        roleListMapper.mapper.mapRoles(attributeStatement, roleListMapper.model, session, userSession, clientSession);
+    }
+
+
+    @Override
+    public Response consentDenied(ClientSessionModel clientSession) {
+        if ("true".equals(clientSession.getClient().getAttribute(SAML_IDP_INITIATED_LOGIN))) {
+            return ErrorPage.error(session, Messages.CONSENT_DENIED);
+        } else {
+            return getErrorResponse(clientSession, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get());
+        }
+    }
+
+    public static String getLogoutServiceUrl(UriInfo uriInfo, ClientModel client, String bindingType) {
+        String logoutServiceUrl = null;
+        if (SAML_POST_BINDING.equals(bindingType)) {
+            logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
+        } else {
+            logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
+        }
+        if (logoutServiceUrl == null && client instanceof ClientModel) logoutServiceUrl = ((ClientModel)client).getManagementUrl();
+        if (logoutServiceUrl == null || logoutServiceUrl.trim().equals("")) return null;
+        return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), logoutServiceUrl);
+
+    }
+
+    @Override
+    public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+        ClientModel client = clientSession.getClient();
+        if (!(client instanceof ClientModel)) return null;
+        try {
+            if (isLogoutPostBindingForClient(clientSession)) {
+                String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
+                SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
+                return logoutBuilder.postBinding().request(bindingUri);
+            } else {
+                logger.debug("frontchannel redirect binding");
+                String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_REDIRECT_BINDING);
+                SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
+                return logoutBuilder.redirectBinding().request(bindingUri);
+            }
+        } catch (ConfigurationException e) {
+            throw new RuntimeException(e);
+        } catch (ProcessingException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } catch (ParsingException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    @Override
+    public Response finishLogout(UserSessionModel userSession) {
+        logger.debug("finishLogout");
+        String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
+        if (logoutBindingUri == null) {
+            logger.error("Can't finish SAML logout as there is no logout binding set");
+            return ErrorPage.error(session, Messages.FAILED_LOGOUT);
+
+        }
+        String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
+        SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
+        builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
+        builder.destination(logoutBindingUri);
+        builder.issuer(getResponseIssuer(realm));
+        builder.relayState(logoutRelayState);
+        String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
+        if (signingAlgorithm != null) {
+            SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
+            builder.signatureAlgorithm(algorithm)
+                    .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                    .signDocument();
+        }
+
+        try {
+            if (isLogoutPostBindingForInitiator(userSession)) {
+                return builder.postBinding().response(logoutBindingUri);
+            } else {
+                return builder.redirectBinding().response(logoutBindingUri);
+            }
+        } catch (ConfigurationException e) {
+            throw new RuntimeException(e);
+        } catch (ProcessingException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+
+    @Override
+    public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+        ClientModel client = clientSession.getClient();
+        String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
+        if (logoutUrl == null) {
+            logger.warnv("Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}", client.getClientId());
+            return;
+        }
+        SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(logoutUrl, clientSession, client);
+
+
+        String logoutRequestString = null;
+        try {
+            logoutRequestString = logoutBuilder.postBinding().encoded();
+        } catch (Exception e) {
+            logger.warn("failed to send saml logout", e);
+            return;
+        }
+
+
+        HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
+        for (int i = 0; i < 2; i++) { // follow redirects once
+            try {
+                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+                formparams.add(new BasicNameValuePair(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString));
+                formparams.add(new BasicNameValuePair("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT")); // for Picketlink todo remove this
+                UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+                HttpPost post = new HttpPost(logoutUrl);
+                post.setEntity(form);
+                HttpResponse response = httpClient.execute(post);
+                try {
+                    int status = response.getStatusLine().getStatusCode();
+                    if (status == 302  && !logoutUrl.endsWith("/")) {
+                        String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
+                        String withSlash = logoutUrl + "/";
+                        if (withSlash.equals(redirect)) {
+                            logoutUrl = withSlash;
+                            continue;
+                        }
+                    }
+                } finally {
+                    HttpEntity entity = response.getEntity();
+                    if (entity != null) {
+                        InputStream is = entity.getContent();
+                        if (is != null) is.close();
+                    }
+
+                }
+            } catch (IOException e) {
+                logger.warn("failed to send saml logout", e);
+            }
+            break;
+        }
+
+    }
+
+    protected SAML2LogoutRequestBuilder createLogoutRequest(String logoutUrl, ClientSessionModel clientSession, ClientModel client) {
+        // build userPrincipal with subject used at login
+        SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder()
+                                         .assertionExpiration(realm.getAccessCodeLifespan())
+                                         .issuer(getResponseIssuer(realm))
+                                         .userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT))
+                                         .destination(logoutUrl);
+        if (requiresRealmSignature(client)) {
+            logoutBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
+                         .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                         .signDocument();
+        }
+        /*
+        if (requiresEncryption(client)) {
+            PublicKey publicKey = null;
+            try {
+                publicKey = PemUtils.decodePublicKey(client.getAttribute(ClientModel.PUBLIC_KEY));
+            } catch (Exception e) {
+                logger.error("failed", e);
+                return;
+            }
+            logoutBuilder.encrypt(publicKey);
+        }
+        */
+        return logoutBuilder;
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
index 4c74ab5..a7a86ed 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
@@ -1,97 +1,97 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.Config;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.AbstractLoginProtocolFactory;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
-import org.keycloak.protocol.saml.mappers.RoleListMapper;
-import org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
-
-    @Override
-    public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
-        return new SamlService(realm, event, authManager);
-    }
-
-    @Override
-    public LoginProtocol create(KeycloakSession session) {
-        return new SamlProtocol().setSession(session);
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-        //PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
-        //sts.installDefaultConfiguration();
-    }
-
-    @Override
-    public String getId() {
-        return "saml";
-    }
-
-    @Override
-    public List<ProtocolMapperModel> getBuiltinMappers() {
-        return builtins;
-    }
-
-    @Override
-    public List<ProtocolMapperModel> getDefaultBuiltinMappers() {
-        return defaultBuiltins;
-    }
-
-    static List<ProtocolMapperModel> builtins = new ArrayList<>();
-    static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
-
-    static {
-        ProtocolMapperModel model;
-        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 email",
-                "email",
-                X500SAMLProfileConstants.EMAIL.get(),
-                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
-                X500SAMLProfileConstants.EMAIL.getFriendlyName(),
-                true, "${email}");
-        builtins.add(model);
-        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 givenName",
-                "firstName",
-                X500SAMLProfileConstants.GIVEN_NAME.get(),
-                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
-                X500SAMLProfileConstants.GIVEN_NAME.getFriendlyName(),
-                true, "${givenName}");
-        builtins.add(model);
-        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 surname",
-                "lastName",
-                X500SAMLProfileConstants.SURNAME.get(),
-                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
-                X500SAMLProfileConstants.SURNAME.getFriendlyName(),
-                true, "${familyName}");
-        builtins.add(model);
-        model = RoleListMapper.create("role list", "Role", AttributeStatementHelper.BASIC, null, false);
-        builtins.add(model);
-        defaultBuiltins.add(model);
-
-    }
-
-
-    @Override
-    protected void addDefaults(ClientModel client) {
-        for (ProtocolMapperModel model : defaultBuiltins) client.addProtocolMapper(model);
-
-    }
-
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.Config;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.AbstractLoginProtocolFactory;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
+import org.keycloak.protocol.saml.mappers.RoleListMapper;
+import org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
+
+    @Override
+    public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
+        return new SamlService(realm, event, authManager);
+    }
+
+    @Override
+    public LoginProtocol create(KeycloakSession session) {
+        return new SamlProtocol().setSession(session);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+        //PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
+        //sts.installDefaultConfiguration();
+    }
+
+    @Override
+    public String getId() {
+        return "saml";
+    }
+
+    @Override
+    public List<ProtocolMapperModel> getBuiltinMappers() {
+        return builtins;
+    }
+
+    @Override
+    public List<ProtocolMapperModel> getDefaultBuiltinMappers() {
+        return defaultBuiltins;
+    }
+
+    static List<ProtocolMapperModel> builtins = new ArrayList<>();
+    static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
+
+    static {
+        ProtocolMapperModel model;
+        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 email",
+                "email",
+                X500SAMLProfileConstants.EMAIL.get(),
+                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
+                X500SAMLProfileConstants.EMAIL.getFriendlyName(),
+                true, "${email}");
+        builtins.add(model);
+        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 givenName",
+                "firstName",
+                X500SAMLProfileConstants.GIVEN_NAME.get(),
+                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
+                X500SAMLProfileConstants.GIVEN_NAME.getFriendlyName(),
+                true, "${givenName}");
+        builtins.add(model);
+        model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 surname",
+                "lastName",
+                X500SAMLProfileConstants.SURNAME.get(),
+                JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
+                X500SAMLProfileConstants.SURNAME.getFriendlyName(),
+                true, "${familyName}");
+        builtins.add(model);
+        model = RoleListMapper.create("role list", "Role", AttributeStatementHelper.BASIC, null, false);
+        builtins.add(model);
+        defaultBuiltins.add(model);
+
+    }
+
+
+    @Override
+    protected void addDefaults(ClientModel client) {
+        for (ProtocolMapperModel model : defaultBuiltins) client.addProtocolMapper(model);
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
index 11007c8..d865b2c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
@@ -1,121 +1,121 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.VerificationException;
-import org.keycloak.models.ClientModel;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
-import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
-import org.keycloak.util.PemUtils;
-import org.w3c.dom.Document;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.cert.Certificate;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SamlProtocolUtils {
-
-    /**
-     * <p>
-     * Creates a random {@code byte[]} secret of the specified size.
-     * </p>
-     *
-     * @param size the size of the secret to be created, in bytes.
-     *
-     * @return a {@code byte[]} containing the generated secret.
-     */
-    public static byte[] createRandomSecret(final int size) {
-        SecureRandom random = new SecureRandom();
-        byte[] secret = new byte[size];
-        random.nextBytes(secret);
-        return secret;
-    }
-
-
-    public static void verifyDocumentSignature(ClientModel client, Document document) throws VerificationException {
-        if (!"true".equals(client.getAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
-            return;
-        }
-        PublicKey publicKey = getSignatureValidationKey(client);
-        verifyDocumentSignature(document, publicKey);
-    }
-
-    public static void verifyDocumentSignature(Document document, PublicKey publicKey) throws VerificationException {
-        SAML2Signature saml2Signature = new SAML2Signature();
-        try {
-            if (!saml2Signature.validate(document, publicKey)) {
-                throw new VerificationException("Invalid signature on document");
-            }
-        } catch (ProcessingException e) {
-            throw new VerificationException("Error validating signature", e);
-        }
-    }
-
-    public static PublicKey getSignatureValidationKey(ClientModel client) throws VerificationException {
-        return getPublicKey(client, SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
-    }
-
-    public static PublicKey getEncryptionValidationKey(ClientModel client) throws VerificationException {
-        return getPublicKey(client, SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE);
-    }
-
-    public static PublicKey getPublicKey(ClientModel client, String attribute) throws VerificationException {
-        String certPem = client.getAttribute(attribute);
-        if (certPem == null) throw new VerificationException("Client does not have a public key.");
-        Certificate cert = null;
-        try {
-            cert = PemUtils.decodeCertificate(certPem);
-        } catch (Exception e) {
-            throw new VerificationException("Could not decode cert", e);
-        }
-        return cert.getPublicKey();
-    }
-
-    public static void verifyRedirectSignature(PublicKey publicKey, UriInfo uriInformation) throws VerificationException {
-        MultivaluedMap<String, String> encodedParams = uriInformation.getQueryParameters(false);
-        String request = encodedParams.getFirst(GeneralConstants.SAML_REQUEST_KEY);
-        String algorithm = encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
-        String signature = encodedParams.getFirst(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
-        String decodedAlgorithm = uriInformation.getQueryParameters(true).getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
-
-        if (request == null) throw new VerificationException("SAMLRequest as null");
-        if (algorithm == null) throw new VerificationException("SigAlg as null");
-        if (signature == null) throw new VerificationException("Signature as null");
-
-        // Shibboleth doesn't sign the document for redirect binding.
-        // todo maybe a flag?
-
-
-        UriBuilder builder = UriBuilder.fromPath("/")
-                .queryParam(GeneralConstants.SAML_REQUEST_KEY, request);
-        if (encodedParams.containsKey(GeneralConstants.RELAY_STATE)) {
-            builder.queryParam(GeneralConstants.RELAY_STATE, encodedParams.getFirst(GeneralConstants.RELAY_STATE));
-        }
-        builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, algorithm);
-        String rawQuery = builder.build().getRawQuery();
-
-        try {
-            byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
-
-            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
-            Signature validator = signatureAlgorithm.createSignature(); // todo plugin signature alg
-            validator.initVerify(publicKey);
-            validator.update(rawQuery.getBytes("UTF-8"));
-            if (!validator.verify(decodedSignature)) {
-                throw new VerificationException("Invalid query param signature");
-            }
-        } catch (Exception e) {
-            throw new VerificationException(e);
-        }
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.VerificationException;
+import org.keycloak.models.ClientModel;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
+import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+import org.keycloak.util.PemUtils;
+import org.w3c.dom.Document;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.cert.Certificate;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlProtocolUtils {
+
+    /**
+     * <p>
+     * Creates a random {@code byte[]} secret of the specified size.
+     * </p>
+     *
+     * @param size the size of the secret to be created, in bytes.
+     *
+     * @return a {@code byte[]} containing the generated secret.
+     */
+    public static byte[] createRandomSecret(final int size) {
+        SecureRandom random = new SecureRandom();
+        byte[] secret = new byte[size];
+        random.nextBytes(secret);
+        return secret;
+    }
+
+
+    public static void verifyDocumentSignature(ClientModel client, Document document) throws VerificationException {
+        if (!"true".equals(client.getAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
+            return;
+        }
+        PublicKey publicKey = getSignatureValidationKey(client);
+        verifyDocumentSignature(document, publicKey);
+    }
+
+    public static void verifyDocumentSignature(Document document, PublicKey publicKey) throws VerificationException {
+        SAML2Signature saml2Signature = new SAML2Signature();
+        try {
+            if (!saml2Signature.validate(document, publicKey)) {
+                throw new VerificationException("Invalid signature on document");
+            }
+        } catch (ProcessingException e) {
+            throw new VerificationException("Error validating signature", e);
+        }
+    }
+
+    public static PublicKey getSignatureValidationKey(ClientModel client) throws VerificationException {
+        return getPublicKey(client, SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
+    }
+
+    public static PublicKey getEncryptionValidationKey(ClientModel client) throws VerificationException {
+        return getPublicKey(client, SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE);
+    }
+
+    public static PublicKey getPublicKey(ClientModel client, String attribute) throws VerificationException {
+        String certPem = client.getAttribute(attribute);
+        if (certPem == null) throw new VerificationException("Client does not have a public key.");
+        Certificate cert = null;
+        try {
+            cert = PemUtils.decodeCertificate(certPem);
+        } catch (Exception e) {
+            throw new VerificationException("Could not decode cert", e);
+        }
+        return cert.getPublicKey();
+    }
+
+    public static void verifyRedirectSignature(PublicKey publicKey, UriInfo uriInformation) throws VerificationException {
+        MultivaluedMap<String, String> encodedParams = uriInformation.getQueryParameters(false);
+        String request = encodedParams.getFirst(GeneralConstants.SAML_REQUEST_KEY);
+        String algorithm = encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
+        String signature = encodedParams.getFirst(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
+        String decodedAlgorithm = uriInformation.getQueryParameters(true).getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
+
+        if (request == null) throw new VerificationException("SAMLRequest as null");
+        if (algorithm == null) throw new VerificationException("SigAlg as null");
+        if (signature == null) throw new VerificationException("Signature as null");
+
+        // Shibboleth doesn't sign the document for redirect binding.
+        // todo maybe a flag?
+
+
+        UriBuilder builder = UriBuilder.fromPath("/")
+                .queryParam(GeneralConstants.SAML_REQUEST_KEY, request);
+        if (encodedParams.containsKey(GeneralConstants.RELAY_STATE)) {
+            builder.queryParam(GeneralConstants.RELAY_STATE, encodedParams.getFirst(GeneralConstants.RELAY_STATE));
+        }
+        builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, algorithm);
+        String rawQuery = builder.build().getRawQuery();
+
+        try {
+            byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
+
+            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
+            Signature validator = signatureAlgorithm.createSignature(); // todo plugin signature alg
+            validator.initVerify(publicKey);
+            validator.update(rawQuery.getBytes("UTF-8"));
+            if (!validator.verify(decodedSignature)) {
+                throw new VerificationException("Invalid query param signature");
+            }
+        } catch (Exception e) {
+            throw new VerificationException(e);
+        }
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
index af97752..65db552 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAMLRequestParser.java
@@ -1,80 +1,80 @@
-package org.keycloak.protocol.saml;
-
-import org.keycloak.saml.common.PicketLinkLogger;
-import org.keycloak.saml.common.PicketLinkLoggerFactory;
-import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
-import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SAMLRequestParser {
-    private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
-
-    public static SAMLDocumentHolder parseRequestRedirectBinding(String samlMessage) {
-        InputStream is;
-        is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
-        SAML2Request saml2Request = new SAML2Request();
-        try {
-            saml2Request.getSAML2ObjectFromStream(is);
-            return saml2Request.getSamlDocumentHolder();
-        } catch (Exception e) {
-            logger.samlBase64DecodingError(e);
-        }
-        return null;
-
-    }
-
-    public static SAMLDocumentHolder parseRequestPostBinding(String samlMessage) {
-        InputStream is;
-        byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
-        is = new ByteArrayInputStream(samlBytes);
-        SAML2Request saml2Request = new SAML2Request();
-        try {
-            saml2Request.getSAML2ObjectFromStream(is);
-            return saml2Request.getSamlDocumentHolder();
-        } catch (Exception e) {
-            logger.samlBase64DecodingError(e);
-        }
-        return null;
-    }
-
-    public static SAMLDocumentHolder parseResponsePostBinding(String samlMessage) {
-        byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
-        return parseResponseDocument(samlBytes);
-    }
-
-    public static SAMLDocumentHolder parseResponseDocument(byte[] samlBytes) {
-        InputStream is = new ByteArrayInputStream(samlBytes);
-        SAML2Response response = new SAML2Response();
-        try {
-            response.getSAML2ObjectFromStream(is);
-            return response.getSamlDocumentHolder();
-        } catch (Exception e) {
-            logger.samlBase64DecodingError(e);
-        }
-        return null;
-    }
-
-    public static SAMLDocumentHolder parseResponseRedirectBinding(String samlMessage) {
-        InputStream is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
-        SAML2Response response = new SAML2Response();
-        try {
-            response.getSAML2ObjectFromStream(is);
-            return response.getSamlDocumentHolder();
-        } catch (Exception e) {
-            logger.samlBase64DecodingError(e);
-        }
-        return null;
-
-    }
-
-
-}
+package org.keycloak.protocol.saml;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAMLRequestParser {
+    private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+    public static SAMLDocumentHolder parseRequestRedirectBinding(String samlMessage) {
+        InputStream is;
+        is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
+        SAML2Request saml2Request = new SAML2Request();
+        try {
+            saml2Request.getSAML2ObjectFromStream(is);
+            return saml2Request.getSamlDocumentHolder();
+        } catch (Exception e) {
+            logger.samlBase64DecodingError(e);
+        }
+        return null;
+
+    }
+
+    public static SAMLDocumentHolder parseRequestPostBinding(String samlMessage) {
+        InputStream is;
+        byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
+        is = new ByteArrayInputStream(samlBytes);
+        SAML2Request saml2Request = new SAML2Request();
+        try {
+            saml2Request.getSAML2ObjectFromStream(is);
+            return saml2Request.getSamlDocumentHolder();
+        } catch (Exception e) {
+            logger.samlBase64DecodingError(e);
+        }
+        return null;
+    }
+
+    public static SAMLDocumentHolder parseResponsePostBinding(String samlMessage) {
+        byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
+        return parseResponseDocument(samlBytes);
+    }
+
+    public static SAMLDocumentHolder parseResponseDocument(byte[] samlBytes) {
+        InputStream is = new ByteArrayInputStream(samlBytes);
+        SAML2Response response = new SAML2Response();
+        try {
+            response.getSAML2ObjectFromStream(is);
+            return response.getSamlDocumentHolder();
+        } catch (Exception e) {
+            logger.samlBase64DecodingError(e);
+        }
+        return null;
+    }
+
+    public static SAMLDocumentHolder parseResponseRedirectBinding(String samlMessage) {
+        InputStream is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
+        SAML2Response response = new SAML2Response();
+        try {
+            response.getSAML2ObjectFromStream(is);
+            return response.getSamlDocumentHolder();
+        } catch (Exception e) {
+            logger.samlBase64DecodingError(e);
+        }
+        return null;
+
+    }
+
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index da2fc9e..eae7ade 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -1,625 +1,625 @@
-package org.keycloak.protocol.saml;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.jboss.resteasy.spi.HttpResponse;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.ClientConnection;
-import org.keycloak.VerificationException;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.dom.saml.v2.SAML2Object;
-import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
-import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
-import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
-import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
-import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.utils.RedirectUtils;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
-import org.keycloak.services.ErrorPage;
-import org.keycloak.services.Urls;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.util.StreamUtil;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.Providers;
-import java.io.InputStream;
-import java.net.URI;
-import java.security.PublicKey;
-import java.util.List;
-
-/**
- * Resource class for the oauth/openid connect token service
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SamlService {
-
-    protected static final Logger logger = Logger.getLogger(SamlService.class);
-
-    protected RealmModel realm;
-    private EventBuilder event;
-    protected AuthenticationManager authManager;
-
-    @Context
-    protected Providers providers;
-    @Context
-    protected SecurityContext securityContext;
-    @Context
-    protected UriInfo uriInfo;
-    @Context
-    protected HttpHeaders headers;
-    @Context
-    protected HttpRequest request;
-    @Context
-    protected HttpResponse response;
-    @Context
-    protected KeycloakSession session;
-    @Context
-    protected ClientConnection clientConnection;
-
-    /*
-    @Context
-    protected ResourceContext resourceContext;
-    */
-
-    public SamlService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
-        this.realm = realm;
-        this.event = event;
-        this.authManager = authManager;
-    }
-
-    public abstract class BindingProtocol {
-        protected Response basicChecks(String samlRequest, String samlResponse) {
-            if (!checkSsl()) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.SSL_REQUIRED);
-                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
-            }
-            if (!realm.isEnabled()) {
-                event.event(EventType.LOGIN_ERROR);
-                event.error(Errors.REALM_DISABLED);
-                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
-            }
-
-            if (samlRequest == null && samlResponse == null) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_TOKEN);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-
-            }
-            return null;
-        }
-
-        protected Response handleSamlResponse(String samlResponse, String relayState) {
-            event.event(EventType.LOGOUT);
-            SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
-            StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
-            // validate destination
-            if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
-                event.detail(Details.REASON, "invalid_destination");
-                event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-
-            AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
-            if (authResult == null) {
-                logger.warn("Unknown saml response.");
-                event.event(EventType.LOGOUT);
-                event.error(Errors.INVALID_TOKEN);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-            // assume this is a logout response
-            UserSessionModel userSession = authResult.getSession();
-            if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
-                logger.warn("Unknown saml response.");
-                logger.warn("UserSession is not tagged as logging out.");
-                event.event(EventType.LOGOUT);
-                event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-            logger.debug("logout response");
-            Response response = authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
-            event.success();
-            return response;
-        }
-
-        protected Response handleSamlRequest(String samlRequest, String relayState) {
-            SAMLDocumentHolder documentHolder = extractRequestDocument(samlRequest);
-            if (documentHolder == null) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_TOKEN);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-
-            SAML2Object samlObject = documentHolder.getSamlObject();
-
-            RequestAbstractType requestAbstractType = (RequestAbstractType) samlObject;
-            String issuer = requestAbstractType.getIssuer().getValue();
-            ClientModel client = realm.getClientByClientId(issuer);
-
-            if (client == null) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.CLIENT_NOT_FOUND);
-                return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
-            }
-
-            if (!client.isEnabled()) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.CLIENT_DISABLED);
-                return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
-            }
-            if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.NOT_ALLOWED);
-                return ErrorPage.error(session, Messages.BEARER_ONLY);
-            }
-            if (client.isDirectGrantsOnly()) {
-                event.event(EventType.LOGIN);
-                event.error(Errors.NOT_ALLOWED);
-                return ErrorPage.error(session, Messages.DIRECT_GRANTS_ONLY);
-            }
-
-            session.getContext().setClient(client);
-
-            try {
-                verifySignature(documentHolder, client);
-            } catch (VerificationException e) {
-                SamlService.logger.error("request validation failed", e);
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_SIGNATURE);
-                return ErrorPage.error(session, Messages.INVALID_REQUESTER);
-            }
-            logger.debug("verified request");
-            if (samlObject instanceof AuthnRequestType) {
-                logger.debug("** login request");
-                event.event(EventType.LOGIN);
-                // Get the SAML Request Message
-                AuthnRequestType authn = (AuthnRequestType) samlObject;
-                return loginRequest(relayState, authn, client);
-            } else if (samlObject instanceof LogoutRequestType) {
-                logger.debug("** logout request");
-                event.event(EventType.LOGOUT);
-                LogoutRequestType logout = (LogoutRequestType) samlObject;
-                return logoutRequest(logout, client, relayState);
-
-            } else {
-                event.event(EventType.LOGIN);
-                event.error(Errors.INVALID_TOKEN);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-        }
-
-        protected abstract void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException;
-
-        protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
-
-        protected abstract SAMLDocumentHolder extractResponseDocument(String response);
-
-        protected Response loginRequest(String relayState, AuthnRequestType requestAbstractType, ClientModel client) {
-            // validate destination
-            if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
-                event.detail(Details.REASON, "invalid_destination");
-                event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-            String bindingType = getBindingType(requestAbstractType);
-            if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
-                bindingType = SamlProtocol.SAML_POST_BINDING;
-            String redirect = null;
-            URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL();
-            if (redirectUri != null && !"null".equals(redirectUri)) {  // "null" is for testing purposes
-                redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client);
-            } else {
-                if (bindingType.equals(SamlProtocol.SAML_POST_BINDING)) {
-                    redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
-                } else {
-                    redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
-                }
-                if (redirect == null) {
-                    redirect = client.getManagementUrl();
-                }
-
-            }
-
-            if (redirect == null) {
-                event.error(Errors.INVALID_REDIRECT_URI);
-                return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
-            }
-
-
-            ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
-            clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
-            clientSession.setRedirectUri(redirect);
-            clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-            clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
-            clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
-            clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
-            clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
-
-            // Handle NameIDPolicy from SP
-            NameIDPolicyType nameIdPolicy = requestAbstractType.getNameIDPolicy();
-            if (nameIdPolicy != null && !SamlProtocol.forceNameIdFormat(client)) {
-                String nameIdFormat = nameIdPolicy.getFormat().toString();
-                // TODO: Handle AllowCreate too, relevant for persistent NameID.
-                if (isSupportedNameIdFormat(nameIdFormat)) {
-                    clientSession.setNote(GeneralConstants.NAMEID_FORMAT, nameIdFormat);
-                } else {
-                    event.detail(Details.REASON, "unsupported_nameid_format");
-                    event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
-                    return ErrorPage.error(session, Messages.UNSUPPORTED_NAME_ID_FORMAT);
-                }
-            }
-
-            return newBrowserAuthentication(clientSession);
-        }
-
-
-
-
-
-        private String getBindingType(AuthnRequestType requestAbstractType) {
-            URI requestedProtocolBinding = requestAbstractType.getProtocolBinding();
-
-            if (requestedProtocolBinding != null) {
-                if (JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get().equals(requestedProtocolBinding.toString())) {
-                    return SamlProtocol.SAML_POST_BINDING;
-                } else {
-                    return SamlProtocol.SAML_REDIRECT_BINDING;
-                }
-            }
-
-            return getBindingType();
-        }
-
-        private boolean isSupportedNameIdFormat(String nameIdFormat) {
-            if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get()) ||
-                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()) ||
-                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get()) ||
-                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())) {
-                return true;
-            }
-            return false;
-        }
-
-        protected abstract String getBindingType();
-
-        protected Response logoutRequest(LogoutRequestType logoutRequest, ClientModel client, String relayState) {
-            // validate destination
-            if (logoutRequest.getDestination() != null && !uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
-                event.detail(Details.REASON, "invalid_destination");
-                event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
-                return ErrorPage.error(session, Messages.INVALID_REQUEST);
-            }
-
-            // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
-            AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
-            if (authResult != null) {
-                String logoutBinding = getBindingType();
-                if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
-                    logoutBinding = SamlProtocol.SAML_POST_BINDING;
-                String bindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
-                UserSessionModel userSession = authResult.getSession();
-                userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING_URI, bindingUri);
-                if (SamlProtocol.requiresRealmSignature(client)) {
-                    userSession.setNote(SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM, SamlProtocol.getSignatureAlgorithm(client).toString());
-
-                }
-                if (relayState != null) userSession.setNote(SamlProtocol.SAML_LOGOUT_RELAY_STATE, relayState);
-                userSession.setNote(SamlProtocol.SAML_LOGOUT_REQUEST_ID, logoutRequest.getID());
-                userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
-                userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
-                // remove client from logout requests
-                for (ClientSessionModel clientSession : userSession.getClientSessions()) {
-                    if (clientSession.getClient().getId().equals(client.getId())) {
-                        clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-                    }
-                }
-                logger.debug("browser Logout");
-                return authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
-            } else if (logoutRequest.getSessionIndex() != null) {
-                for (String sessionIndex : logoutRequest.getSessionIndex()) {
-                    ClientSessionModel clientSession = session.sessions().getClientSession(realm, sessionIndex);
-                    if (clientSession == null) continue;
-                    UserSessionModel userSession = clientSession.getUserSession();
-                    if (clientSession.getClient().getClientId().equals(client.getClientId())) {
-                        // remove requesting client from logout
-                        clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-
-                        // Remove also other clientSessions of this client as there could be more in this UserSession
-                        if (userSession != null) {
-                            for (ClientSessionModel clientSession2 : userSession.getClientSessions()) {
-                                if (clientSession2.getClient().getId().equals(client.getId())) {
-                                    clientSession2.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-                                }
-                            }
-                        }
-                    }
-
-                    try {
-                        authManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
-                    } catch (Exception e) {
-                        logger.warn("Failure with backchannel logout", e);
-                    }
-
-                }
-
-            }
-
-            // default
-
-            String logoutBinding = getBindingType();
-            String logoutBindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
-            String logoutRelayState = relayState;
-            SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
-            builder.logoutRequestID(logoutRequest.getID());
-            builder.destination(logoutBindingUri);
-            builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
-            builder.relayState(logoutRelayState);
-            if (SamlProtocol.requiresRealmSignature(client)) {
-                SignatureAlgorithm algorithm = SamlProtocol.getSignatureAlgorithm(client);
-                builder.signatureAlgorithm(algorithm)
-                        .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
-                        .signDocument();
-
-            }
-            try {
-                if (SamlProtocol.SAML_POST_BINDING.equals(logoutBinding)) {
-                    return builder.postBinding().response(logoutBindingUri);
-                } else {
-                    return builder.redirectBinding().response(logoutBindingUri);
-                }
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        private boolean checkSsl() {
-            if (uriInfo.getBaseUri().getScheme().equals("https")) {
-                return true;
-            } else {
-                return !realm.getSslRequired().isRequired(clientConnection);
-            }
-        }
-    }
-
-
-    protected class PostBindingProtocol extends BindingProtocol {
-
-        @Override
-        protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
-            SamlProtocolUtils.verifyDocumentSignature(client, documentHolder.getSamlDocument());
-        }
-
-        @Override
-        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
-            return SAMLRequestParser.parseRequestPostBinding(samlRequest);
-        }
-
-        @Override
-        protected SAMLDocumentHolder extractResponseDocument(String response) {
-            return SAMLRequestParser.parseResponsePostBinding(response);
-        }
-
-        @Override
-        protected String getBindingType() {
-            return SamlProtocol.SAML_POST_BINDING;
-        }
-
-
-        public Response execute(String samlRequest, String samlResponse, String relayState) {
-            Response response = basicChecks(samlRequest, samlResponse);
-            if (response != null) return response;
-            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
-            else return handleSamlResponse(samlResponse, relayState);
-        }
-
-    }
-
-    protected class RedirectBindingProtocol extends BindingProtocol {
-
-        @Override
-        protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
-            if (!"true".equals(client.getAttribute("saml.client.signature"))) {
-                return;
-            }
-            PublicKey publicKey = SamlProtocolUtils.getSignatureValidationKey(client);
-            SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
-        }
-
-
-        @Override
-        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
-            return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
-        }
-
-        @Override
-        protected SAMLDocumentHolder extractResponseDocument(String response) {
-            return SAMLRequestParser.parseRequestRedirectBinding(response);
-        }
-
-        @Override
-        protected String getBindingType() {
-            return SamlProtocol.SAML_REDIRECT_BINDING;
-        }
-
-
-        public Response execute(String samlRequest, String samlResponse, String relayState) {
-            Response response = basicChecks(samlRequest, samlResponse);
-            if (response != null) return response;
-            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
-            else return handleSamlResponse(samlResponse, relayState);
-        }
-
-    }
-
-
-    private Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
-        logger.debug("Automatically redirect to identity provider: " + providerId);
-        return Response.temporaryRedirect(
-                Urls.identityProviderAuthnRequest(uriInfo.getBaseUri(), providerId, realm.getName(), accessCode))
-                .build();
-    }
-
-    protected Response newBrowserAuthentication(ClientSessionModel clientSession) {
-        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
-        for (IdentityProviderModel identityProvider : identityProviders) {
-            if (identityProvider.isAuthenticateByDefault()) {
-                return buildRedirectToIdentityProvider(identityProvider.getAlias(), new ClientSessionCode(realm, clientSession).getCode() );
-            }
-        }
-        AuthenticationFlowModel flow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
-        String flowId = flow.getId();
-        AuthenticationProcessor processor = new AuthenticationProcessor();
-        processor.setClientSession(clientSession)
-                .setFlowId(flowId)
-                .setConnection(clientConnection)
-                .setEventBuilder(event)
-                .setProtector(authManager.getProtector())
-                .setRealm(realm)
-                .setSession(session)
-                .setUriInfo(uriInfo)
-                .setRequest(request);
-
-        try {
-            return processor.authenticate();
-        } catch (Exception e) {
-            return processor.handleBrowserException(e);
-        }
-    }
-
-
-
-    /**
-     */
-    @GET
-    public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
-                                    @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
-                                    @QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
-        logger.debug("SAML GET");
-        return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
-    }
-
-
-    /**
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
-                                @FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
-                                @FormParam(GeneralConstants.RELAY_STATE) String relayState) {
-        logger.debug("SAML POST");
-        return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState);
-    }
-
-    @GET
-    @Path("descriptor")
-    @Produces(MediaType.APPLICATION_XML)
-    public String getDescriptor() throws Exception {
-        InputStream is = getClass().getResourceAsStream("/idp-metadata-template.xml");
-        String template = StreamUtil.readString(is);
-        template = template.replace("${idp.entityID}", RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
-        template = template.replace("${idp.sso.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
-        template = template.replace("${idp.sso.HTTP-Redirect}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
-        template = template.replace("${idp.sls.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
-        template = template.replace("${idp.signing.certificate}", realm.getCertificatePem());
-        return template;
-
-    }
-
-    @GET
-    @Path("clients/{client}")
-    @Produces(MediaType.TEXT_HTML)
-    public Response idpInitiatedSSO(@PathParam("client") String clientUrlName,
-                                    @QueryParam("RelayState") String relayState) {
-        event.event(EventType.LOGIN);
-        ClientModel client = null;
-        for (ClientModel c : realm.getClients()) {
-            String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME);
-            if (urlName == null) continue;
-            if (urlName.equals(clientUrlName)) {
-                client = c;
-                break;
-            }
-        }
-        if (client == null) {
-            event.error(Errors.CLIENT_NOT_FOUND);
-            return ErrorPage.error(session, Messages.CLIENT_NOT_FOUND);
-        }
-        if (client.getManagementUrl() == null
-                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null
-                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) == null) {
-            logger.error("SAML assertion consumer url not set up");
-            event.error(Errors.INVALID_REDIRECT_URI);
-            return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
-        }
-
-        String bindingType = SamlProtocol.SAML_POST_BINDING;
-        if (client.getManagementUrl() == null
-                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null
-                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) != null) {
-            bindingType = SamlProtocol.SAML_REDIRECT_BINDING;
-        }
-
-        String redirect = null;
-        if (bindingType.equals(SamlProtocol.SAML_REDIRECT_BINDING)) {
-            redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
-        } else {
-            redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
-        }
-        if (redirect == null) {
-            redirect = client.getManagementUrl();
-        }
-
-        ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
-        clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
-        clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
-        clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
-        clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
-        clientSession.setRedirectUri(redirect);
-
-        if (relayState == null) {
-            relayState = client.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_RELAY_STATE);
-        }
-        if (relayState != null && !relayState.trim().equals("")) {
-            clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
-        }
-
-
-        return newBrowserAuthentication(clientSession);
-
-    }
-
-}
+package org.keycloak.protocol.saml;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.ClientConnection;
+import org.keycloak.VerificationException;
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.dom.saml.v2.SAML2Object;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
+import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.utils.RedirectUtils;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.services.ErrorPage;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.util.StreamUtil;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.PublicKey;
+import java.util.List;
+
+/**
+ * Resource class for the oauth/openid connect token service
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlService {
+
+    protected static final Logger logger = Logger.getLogger(SamlService.class);
+
+    protected RealmModel realm;
+    private EventBuilder event;
+    protected AuthenticationManager authManager;
+
+    @Context
+    protected Providers providers;
+    @Context
+    protected SecurityContext securityContext;
+    @Context
+    protected UriInfo uriInfo;
+    @Context
+    protected HttpHeaders headers;
+    @Context
+    protected HttpRequest request;
+    @Context
+    protected HttpResponse response;
+    @Context
+    protected KeycloakSession session;
+    @Context
+    protected ClientConnection clientConnection;
+
+    /*
+    @Context
+    protected ResourceContext resourceContext;
+    */
+
+    public SamlService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
+        this.realm = realm;
+        this.event = event;
+        this.authManager = authManager;
+    }
+
+    public abstract class BindingProtocol {
+        protected Response basicChecks(String samlRequest, String samlResponse) {
+            if (!checkSsl()) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.SSL_REQUIRED);
+                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
+            }
+            if (!realm.isEnabled()) {
+                event.event(EventType.LOGIN_ERROR);
+                event.error(Errors.REALM_DISABLED);
+                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
+            }
+
+            if (samlRequest == null && samlResponse == null) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_TOKEN);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+
+            }
+            return null;
+        }
+
+        protected Response handleSamlResponse(String samlResponse, String relayState) {
+            event.event(EventType.LOGOUT);
+            SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
+            StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
+            // validate destination
+            if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
+                event.detail(Details.REASON, "invalid_destination");
+                event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+
+            AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
+            if (authResult == null) {
+                logger.warn("Unknown saml response.");
+                event.event(EventType.LOGOUT);
+                event.error(Errors.INVALID_TOKEN);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+            // assume this is a logout response
+            UserSessionModel userSession = authResult.getSession();
+            if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
+                logger.warn("Unknown saml response.");
+                logger.warn("UserSession is not tagged as logging out.");
+                event.event(EventType.LOGOUT);
+                event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+            logger.debug("logout response");
+            Response response = authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
+            event.success();
+            return response;
+        }
+
+        protected Response handleSamlRequest(String samlRequest, String relayState) {
+            SAMLDocumentHolder documentHolder = extractRequestDocument(samlRequest);
+            if (documentHolder == null) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_TOKEN);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+
+            SAML2Object samlObject = documentHolder.getSamlObject();
+
+            RequestAbstractType requestAbstractType = (RequestAbstractType) samlObject;
+            String issuer = requestAbstractType.getIssuer().getValue();
+            ClientModel client = realm.getClientByClientId(issuer);
+
+            if (client == null) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.CLIENT_NOT_FOUND);
+                return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
+            }
+
+            if (!client.isEnabled()) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.CLIENT_DISABLED);
+                return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
+            }
+            if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.NOT_ALLOWED);
+                return ErrorPage.error(session, Messages.BEARER_ONLY);
+            }
+            if (client.isDirectGrantsOnly()) {
+                event.event(EventType.LOGIN);
+                event.error(Errors.NOT_ALLOWED);
+                return ErrorPage.error(session, Messages.DIRECT_GRANTS_ONLY);
+            }
+
+            session.getContext().setClient(client);
+
+            try {
+                verifySignature(documentHolder, client);
+            } catch (VerificationException e) {
+                SamlService.logger.error("request validation failed", e);
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_SIGNATURE);
+                return ErrorPage.error(session, Messages.INVALID_REQUESTER);
+            }
+            logger.debug("verified request");
+            if (samlObject instanceof AuthnRequestType) {
+                logger.debug("** login request");
+                event.event(EventType.LOGIN);
+                // Get the SAML Request Message
+                AuthnRequestType authn = (AuthnRequestType) samlObject;
+                return loginRequest(relayState, authn, client);
+            } else if (samlObject instanceof LogoutRequestType) {
+                logger.debug("** logout request");
+                event.event(EventType.LOGOUT);
+                LogoutRequestType logout = (LogoutRequestType) samlObject;
+                return logoutRequest(logout, client, relayState);
+
+            } else {
+                event.event(EventType.LOGIN);
+                event.error(Errors.INVALID_TOKEN);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+        }
+
+        protected abstract void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException;
+
+        protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
+
+        protected abstract SAMLDocumentHolder extractResponseDocument(String response);
+
+        protected Response loginRequest(String relayState, AuthnRequestType requestAbstractType, ClientModel client) {
+            // validate destination
+            if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
+                event.detail(Details.REASON, "invalid_destination");
+                event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+            String bindingType = getBindingType(requestAbstractType);
+            if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
+                bindingType = SamlProtocol.SAML_POST_BINDING;
+            String redirect = null;
+            URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL();
+            if (redirectUri != null && !"null".equals(redirectUri)) {  // "null" is for testing purposes
+                redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client);
+            } else {
+                if (bindingType.equals(SamlProtocol.SAML_POST_BINDING)) {
+                    redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
+                } else {
+                    redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
+                }
+                if (redirect == null) {
+                    redirect = client.getManagementUrl();
+                }
+
+            }
+
+            if (redirect == null) {
+                event.error(Errors.INVALID_REDIRECT_URI);
+                return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
+            }
+
+
+            ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+            clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
+            clientSession.setRedirectUri(redirect);
+            clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+            clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
+            clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
+            clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
+            clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
+
+            // Handle NameIDPolicy from SP
+            NameIDPolicyType nameIdPolicy = requestAbstractType.getNameIDPolicy();
+            if (nameIdPolicy != null && !SamlProtocol.forceNameIdFormat(client)) {
+                String nameIdFormat = nameIdPolicy.getFormat().toString();
+                // TODO: Handle AllowCreate too, relevant for persistent NameID.
+                if (isSupportedNameIdFormat(nameIdFormat)) {
+                    clientSession.setNote(GeneralConstants.NAMEID_FORMAT, nameIdFormat);
+                } else {
+                    event.detail(Details.REASON, "unsupported_nameid_format");
+                    event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
+                    return ErrorPage.error(session, Messages.UNSUPPORTED_NAME_ID_FORMAT);
+                }
+            }
+
+            return newBrowserAuthentication(clientSession);
+        }
+
+
+
+
+
+        private String getBindingType(AuthnRequestType requestAbstractType) {
+            URI requestedProtocolBinding = requestAbstractType.getProtocolBinding();
+
+            if (requestedProtocolBinding != null) {
+                if (JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get().equals(requestedProtocolBinding.toString())) {
+                    return SamlProtocol.SAML_POST_BINDING;
+                } else {
+                    return SamlProtocol.SAML_REDIRECT_BINDING;
+                }
+            }
+
+            return getBindingType();
+        }
+
+        private boolean isSupportedNameIdFormat(String nameIdFormat) {
+            if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get()) ||
+                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()) ||
+                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get()) ||
+                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())) {
+                return true;
+            }
+            return false;
+        }
+
+        protected abstract String getBindingType();
+
+        protected Response logoutRequest(LogoutRequestType logoutRequest, ClientModel client, String relayState) {
+            // validate destination
+            if (logoutRequest.getDestination() != null && !uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
+                event.detail(Details.REASON, "invalid_destination");
+                event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
+            }
+
+            // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
+            AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
+            if (authResult != null) {
+                String logoutBinding = getBindingType();
+                if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
+                    logoutBinding = SamlProtocol.SAML_POST_BINDING;
+                String bindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
+                UserSessionModel userSession = authResult.getSession();
+                userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING_URI, bindingUri);
+                if (SamlProtocol.requiresRealmSignature(client)) {
+                    userSession.setNote(SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM, SamlProtocol.getSignatureAlgorithm(client).toString());
+
+                }
+                if (relayState != null) userSession.setNote(SamlProtocol.SAML_LOGOUT_RELAY_STATE, relayState);
+                userSession.setNote(SamlProtocol.SAML_LOGOUT_REQUEST_ID, logoutRequest.getID());
+                userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
+                userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
+                // remove client from logout requests
+                for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+                    if (clientSession.getClient().getId().equals(client.getId())) {
+                        clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+                    }
+                }
+                logger.debug("browser Logout");
+                return authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
+            } else if (logoutRequest.getSessionIndex() != null) {
+                for (String sessionIndex : logoutRequest.getSessionIndex()) {
+                    ClientSessionModel clientSession = session.sessions().getClientSession(realm, sessionIndex);
+                    if (clientSession == null) continue;
+                    UserSessionModel userSession = clientSession.getUserSession();
+                    if (clientSession.getClient().getClientId().equals(client.getClientId())) {
+                        // remove requesting client from logout
+                        clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+
+                        // Remove also other clientSessions of this client as there could be more in this UserSession
+                        if (userSession != null) {
+                            for (ClientSessionModel clientSession2 : userSession.getClientSessions()) {
+                                if (clientSession2.getClient().getId().equals(client.getId())) {
+                                    clientSession2.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+                                }
+                            }
+                        }
+                    }
+
+                    try {
+                        authManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
+                    } catch (Exception e) {
+                        logger.warn("Failure with backchannel logout", e);
+                    }
+
+                }
+
+            }
+
+            // default
+
+            String logoutBinding = getBindingType();
+            String logoutBindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
+            String logoutRelayState = relayState;
+            SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
+            builder.logoutRequestID(logoutRequest.getID());
+            builder.destination(logoutBindingUri);
+            builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
+            builder.relayState(logoutRelayState);
+            if (SamlProtocol.requiresRealmSignature(client)) {
+                SignatureAlgorithm algorithm = SamlProtocol.getSignatureAlgorithm(client);
+                builder.signatureAlgorithm(algorithm)
+                        .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
+                        .signDocument();
+
+            }
+            try {
+                if (SamlProtocol.SAML_POST_BINDING.equals(logoutBinding)) {
+                    return builder.postBinding().response(logoutBindingUri);
+                } else {
+                    return builder.redirectBinding().response(logoutBindingUri);
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        private boolean checkSsl() {
+            if (uriInfo.getBaseUri().getScheme().equals("https")) {
+                return true;
+            } else {
+                return !realm.getSslRequired().isRequired(clientConnection);
+            }
+        }
+    }
+
+
+    protected class PostBindingProtocol extends BindingProtocol {
+
+        @Override
+        protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
+            SamlProtocolUtils.verifyDocumentSignature(client, documentHolder.getSamlDocument());
+        }
+
+        @Override
+        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
+            return SAMLRequestParser.parseRequestPostBinding(samlRequest);
+        }
+
+        @Override
+        protected SAMLDocumentHolder extractResponseDocument(String response) {
+            return SAMLRequestParser.parseResponsePostBinding(response);
+        }
+
+        @Override
+        protected String getBindingType() {
+            return SamlProtocol.SAML_POST_BINDING;
+        }
+
+
+        public Response execute(String samlRequest, String samlResponse, String relayState) {
+            Response response = basicChecks(samlRequest, samlResponse);
+            if (response != null) return response;
+            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
+            else return handleSamlResponse(samlResponse, relayState);
+        }
+
+    }
+
+    protected class RedirectBindingProtocol extends BindingProtocol {
+
+        @Override
+        protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
+            if (!"true".equals(client.getAttribute("saml.client.signature"))) {
+                return;
+            }
+            PublicKey publicKey = SamlProtocolUtils.getSignatureValidationKey(client);
+            SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
+        }
+
+
+        @Override
+        protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
+            return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
+        }
+
+        @Override
+        protected SAMLDocumentHolder extractResponseDocument(String response) {
+            return SAMLRequestParser.parseRequestRedirectBinding(response);
+        }
+
+        @Override
+        protected String getBindingType() {
+            return SamlProtocol.SAML_REDIRECT_BINDING;
+        }
+
+
+        public Response execute(String samlRequest, String samlResponse, String relayState) {
+            Response response = basicChecks(samlRequest, samlResponse);
+            if (response != null) return response;
+            if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
+            else return handleSamlResponse(samlResponse, relayState);
+        }
+
+    }
+
+
+    private Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
+        logger.debug("Automatically redirect to identity provider: " + providerId);
+        return Response.temporaryRedirect(
+                Urls.identityProviderAuthnRequest(uriInfo.getBaseUri(), providerId, realm.getName(), accessCode))
+                .build();
+    }
+
+    protected Response newBrowserAuthentication(ClientSessionModel clientSession) {
+        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
+        for (IdentityProviderModel identityProvider : identityProviders) {
+            if (identityProvider.isAuthenticateByDefault()) {
+                return buildRedirectToIdentityProvider(identityProvider.getAlias(), new ClientSessionCode(realm, clientSession).getCode() );
+            }
+        }
+        AuthenticationFlowModel flow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
+        String flowId = flow.getId();
+        AuthenticationProcessor processor = new AuthenticationProcessor();
+        processor.setClientSession(clientSession)
+                .setFlowId(flowId)
+                .setConnection(clientConnection)
+                .setEventBuilder(event)
+                .setProtector(authManager.getProtector())
+                .setRealm(realm)
+                .setSession(session)
+                .setUriInfo(uriInfo)
+                .setRequest(request);
+
+        try {
+            return processor.authenticate();
+        } catch (Exception e) {
+            return processor.handleBrowserException(e);
+        }
+    }
+
+
+
+    /**
+     */
+    @GET
+    public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
+                                    @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
+                                    @QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
+        logger.debug("SAML GET");
+        return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
+    }
+
+
+    /**
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
+                                @FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
+                                @FormParam(GeneralConstants.RELAY_STATE) String relayState) {
+        logger.debug("SAML POST");
+        return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState);
+    }
+
+    @GET
+    @Path("descriptor")
+    @Produces(MediaType.APPLICATION_XML)
+    public String getDescriptor() throws Exception {
+        InputStream is = getClass().getResourceAsStream("/idp-metadata-template.xml");
+        String template = StreamUtil.readString(is);
+        template = template.replace("${idp.entityID}", RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
+        template = template.replace("${idp.sso.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
+        template = template.replace("${idp.sso.HTTP-Redirect}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
+        template = template.replace("${idp.sls.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
+        template = template.replace("${idp.signing.certificate}", realm.getCertificatePem());
+        return template;
+
+    }
+
+    @GET
+    @Path("clients/{client}")
+    @Produces(MediaType.TEXT_HTML)
+    public Response idpInitiatedSSO(@PathParam("client") String clientUrlName,
+                                    @QueryParam("RelayState") String relayState) {
+        event.event(EventType.LOGIN);
+        ClientModel client = null;
+        for (ClientModel c : realm.getClients()) {
+            String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME);
+            if (urlName == null) continue;
+            if (urlName.equals(clientUrlName)) {
+                client = c;
+                break;
+            }
+        }
+        if (client == null) {
+            event.error(Errors.CLIENT_NOT_FOUND);
+            return ErrorPage.error(session, Messages.CLIENT_NOT_FOUND);
+        }
+        if (client.getManagementUrl() == null
+                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null
+                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) == null) {
+            logger.error("SAML assertion consumer url not set up");
+            event.error(Errors.INVALID_REDIRECT_URI);
+            return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
+        }
+
+        String bindingType = SamlProtocol.SAML_POST_BINDING;
+        if (client.getManagementUrl() == null
+                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null
+                && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) != null) {
+            bindingType = SamlProtocol.SAML_REDIRECT_BINDING;
+        }
+
+        String redirect = null;
+        if (bindingType.equals(SamlProtocol.SAML_REDIRECT_BINDING)) {
+            redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
+        } else {
+            redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
+        }
+        if (redirect == null) {
+            redirect = client.getManagementUrl();
+        }
+
+        ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+        clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
+        clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
+        clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
+        clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
+        clientSession.setRedirectUri(redirect);
+
+        if (relayState == null) {
+            relayState = client.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_RELAY_STATE);
+        }
+        if (relayState != null && !relayState.trim().equals("")) {
+            clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
+        }
+
+
+        return newBrowserAuthentication(clientSession);
+
+    }
+
+}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SignatureAlgorithm.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SignatureAlgorithm.java
index e169201..b10f0ce 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SignatureAlgorithm.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SignatureAlgorithm.java
@@ -1,69 +1,69 @@
-package org.keycloak.protocol.saml;
-
-import java.security.Signature;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public enum SignatureAlgorithm {
-    RSA_SHA1("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withRSA"),
-    RSA_SHA256("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256", "SHA256withRSA"),
-    RSA_SHA512("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512", "SHA512withRSA"),
-    DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withDSA")
-    ;
-    private final String xmlSignatureMethod;
-    private final String xmlSignatureDigestMethod;
-    private final String javaSignatureAlgorithm;
-
-    private static final Map<String, SignatureAlgorithm> signatureMethodMap = new HashMap<>();
-    private static final Map<String, SignatureAlgorithm> signatureDigestMethodMap = new HashMap<>();
-
-    static {
-        signatureMethodMap.put(RSA_SHA1.getXmlSignatureMethod(), RSA_SHA1);
-        signatureMethodMap.put(RSA_SHA256.getXmlSignatureMethod(), RSA_SHA256);
-        signatureMethodMap.put(RSA_SHA512.getXmlSignatureMethod(), RSA_SHA512);
-        signatureMethodMap.put(DSA_SHA1.getXmlSignatureMethod(), DSA_SHA1);
-
-        signatureDigestMethodMap.put(RSA_SHA1.getXmlSignatureDigestMethod(), RSA_SHA1);
-        signatureDigestMethodMap.put(RSA_SHA256.getXmlSignatureDigestMethod(), RSA_SHA256);
-        signatureDigestMethodMap.put(RSA_SHA512.getXmlSignatureDigestMethod(), RSA_SHA512);
-        signatureDigestMethodMap.put(DSA_SHA1.getXmlSignatureDigestMethod(), DSA_SHA1);
-    }
-
-    public static SignatureAlgorithm getFromXmlMethod(String xml) {
-        return signatureMethodMap.get(xml);
-    }
-
-    public static SignatureAlgorithm getFromXmlDigest(String xml) {
-        return signatureDigestMethodMap.get(xml);
-    }
-
-    SignatureAlgorithm(String xmlSignatureMethod, String xmlSignatureDigestMethod, String javaSignatureAlgorithm) {
-        this.xmlSignatureMethod = xmlSignatureMethod;
-        this.xmlSignatureDigestMethod = xmlSignatureDigestMethod;
-        this.javaSignatureAlgorithm = javaSignatureAlgorithm;
-    }
-
-    public String getXmlSignatureMethod() {
-        return xmlSignatureMethod;
-    }
-
-    public String getXmlSignatureDigestMethod() {
-        return xmlSignatureDigestMethod;
-    }
-
-    public String getJavaSignatureAlgorithm() {
-        return javaSignatureAlgorithm;
-    }
-
-    public Signature createSignature() {
-        try {
-            return Signature.getInstance(javaSignatureAlgorithm);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
+package org.keycloak.protocol.saml;
+
+import java.security.Signature;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public enum SignatureAlgorithm {
+    RSA_SHA1("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withRSA"),
+    RSA_SHA256("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256", "SHA256withRSA"),
+    RSA_SHA512("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512", "SHA512withRSA"),
+    DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withDSA")
+    ;
+    private final String xmlSignatureMethod;
+    private final String xmlSignatureDigestMethod;
+    private final String javaSignatureAlgorithm;
+
+    private static final Map<String, SignatureAlgorithm> signatureMethodMap = new HashMap<>();
+    private static final Map<String, SignatureAlgorithm> signatureDigestMethodMap = new HashMap<>();
+
+    static {
+        signatureMethodMap.put(RSA_SHA1.getXmlSignatureMethod(), RSA_SHA1);
+        signatureMethodMap.put(RSA_SHA256.getXmlSignatureMethod(), RSA_SHA256);
+        signatureMethodMap.put(RSA_SHA512.getXmlSignatureMethod(), RSA_SHA512);
+        signatureMethodMap.put(DSA_SHA1.getXmlSignatureMethod(), DSA_SHA1);
+
+        signatureDigestMethodMap.put(RSA_SHA1.getXmlSignatureDigestMethod(), RSA_SHA1);
+        signatureDigestMethodMap.put(RSA_SHA256.getXmlSignatureDigestMethod(), RSA_SHA256);
+        signatureDigestMethodMap.put(RSA_SHA512.getXmlSignatureDigestMethod(), RSA_SHA512);
+        signatureDigestMethodMap.put(DSA_SHA1.getXmlSignatureDigestMethod(), DSA_SHA1);
+    }
+
+    public static SignatureAlgorithm getFromXmlMethod(String xml) {
+        return signatureMethodMap.get(xml);
+    }
+
+    public static SignatureAlgorithm getFromXmlDigest(String xml) {
+        return signatureDigestMethodMap.get(xml);
+    }
+
+    SignatureAlgorithm(String xmlSignatureMethod, String xmlSignatureDigestMethod, String javaSignatureAlgorithm) {
+        this.xmlSignatureMethod = xmlSignatureMethod;
+        this.xmlSignatureDigestMethod = xmlSignatureDigestMethod;
+        this.javaSignatureAlgorithm = javaSignatureAlgorithm;
+    }
+
+    public String getXmlSignatureMethod() {
+        return xmlSignatureMethod;
+    }
+
+    public String getXmlSignatureDigestMethod() {
+        return xmlSignatureDigestMethod;
+    }
+
+    public String getJavaSignatureAlgorithm() {
+        return javaSignatureAlgorithm;
+    }
+
+    public Signature createSignature() {
+        try {
+            return Signature.getInstance(javaSignatureAlgorithm);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
index 392feae..58e10db 100755
--- a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
+++ b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -1,8 +1,8 @@
-org.keycloak.protocol.saml.mappers.RoleListMapper
-org.keycloak.protocol.saml.mappers.RoleNameMapper
-org.keycloak.protocol.saml.mappers.HardcodedRole
-org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
-org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
-org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
-
-
+org.keycloak.protocol.saml.mappers.RoleListMapper
+org.keycloak.protocol.saml.mappers.RoleNameMapper
+org.keycloak.protocol.saml.mappers.HardcodedRole
+org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
+org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
+org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
+
+

services/pom.xml 428(+214 -214)

diff --git a/services/pom.xml b/services/pom.xml
index b3017a0..da71e9a 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -1,214 +1,214 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-services</artifactId>
-    <name>Keycloak REST Services</name>
-    <description />
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core-jaxrs</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-connections-http-client</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-forms-common-freemarker</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-account-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-email-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-login-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-invalidation-cache-model</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-timer-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-timer-basic</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-export-import-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <scope>provided</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <configuration>
-                    <subpackages>org.keycloak.services.resources.admin:org.keycloak.protocol.oidc</subpackages>
-                    <doclet>com.lunatech.doclets.jax.jaxrs.JAXRSDoclet</doclet>
-                    <docletArtifacts>
-                        <docletArtifact>
-                            <groupId>com.lunatech.jax-doclets</groupId>
-                            <artifactId>doclets</artifactId>
-                            <version>0.10.2</version>
-                        </docletArtifact>
-                    </docletArtifacts>
-                    <detectOfflineLinks>false</detectOfflineLinks>
-                    <offlineLinks>
-                        <offlineLink>
-                            <url>../javadocs</url>
-                            <location>${project.basedir}/../target/site/apidocs</location>
-                        </offlineLink>
-                    </offlineLinks>
-                    <additionalparam>-disablejavascriptexample</additionalparam>
-                    <additionalparam>-pathexcludefilter '/admin/.*index.*' -pathexcludefilter '/admin' -pathexcludefilter '/admin/\\{realm\\}/console.*'</additionalparam>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-services</artifactId>
+    <name>Keycloak REST Services</name>
+    <description />
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-connections-http-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-forms-common-freemarker</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-account-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-email-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-login-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-timer-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-timer-basic</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-export-import-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <subpackages>org.keycloak.services.resources.admin:org.keycloak.protocol.oidc</subpackages>
+                    <doclet>com.lunatech.doclets.jax.jaxrs.JAXRSDoclet</doclet>
+                    <docletArtifacts>
+                        <docletArtifact>
+                            <groupId>com.lunatech.jax-doclets</groupId>
+                            <artifactId>doclets</artifactId>
+                            <version>0.10.2</version>
+                        </docletArtifact>
+                    </docletArtifacts>
+                    <detectOfflineLinks>false</detectOfflineLinks>
+                    <offlineLinks>
+                        <offlineLink>
+                            <url>../javadocs</url>
+                            <location>${project.basedir}/../target/site/apidocs</location>
+                        </offlineLink>
+                    </offlineLinks>
+                    <additionalparam>-disablejavascriptexample</additionalparam>
+                    <additionalparam>-pathexcludefilter '/admin/.*index.*' -pathexcludefilter '/admin' -pathexcludefilter '/admin/\\{realm\\}/console.*'</additionalparam>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/AuthenticationFlow.java
index 0d208c7..c95f25d 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationFlow.java
@@ -1,15 +1,15 @@
-package org.keycloak.authentication;
-
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface AuthenticationFlow {
-    String BASIC_FLOW = "basic-flow";
-    String FORM_FLOW = "form-flow";
-
-    Response processAction(String actionExecution);
-    Response processFlow();
-}
+package org.keycloak.authentication;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AuthenticationFlow {
+    String BASIC_FLOW = "basic-flow";
+    String FORM_FLOW = "form-flow";
+
+    Response processAction(String actionExecution);
+    Response processFlow();
+}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index a81b74c..436762f 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -1,623 +1,623 @@
-package org.keycloak.authentication;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.authentication.authenticators.AbstractFormAuthenticator;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.services.ErrorPage;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationProcessor {
-    public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution";
-    protected static Logger logger = Logger.getLogger(AuthenticationProcessor.class);
-    protected RealmModel realm;
-    protected UserSessionModel userSession;
-    protected ClientSessionModel clientSession;
-    protected ClientConnection connection;
-    protected UriInfo uriInfo;
-    protected KeycloakSession session;
-    protected BruteForceProtector protector;
-    protected EventBuilder event;
-    protected HttpRequest request;
-    protected String flowId;
-    /**
-     * This could be an error message forwarded from brokering when the broker failed authentication
-     * and we want to continue authentication locally.  forwardedErrorMessage can then be displayed by
-     * whatever form is challenging.
-     */
-    protected String forwardedErrorMessage;
-    protected boolean userSessionCreated;
-
-
-    public static enum Status {
-        SUCCESS,
-        CHALLENGE,
-        FORCE_CHALLENGE,
-        FAILURE_CHALLENGE,
-        FAILED,
-        ATTEMPTED
-
-    }
-
-    public static enum Error {
-        EXPIRED_CODE,
-        INVALID_CLIENT_SESSION,
-        INVALID_USER,
-        INVALID_CREDENTIALS,
-        CREDENTIAL_SETUP_REQUIRED,
-        USER_DISABLED,
-        USER_CONFLICT,
-        USER_TEMPORARILY_DISABLED,
-        INTERNAL_ERROR,
-        UNKNOWN_USER
-    }
-
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    public ClientSessionModel getClientSession() {
-        return clientSession;
-    }
-
-    public ClientConnection getConnection() {
-        return connection;
-    }
-
-    public UriInfo getUriInfo() {
-        return uriInfo;
-    }
-
-    public KeycloakSession getSession() {
-        return session;
-    }
-
-    public UserSessionModel getUserSession() {
-        return userSession;
-    }
-
-    public boolean isUserSessionCreated() {
-        return userSessionCreated;
-    }
-
-    public AuthenticationProcessor setRealm(RealmModel realm) {
-        this.realm = realm;
-        return this;
-    }
-
-    public AuthenticationProcessor setClientSession(ClientSessionModel clientSession) {
-        this.clientSession = clientSession;
-        return this;
-    }
-
-    public AuthenticationProcessor setConnection(ClientConnection connection) {
-        this.connection = connection;
-        return this;
-    }
-
-    public AuthenticationProcessor setUriInfo(UriInfo uriInfo) {
-        this.uriInfo = uriInfo;
-        return this;
-    }
-
-    public AuthenticationProcessor setSession(KeycloakSession session) {
-        this.session = session;
-        return this;
-    }
-
-    public AuthenticationProcessor setProtector(BruteForceProtector protector) {
-        this.protector = protector;
-        return this;
-    }
-
-    public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) {
-        this.event = eventBuilder;
-        return this;
-    }
-
-    public AuthenticationProcessor setRequest(HttpRequest request) {
-        this.request = request;
-        return this;
-    }
-
-    public AuthenticationProcessor setFlowId(String flowId) {
-        this.flowId = flowId;
-        return this;
-    }
-
-    public AuthenticationProcessor setForwardedErrorMessage(String forwardedErrorMessage) {
-        this.forwardedErrorMessage = forwardedErrorMessage;
-        return this;
-    }
-
-    public String generateCode() {
-        ClientSessionCode accessCode = new ClientSessionCode(getRealm(), getClientSession());
-        clientSession.setTimestamp(Time.currentTime());
-        return accessCode.getCode();
-    }
-
-    public EventBuilder newEvent() {
-        this.event = new EventBuilder(realm, session, connection);
-        return this.event;
-    }
-
-    public EventBuilder getEvent() {
-        return event;
-    }
-
-    public HttpRequest getRequest() {
-        return request;
-    }
-
-    public void setAutheticatedUser(UserModel user) {
-        UserModel previousUser = clientSession.getAuthenticatedUser();
-        if (previousUser != null && !user.getId().equals(previousUser.getId()))
-            throw new AuthException(Error.USER_CONFLICT);
-        validateUser(user);
-        getClientSession().setAuthenticatedUser(user);
-    }
-
-
-    private class Result implements AuthenticatorContext {
-        AuthenticatorConfigModel authenticatorConfig;
-        AuthenticationExecutionModel execution;
-        Authenticator authenticator;
-        Status status;
-        Response challenge;
-        Error error;
-        List<AuthenticationExecutionModel> currentExecutions;
-
-        private Result(AuthenticationExecutionModel execution, Authenticator authenticator, List<AuthenticationExecutionModel> currentExecutions) {
-            this.execution = execution;
-            this.authenticator = authenticator;
-            this.currentExecutions = currentExecutions;
-        }
-
-        @Override
-        public EventBuilder newEvent() {
-            return AuthenticationProcessor.this.newEvent();
-        }
-
-        @Override
-        public AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory) {
-            List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(execution.getParentFlow());
-            for (AuthenticationExecutionModel exe : executions) {
-                AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, exe.getAuthenticator());
-                if (factory != null && factory.getReferenceCategory().equals(authenticatorCategory)) {
-                    return exe.getRequirement();
-                }
-
-            }
-            return null;
-        }
-
-        @Override
-        public AuthenticationExecutionModel getExecution() {
-            return execution;
-        }
-
-        @Override
-        public void setExecution(AuthenticationExecutionModel execution) {
-            this.execution = execution;
-        }
-
-        @Override
-        public AuthenticatorConfigModel getAuthenticatorConfig() {
-            if (execution.getAuthenticatorConfig() == null) return null;
-            if (authenticatorConfig != null) return authenticatorConfig;
-            authenticatorConfig = realm.getAuthenticatorConfigById(execution.getAuthenticatorConfig());
-            return authenticatorConfig;
-        }
-
-        @Override
-        public Authenticator getAuthenticator() {
-            return authenticator;
-        }
-
-        @Override
-        public void setAuthenticator(Authenticator authenticator) {
-            this.authenticator = authenticator;
-        }
-
-        @Override
-        public Status getStatus() {
-            return status;
-        }
-
-        @Override
-        public void success() {
-            this.status = Status.SUCCESS;
-        }
-
-        @Override
-        public void failure(Error error) {
-            status = Status.FAILED;
-            this.error = error;
-
-        }
-
-        @Override
-        public void challenge(Response challenge) {
-            this.status = Status.CHALLENGE;
-            this.challenge = challenge;
-
-        }
-
-        @Override
-        public void forceChallenge(Response challenge) {
-            this.status = Status.FORCE_CHALLENGE;
-            this.challenge = challenge;
-
-        }
-
-        @Override
-        public void failureChallenge(Error error, Response challenge) {
-            this.error = error;
-            this.status = Status.FAILURE_CHALLENGE;
-            this.challenge = challenge;
-
-        }
-
-        @Override
-        public void failure(Error error, Response challenge) {
-            this.error = error;
-            this.status = Status.FAILED;
-            this.challenge = challenge;
-
-        }
-
-        @Override
-        public void attempted() {
-            this.status = Status.ATTEMPTED;
-
-        }
-
-        @Override
-        public UserModel getUser() {
-            return getClientSession().getAuthenticatedUser();
-        }
-
-        @Override
-        public void setUser(UserModel user) {
-            setAutheticatedUser(user);
-        }
-
-        @Override
-        public RealmModel getRealm() {
-            return AuthenticationProcessor.this.getRealm();
-        }
-
-        @Override
-        public ClientSessionModel getClientSession() {
-            return AuthenticationProcessor.this.getClientSession();
-        }
-
-        @Override
-        public ClientConnection getConnection() {
-            return AuthenticationProcessor.this.getConnection();
-        }
-
-        @Override
-        public UriInfo getUriInfo() {
-            return AuthenticationProcessor.this.getUriInfo();
-        }
-
-        @Override
-        public KeycloakSession getSession() {
-            return AuthenticationProcessor.this.getSession();
-        }
-
-        @Override
-        public HttpRequest getHttpRequest() {
-            return AuthenticationProcessor.this.request;
-        }
-
-        @Override
-        public void attachUserSession(UserSessionModel userSession) {
-            AuthenticationProcessor.this.userSession = userSession;
-        }
-
-        @Override
-        public BruteForceProtector getProtector() {
-            return AuthenticationProcessor.this.protector;
-        }
-
-        @Override
-        public EventBuilder getEvent() {
-            return AuthenticationProcessor.this.event;
-        }
-
-        @Override
-        public String getForwardedErrorMessage() {
-            return AuthenticationProcessor.this.forwardedErrorMessage;
-        }
-
-        @Override
-        public String generateAccessCode() {
-            return generateCode();
-        }
-
-
-        @Override
-        public Response getChallenge() {
-            return challenge;
-        }
-
-        @Override
-        public Error getError() {
-            return error;
-        }
-    }
-
-    public static class AuthException extends RuntimeException {
-        private Error error;
-
-        public AuthException(Error error) {
-            this.error = error;
-        }
-
-        public AuthException(String message, Error error) {
-            super(message);
-            this.error = error;
-        }
-
-        public AuthException(String message, Throwable cause, Error error) {
-            super(message, cause);
-            this.error = error;
-        }
-
-        public AuthException(Throwable cause, Error error) {
-            super(cause);
-            this.error = error;
-        }
-
-        public AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Error error) {
-            super(message, cause, enableSuppression, writableStackTrace);
-            this.error = error;
-        }
-
-        public Error getError() {
-            return error;
-        }
-    }
-
-    public void logFailure() {
-        if (realm.isBruteForceProtected()) {
-            String username = clientSession.getNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME);
-            // todo need to handle non form failures
-            if (username == null) {
-
-            } else {
-                protector.failedLogin(realm, username, connection);
-
-            }
-        }
-    }
-
-    public boolean isSuccessful(AuthenticationExecutionModel model) {
-        ClientSessionModel.ExecutionStatus status = clientSession.getExecutionStatus().get(model.getId());
-        if (status == null) return false;
-        return status == ClientSessionModel.ExecutionStatus.SUCCESS;
-    }
-
-    public Response handleBrowserException(Exception failure) {
-        if (failure instanceof AuthException) {
-            AuthException e = (AuthException) failure;
-            logger.error("failed authentication: " + e.getError().toString(), e);
-            if (e.getError() == AuthenticationProcessor.Error.INVALID_USER) {
-                event.error(Errors.USER_NOT_FOUND);
-                return ErrorPage.error(session, Messages.INVALID_USER);
-            } else if (e.getError() == AuthenticationProcessor.Error.USER_DISABLED) {
-                event.error(Errors.USER_DISABLED);
-                return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
-            } else if (e.getError() == AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED) {
-                event.error(Errors.USER_TEMPORARILY_DISABLED);
-                return ErrorPage.error(session, Messages.ACCOUNT_TEMPORARILY_DISABLED);
-
-            } else if (e.getError() == Error.INVALID_CLIENT_SESSION) {
-                event.error(Errors.INVALID_CODE);
-                return ErrorPage.error(session, Messages.INVALID_CODE);
-
-            } else if (e.getError() == Error.EXPIRED_CODE) {
-                event.error(Errors.EXPIRED_CODE);
-                return ErrorPage.error(session, Messages.EXPIRED_CODE);
-
-            } else {
-                event.error(Errors.INVALID_USER_CREDENTIALS);
-                return ErrorPage.error(session, Messages.INVALID_USER);
-            }
-
-        } else {
-            logger.error("failed authentication", failure);
-            event.error(Errors.INVALID_USER_CREDENTIALS);
-            return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
-        }
-
-    }
-
-    public AuthenticationFlow createFlowExecution(String flowId, AuthenticationExecutionModel execution) {
-        AuthenticationFlowModel flow = realm.getAuthenticationFlowById(flowId);
-        if (flow == null) {
-            logger.error("Unknown flow to execute with");
-            throw new AuthException(Error.INTERNAL_ERROR);
-        }
-        if (flow.getProviderId() == null || flow.getProviderId().equals(AuthenticationFlow.BASIC_FLOW)) {
-            DefaultAuthenticationFlow flowExecution = new DefaultAuthenticationFlow(this, flow);
-            return flowExecution;
-
-        } else if (flow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
-            FormAuthenticationFlow flowExecution = new FormAuthenticationFlow(this, execution);
-            return flowExecution;
-        }
-        throw new AuthException("Unknown flow provider type", Error.INTERNAL_ERROR);
-    }
-
-    public Response authenticate() throws AuthException {
-        checkClientSession();
-        logger.debug("AUTHENTICATE");
-        event.client(clientSession.getClient().getClientId())
-                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
-                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
-        String authType = clientSession.getNote(Details.AUTH_TYPE);
-        if (authType != null) {
-            event.detail(Details.AUTH_TYPE, authType);
-        }
-        UserModel authUser = clientSession.getAuthenticatedUser();
-        validateUser(authUser);
-        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
-        Response challenge = authenticationFlow.processFlow();
-        if (challenge != null) return challenge;
-        if (clientSession.getAuthenticatedUser() == null) {
-            throw new AuthException(Error.UNKNOWN_USER);
-        }
-        return authenticationComplete();
-    }
-
-    public static void resetFlow(ClientSessionModel clientSession) {
-        clientSession.setAuthenticatedUser(null);
-        clientSession.clearExecutionStatus();
-        clientSession.clearUserSessionNotes();
-        clientSession.removeNote(CURRENT_AUTHENTICATION_EXECUTION);
-    }
-
-    public Response authenticationAction(String execution) {
-        checkClientSession();
-        String current = clientSession.getNote(CURRENT_AUTHENTICATION_EXECUTION);
-        if (!execution.equals(current)) {
-            logger.debug("Current execution does not equal executed execution.  Might be a page refresh");
-            logFailure();
-            resetFlow(clientSession);
-            return authenticate();
-        }
-        AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
-        if (model == null) {
-            logger.debug("Cannot find execution, reseting flow");
-            logFailure();
-            resetFlow(clientSession);
-            return authenticate();
-        }
-        event.client(clientSession.getClient().getClientId())
-                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
-                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
-        String authType = clientSession.getNote(Details.AUTH_TYPE);
-        if (authType != null) {
-            event.detail(Details.AUTH_TYPE, authType);
-        }
-
-        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, model);
-        Response challenge = authenticationFlow.processAction(execution);
-        if (challenge != null) return challenge;
-        if (clientSession.getAuthenticatedUser() == null) {
-            throw new AuthException(Error.UNKNOWN_USER);
-        }
-        return authenticationComplete();
-    }
-
-    public void checkClientSession() {
-        ClientSessionCode code = new ClientSessionCode(realm, clientSession);
-        if (!code.isValidAction(ClientSessionModel.Action.AUTHENTICATE.name())) {
-            throw new AuthException(Error.INVALID_CLIENT_SESSION);
-        }
-        if (!code.isActionActive(ClientSessionModel.Action.AUTHENTICATE.name())) {
-            throw new AuthException(Error.EXPIRED_CODE);
-        }
-        clientSession.setTimestamp(Time.currentTime());
-    }
-
-    public Response authenticateOnly() throws AuthException {
-        checkClientSession();
-        event.client(clientSession.getClient().getClientId())
-                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
-                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
-        String authType = clientSession.getNote(Details.AUTH_TYPE);
-        if (authType != null) {
-            event.detail(Details.AUTH_TYPE, authType);
-        }
-        UserModel authUser = clientSession.getAuthenticatedUser();
-        validateUser(authUser);
-        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
-        Response challenge = authenticationFlow.processFlow();
-        if (challenge != null) return challenge;
-
-        String username = clientSession.getAuthenticatedUser().getUsername();
-        if (userSession == null) { // if no authenticator attached a usersession
-            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), "form", false, null, null);
-            userSession.setState(UserSessionModel.State.LOGGING_IN);
-            userSessionCreated = true;
-        }
-        TokenManager.attachClientSession(userSession, clientSession);
-        event.user(userSession.getUser())
-                .detail(Details.USERNAME, username)
-                .session(userSession);
-
-        return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
-    }
-
-    public Response finishAuthentication() {
-        event.success();
-        RealmModel realm = clientSession.getRealm();
-        return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, connection);
-
-    }
-
-    public void validateUser(UserModel authenticatedUser) {
-        if (authenticatedUser != null) {
-            if (!authenticatedUser.isEnabled()) throw new AuthException(Error.USER_DISABLED);
-        }
-        if (realm.isBruteForceProtected()) {
-            if (protector.isTemporarilyDisabled(session, realm, authenticatedUser.getUsername())) {
-                throw new AuthException(Error.USER_TEMPORARILY_DISABLED);
-            }
-        }
-    }
-
-    protected Response authenticationComplete() {
-        String username = clientSession.getAuthenticatedUser().getUsername();
-        String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
-        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
-        if (userSession == null) { // if no authenticator attached a usersession
-            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
-            userSession.setState(UserSessionModel.State.LOGGING_IN);
-        }
-        if (remember) {
-            event.detail(Details.REMEMBER_ME, "true");
-        }
-        TokenManager.attachClientSession(userSession, clientSession);
-        event.user(userSession.getUser())
-                .detail(Details.USERNAME, username)
-                .session(userSession);
-
-        return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, connection, request, uriInfo, event);
-
-    }
-
-    public AuthenticatorContext createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List<AuthenticationExecutionModel> executions) {
-        return new Result(model, authenticator, executions);
-    }
-
-
-}
+package org.keycloak.authentication;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.authentication.authenticators.AbstractFormAuthenticator;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.services.ErrorPage;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationProcessor {
+    public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution";
+    protected static Logger logger = Logger.getLogger(AuthenticationProcessor.class);
+    protected RealmModel realm;
+    protected UserSessionModel userSession;
+    protected ClientSessionModel clientSession;
+    protected ClientConnection connection;
+    protected UriInfo uriInfo;
+    protected KeycloakSession session;
+    protected BruteForceProtector protector;
+    protected EventBuilder event;
+    protected HttpRequest request;
+    protected String flowId;
+    /**
+     * This could be an error message forwarded from brokering when the broker failed authentication
+     * and we want to continue authentication locally.  forwardedErrorMessage can then be displayed by
+     * whatever form is challenging.
+     */
+    protected String forwardedErrorMessage;
+    protected boolean userSessionCreated;
+
+
+    public static enum Status {
+        SUCCESS,
+        CHALLENGE,
+        FORCE_CHALLENGE,
+        FAILURE_CHALLENGE,
+        FAILED,
+        ATTEMPTED
+
+    }
+
+    public static enum Error {
+        EXPIRED_CODE,
+        INVALID_CLIENT_SESSION,
+        INVALID_USER,
+        INVALID_CREDENTIALS,
+        CREDENTIAL_SETUP_REQUIRED,
+        USER_DISABLED,
+        USER_CONFLICT,
+        USER_TEMPORARILY_DISABLED,
+        INTERNAL_ERROR,
+        UNKNOWN_USER
+    }
+
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    public ClientSessionModel getClientSession() {
+        return clientSession;
+    }
+
+    public ClientConnection getConnection() {
+        return connection;
+    }
+
+    public UriInfo getUriInfo() {
+        return uriInfo;
+    }
+
+    public KeycloakSession getSession() {
+        return session;
+    }
+
+    public UserSessionModel getUserSession() {
+        return userSession;
+    }
+
+    public boolean isUserSessionCreated() {
+        return userSessionCreated;
+    }
+
+    public AuthenticationProcessor setRealm(RealmModel realm) {
+        this.realm = realm;
+        return this;
+    }
+
+    public AuthenticationProcessor setClientSession(ClientSessionModel clientSession) {
+        this.clientSession = clientSession;
+        return this;
+    }
+
+    public AuthenticationProcessor setConnection(ClientConnection connection) {
+        this.connection = connection;
+        return this;
+    }
+
+    public AuthenticationProcessor setUriInfo(UriInfo uriInfo) {
+        this.uriInfo = uriInfo;
+        return this;
+    }
+
+    public AuthenticationProcessor setSession(KeycloakSession session) {
+        this.session = session;
+        return this;
+    }
+
+    public AuthenticationProcessor setProtector(BruteForceProtector protector) {
+        this.protector = protector;
+        return this;
+    }
+
+    public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) {
+        this.event = eventBuilder;
+        return this;
+    }
+
+    public AuthenticationProcessor setRequest(HttpRequest request) {
+        this.request = request;
+        return this;
+    }
+
+    public AuthenticationProcessor setFlowId(String flowId) {
+        this.flowId = flowId;
+        return this;
+    }
+
+    public AuthenticationProcessor setForwardedErrorMessage(String forwardedErrorMessage) {
+        this.forwardedErrorMessage = forwardedErrorMessage;
+        return this;
+    }
+
+    public String generateCode() {
+        ClientSessionCode accessCode = new ClientSessionCode(getRealm(), getClientSession());
+        clientSession.setTimestamp(Time.currentTime());
+        return accessCode.getCode();
+    }
+
+    public EventBuilder newEvent() {
+        this.event = new EventBuilder(realm, session, connection);
+        return this.event;
+    }
+
+    public EventBuilder getEvent() {
+        return event;
+    }
+
+    public HttpRequest getRequest() {
+        return request;
+    }
+
+    public void setAutheticatedUser(UserModel user) {
+        UserModel previousUser = clientSession.getAuthenticatedUser();
+        if (previousUser != null && !user.getId().equals(previousUser.getId()))
+            throw new AuthException(Error.USER_CONFLICT);
+        validateUser(user);
+        getClientSession().setAuthenticatedUser(user);
+    }
+
+
+    private class Result implements AuthenticatorContext {
+        AuthenticatorConfigModel authenticatorConfig;
+        AuthenticationExecutionModel execution;
+        Authenticator authenticator;
+        Status status;
+        Response challenge;
+        Error error;
+        List<AuthenticationExecutionModel> currentExecutions;
+
+        private Result(AuthenticationExecutionModel execution, Authenticator authenticator, List<AuthenticationExecutionModel> currentExecutions) {
+            this.execution = execution;
+            this.authenticator = authenticator;
+            this.currentExecutions = currentExecutions;
+        }
+
+        @Override
+        public EventBuilder newEvent() {
+            return AuthenticationProcessor.this.newEvent();
+        }
+
+        @Override
+        public AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory) {
+            List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(execution.getParentFlow());
+            for (AuthenticationExecutionModel exe : executions) {
+                AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, exe.getAuthenticator());
+                if (factory != null && factory.getReferenceCategory().equals(authenticatorCategory)) {
+                    return exe.getRequirement();
+                }
+
+            }
+            return null;
+        }
+
+        @Override
+        public AuthenticationExecutionModel getExecution() {
+            return execution;
+        }
+
+        @Override
+        public void setExecution(AuthenticationExecutionModel execution) {
+            this.execution = execution;
+        }
+
+        @Override
+        public AuthenticatorConfigModel getAuthenticatorConfig() {
+            if (execution.getAuthenticatorConfig() == null) return null;
+            if (authenticatorConfig != null) return authenticatorConfig;
+            authenticatorConfig = realm.getAuthenticatorConfigById(execution.getAuthenticatorConfig());
+            return authenticatorConfig;
+        }
+
+        @Override
+        public Authenticator getAuthenticator() {
+            return authenticator;
+        }
+
+        @Override
+        public void setAuthenticator(Authenticator authenticator) {
+            this.authenticator = authenticator;
+        }
+
+        @Override
+        public Status getStatus() {
+            return status;
+        }
+
+        @Override
+        public void success() {
+            this.status = Status.SUCCESS;
+        }
+
+        @Override
+        public void failure(Error error) {
+            status = Status.FAILED;
+            this.error = error;
+
+        }
+
+        @Override
+        public void challenge(Response challenge) {
+            this.status = Status.CHALLENGE;
+            this.challenge = challenge;
+
+        }
+
+        @Override
+        public void forceChallenge(Response challenge) {
+            this.status = Status.FORCE_CHALLENGE;
+            this.challenge = challenge;
+
+        }
+
+        @Override
+        public void failureChallenge(Error error, Response challenge) {
+            this.error = error;
+            this.status = Status.FAILURE_CHALLENGE;
+            this.challenge = challenge;
+
+        }
+
+        @Override
+        public void failure(Error error, Response challenge) {
+            this.error = error;
+            this.status = Status.FAILED;
+            this.challenge = challenge;
+
+        }
+
+        @Override
+        public void attempted() {
+            this.status = Status.ATTEMPTED;
+
+        }
+
+        @Override
+        public UserModel getUser() {
+            return getClientSession().getAuthenticatedUser();
+        }
+
+        @Override
+        public void setUser(UserModel user) {
+            setAutheticatedUser(user);
+        }
+
+        @Override
+        public RealmModel getRealm() {
+            return AuthenticationProcessor.this.getRealm();
+        }
+
+        @Override
+        public ClientSessionModel getClientSession() {
+            return AuthenticationProcessor.this.getClientSession();
+        }
+
+        @Override
+        public ClientConnection getConnection() {
+            return AuthenticationProcessor.this.getConnection();
+        }
+
+        @Override
+        public UriInfo getUriInfo() {
+            return AuthenticationProcessor.this.getUriInfo();
+        }
+
+        @Override
+        public KeycloakSession getSession() {
+            return AuthenticationProcessor.this.getSession();
+        }
+
+        @Override
+        public HttpRequest getHttpRequest() {
+            return AuthenticationProcessor.this.request;
+        }
+
+        @Override
+        public void attachUserSession(UserSessionModel userSession) {
+            AuthenticationProcessor.this.userSession = userSession;
+        }
+
+        @Override
+        public BruteForceProtector getProtector() {
+            return AuthenticationProcessor.this.protector;
+        }
+
+        @Override
+        public EventBuilder getEvent() {
+            return AuthenticationProcessor.this.event;
+        }
+
+        @Override
+        public String getForwardedErrorMessage() {
+            return AuthenticationProcessor.this.forwardedErrorMessage;
+        }
+
+        @Override
+        public String generateAccessCode() {
+            return generateCode();
+        }
+
+
+        @Override
+        public Response getChallenge() {
+            return challenge;
+        }
+
+        @Override
+        public Error getError() {
+            return error;
+        }
+    }
+
+    public static class AuthException extends RuntimeException {
+        private Error error;
+
+        public AuthException(Error error) {
+            this.error = error;
+        }
+
+        public AuthException(String message, Error error) {
+            super(message);
+            this.error = error;
+        }
+
+        public AuthException(String message, Throwable cause, Error error) {
+            super(message, cause);
+            this.error = error;
+        }
+
+        public AuthException(Throwable cause, Error error) {
+            super(cause);
+            this.error = error;
+        }
+
+        public AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Error error) {
+            super(message, cause, enableSuppression, writableStackTrace);
+            this.error = error;
+        }
+
+        public Error getError() {
+            return error;
+        }
+    }
+
+    public void logFailure() {
+        if (realm.isBruteForceProtected()) {
+            String username = clientSession.getNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME);
+            // todo need to handle non form failures
+            if (username == null) {
+
+            } else {
+                protector.failedLogin(realm, username, connection);
+
+            }
+        }
+    }
+
+    public boolean isSuccessful(AuthenticationExecutionModel model) {
+        ClientSessionModel.ExecutionStatus status = clientSession.getExecutionStatus().get(model.getId());
+        if (status == null) return false;
+        return status == ClientSessionModel.ExecutionStatus.SUCCESS;
+    }
+
+    public Response handleBrowserException(Exception failure) {
+        if (failure instanceof AuthException) {
+            AuthException e = (AuthException) failure;
+            logger.error("failed authentication: " + e.getError().toString(), e);
+            if (e.getError() == AuthenticationProcessor.Error.INVALID_USER) {
+                event.error(Errors.USER_NOT_FOUND);
+                return ErrorPage.error(session, Messages.INVALID_USER);
+            } else if (e.getError() == AuthenticationProcessor.Error.USER_DISABLED) {
+                event.error(Errors.USER_DISABLED);
+                return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
+            } else if (e.getError() == AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED) {
+                event.error(Errors.USER_TEMPORARILY_DISABLED);
+                return ErrorPage.error(session, Messages.ACCOUNT_TEMPORARILY_DISABLED);
+
+            } else if (e.getError() == Error.INVALID_CLIENT_SESSION) {
+                event.error(Errors.INVALID_CODE);
+                return ErrorPage.error(session, Messages.INVALID_CODE);
+
+            } else if (e.getError() == Error.EXPIRED_CODE) {
+                event.error(Errors.EXPIRED_CODE);
+                return ErrorPage.error(session, Messages.EXPIRED_CODE);
+
+            } else {
+                event.error(Errors.INVALID_USER_CREDENTIALS);
+                return ErrorPage.error(session, Messages.INVALID_USER);
+            }
+
+        } else {
+            logger.error("failed authentication", failure);
+            event.error(Errors.INVALID_USER_CREDENTIALS);
+            return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
+        }
+
+    }
+
+    public AuthenticationFlow createFlowExecution(String flowId, AuthenticationExecutionModel execution) {
+        AuthenticationFlowModel flow = realm.getAuthenticationFlowById(flowId);
+        if (flow == null) {
+            logger.error("Unknown flow to execute with");
+            throw new AuthException(Error.INTERNAL_ERROR);
+        }
+        if (flow.getProviderId() == null || flow.getProviderId().equals(AuthenticationFlow.BASIC_FLOW)) {
+            DefaultAuthenticationFlow flowExecution = new DefaultAuthenticationFlow(this, flow);
+            return flowExecution;
+
+        } else if (flow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
+            FormAuthenticationFlow flowExecution = new FormAuthenticationFlow(this, execution);
+            return flowExecution;
+        }
+        throw new AuthException("Unknown flow provider type", Error.INTERNAL_ERROR);
+    }
+
+    public Response authenticate() throws AuthException {
+        checkClientSession();
+        logger.debug("AUTHENTICATE");
+        event.client(clientSession.getClient().getClientId())
+                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
+                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
+        String authType = clientSession.getNote(Details.AUTH_TYPE);
+        if (authType != null) {
+            event.detail(Details.AUTH_TYPE, authType);
+        }
+        UserModel authUser = clientSession.getAuthenticatedUser();
+        validateUser(authUser);
+        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
+        Response challenge = authenticationFlow.processFlow();
+        if (challenge != null) return challenge;
+        if (clientSession.getAuthenticatedUser() == null) {
+            throw new AuthException(Error.UNKNOWN_USER);
+        }
+        return authenticationComplete();
+    }
+
+    public static void resetFlow(ClientSessionModel clientSession) {
+        clientSession.setAuthenticatedUser(null);
+        clientSession.clearExecutionStatus();
+        clientSession.clearUserSessionNotes();
+        clientSession.removeNote(CURRENT_AUTHENTICATION_EXECUTION);
+    }
+
+    public Response authenticationAction(String execution) {
+        checkClientSession();
+        String current = clientSession.getNote(CURRENT_AUTHENTICATION_EXECUTION);
+        if (!execution.equals(current)) {
+            logger.debug("Current execution does not equal executed execution.  Might be a page refresh");
+            logFailure();
+            resetFlow(clientSession);
+            return authenticate();
+        }
+        AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
+        if (model == null) {
+            logger.debug("Cannot find execution, reseting flow");
+            logFailure();
+            resetFlow(clientSession);
+            return authenticate();
+        }
+        event.client(clientSession.getClient().getClientId())
+                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
+                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
+        String authType = clientSession.getNote(Details.AUTH_TYPE);
+        if (authType != null) {
+            event.detail(Details.AUTH_TYPE, authType);
+        }
+
+        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, model);
+        Response challenge = authenticationFlow.processAction(execution);
+        if (challenge != null) return challenge;
+        if (clientSession.getAuthenticatedUser() == null) {
+            throw new AuthException(Error.UNKNOWN_USER);
+        }
+        return authenticationComplete();
+    }
+
+    public void checkClientSession() {
+        ClientSessionCode code = new ClientSessionCode(realm, clientSession);
+        if (!code.isValidAction(ClientSessionModel.Action.AUTHENTICATE.name())) {
+            throw new AuthException(Error.INVALID_CLIENT_SESSION);
+        }
+        if (!code.isActionActive(ClientSessionModel.Action.AUTHENTICATE.name())) {
+            throw new AuthException(Error.EXPIRED_CODE);
+        }
+        clientSession.setTimestamp(Time.currentTime());
+    }
+
+    public Response authenticateOnly() throws AuthException {
+        checkClientSession();
+        event.client(clientSession.getClient().getClientId())
+                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
+                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
+        String authType = clientSession.getNote(Details.AUTH_TYPE);
+        if (authType != null) {
+            event.detail(Details.AUTH_TYPE, authType);
+        }
+        UserModel authUser = clientSession.getAuthenticatedUser();
+        validateUser(authUser);
+        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
+        Response challenge = authenticationFlow.processFlow();
+        if (challenge != null) return challenge;
+
+        String username = clientSession.getAuthenticatedUser().getUsername();
+        if (userSession == null) { // if no authenticator attached a usersession
+            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), "form", false, null, null);
+            userSession.setState(UserSessionModel.State.LOGGING_IN);
+            userSessionCreated = true;
+        }
+        TokenManager.attachClientSession(userSession, clientSession);
+        event.user(userSession.getUser())
+                .detail(Details.USERNAME, username)
+                .session(userSession);
+
+        return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
+    }
+
+    public Response finishAuthentication() {
+        event.success();
+        RealmModel realm = clientSession.getRealm();
+        return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, connection);
+
+    }
+
+    public void validateUser(UserModel authenticatedUser) {
+        if (authenticatedUser != null) {
+            if (!authenticatedUser.isEnabled()) throw new AuthException(Error.USER_DISABLED);
+        }
+        if (realm.isBruteForceProtected()) {
+            if (protector.isTemporarilyDisabled(session, realm, authenticatedUser.getUsername())) {
+                throw new AuthException(Error.USER_TEMPORARILY_DISABLED);
+            }
+        }
+    }
+
+    protected Response authenticationComplete() {
+        String username = clientSession.getAuthenticatedUser().getUsername();
+        String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
+        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
+        if (userSession == null) { // if no authenticator attached a usersession
+            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
+            userSession.setState(UserSessionModel.State.LOGGING_IN);
+        }
+        if (remember) {
+            event.detail(Details.REMEMBER_ME, "true");
+        }
+        TokenManager.attachClientSession(userSession, clientSession);
+        event.user(userSession.getUser())
+                .detail(Details.USERNAME, username)
+                .session(userSession);
+
+        return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, connection, request, uriInfo, event);
+
+    }
+
+    public AuthenticatorContext createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List<AuthenticationExecutionModel> executions) {
+        return new Result(model, authenticator, executions);
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/Authenticator.java b/services/src/main/java/org/keycloak/authentication/Authenticator.java
index ddde806..674f892 100755
--- a/services/src/main/java/org/keycloak/authentication/Authenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/Authenticator.java
@@ -1,26 +1,26 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.Provider;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public interface Authenticator extends Provider {
-    void authenticate(AuthenticatorContext context);
-    boolean requiresUser();
-    boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
-
-    /**
-     * Set actions to configure authenticator
-     *
-     */
-    void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
-
-    void action(AuthenticatorContext context);
-
-
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.Provider;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public interface Authenticator extends Provider {
+    void authenticate(AuthenticatorContext context);
+    boolean requiresUser();
+    boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
+
+    /**
+     * Set actions to configure authenticator
+     *
+     */
+    void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
+
+    void action(AuthenticatorContext context);
+
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
index 6da5e54..d6b5bf2 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
@@ -1,87 +1,87 @@
-package org.keycloak.authentication;
-
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.services.managers.BruteForceProtector;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface AuthenticatorContext {
-    EventBuilder getEvent();
-    EventBuilder newEvent();
-
-    AuthenticationExecutionModel getExecution();
-
-    void setExecution(AuthenticationExecutionModel execution);
-
-     UserModel getUser();
-
-    void setUser(UserModel user);
-
-    RealmModel getRealm();
-
-    ClientSessionModel getClientSession();
-    void attachUserSession(UserSessionModel userSession);
-
-    ClientConnection getConnection();
-
-    UriInfo getUriInfo();
-
-    KeycloakSession getSession();
-
-    HttpRequest getHttpRequest();
-    BruteForceProtector getProtector();
-
-
-    /**
-     * This could be an error message forwarded from brokering when the broker failed authentication
-     * and we want to continue authentication locally.  forwardedErrorMessage can then be displayed by
-     * whatever form is challenging.
-     */
-    String getForwardedErrorMessage();
-
-    /**
-     * Generates access code and updates clientsession timestamp
-     *
-     * @return
-     */
-    String generateAccessCode();
-
-    AuthenticatorConfigModel getAuthenticatorConfig();
-
-    Authenticator getAuthenticator();
-
-    void setAuthenticator(Authenticator authenticator);
-
-    AuthenticationProcessor.Status getStatus();
-
-    AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory);
-
-    void success();
-    void failure(AuthenticationProcessor.Error error);
-    void failure(AuthenticationProcessor.Error error, Response response);
-    void challenge(Response challenge);
-
-    void forceChallenge(Response challenge);
-
-    void failureChallenge(AuthenticationProcessor.Error error, Response challenge);
-    void attempted();
-
-
-    Response getChallenge();
-
-    AuthenticationProcessor.Error getError();
-}
+package org.keycloak.authentication;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.services.managers.BruteForceProtector;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface AuthenticatorContext {
+    EventBuilder getEvent();
+    EventBuilder newEvent();
+
+    AuthenticationExecutionModel getExecution();
+
+    void setExecution(AuthenticationExecutionModel execution);
+
+     UserModel getUser();
+
+    void setUser(UserModel user);
+
+    RealmModel getRealm();
+
+    ClientSessionModel getClientSession();
+    void attachUserSession(UserSessionModel userSession);
+
+    ClientConnection getConnection();
+
+    UriInfo getUriInfo();
+
+    KeycloakSession getSession();
+
+    HttpRequest getHttpRequest();
+    BruteForceProtector getProtector();
+
+
+    /**
+     * This could be an error message forwarded from brokering when the broker failed authentication
+     * and we want to continue authentication locally.  forwardedErrorMessage can then be displayed by
+     * whatever form is challenging.
+     */
+    String getForwardedErrorMessage();
+
+    /**
+     * Generates access code and updates clientsession timestamp
+     *
+     * @return
+     */
+    String generateAccessCode();
+
+    AuthenticatorConfigModel getAuthenticatorConfig();
+
+    Authenticator getAuthenticator();
+
+    void setAuthenticator(Authenticator authenticator);
+
+    AuthenticationProcessor.Status getStatus();
+
+    AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory);
+
+    void success();
+    void failure(AuthenticationProcessor.Error error);
+    void failure(AuthenticationProcessor.Error error, Response response);
+    void challenge(Response challenge);
+
+    void forceChallenge(Response challenge);
+
+    void failureChallenge(AuthenticationProcessor.Error error, Response challenge);
+    void attempted();
+
+
+    Response getChallenge();
+
+    AuthenticationProcessor.Error getError();
+}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
index 5f32b41..9ed9371 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
@@ -1,15 +1,15 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.provider.ConfiguredProvider;
-import org.keycloak.provider.ProviderFactory;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public interface AuthenticatorFactory extends ProviderFactory<Authenticator>, ConfigurableAuthenticatorFactory {
-    Authenticator create();
-
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.provider.ConfiguredProvider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public interface AuthenticatorFactory extends ProviderFactory<Authenticator>, ConfigurableAuthenticatorFactory {
+    Authenticator create();
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
index 98b906c..3fc7098 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
@@ -1,186 +1,186 @@
-package org.keycloak.authentication.authenticators;
-
-import org.jboss.logging.Logger;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorContext;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.LoginActionsService;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import java.net.URI;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractFormAuthenticator implements Authenticator {
-
-    private static final Logger logger = Logger.getLogger(AbstractFormAuthenticator.class);
-
-    public static final String REGISTRATION_FORM_ACTION = "registration_form";
-    public static final String EXECUTION = "execution";
-    public static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME";
-
-    @Override
-    public void action(AuthenticatorContext context) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    protected LoginFormsProvider loginForm(AuthenticatorContext context) {
-        String accessCode = context.generateAccessCode();
-        URI action = getActionUrl(context, accessCode);
-        LoginFormsProvider provider = context.getSession().getProvider(LoginFormsProvider.class)
-                    .setUser(context.getUser())
-                    .setActionUri(action)
-                    .setClientSessionCode(accessCode);
-        if (context.getForwardedErrorMessage() != null) {
-            provider.setError(context.getForwardedErrorMessage());
-        }
-        return provider;
-    }
-
-    public URI getActionUrl(AuthenticatorContext context, String code) {
-        return LoginActionsService.authenticationFormProcessor(context.getUriInfo())
-                .queryParam(OAuth2Constants.CODE, code)
-                .queryParam(EXECUTION, context.getExecution().getId())
-                    .build(context.getRealm().getName());
-    }
-
-    protected Response invalidUser(AuthenticatorContext context) {
-        return loginForm(context)
-                .setError(Messages.INVALID_USER)
-                .createLogin();
-    }
-
-    protected Response disabledUser(AuthenticatorContext context) {
-        return loginForm(context)
-                .setError(Messages.ACCOUNT_DISABLED).createLogin();
-    }
-
-    protected Response temporarilyDisabledUser(AuthenticatorContext context) {
-        return loginForm(context)
-                .setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).createLogin();
-    }
-
-    protected Response invalidCredentials(AuthenticatorContext context) {
-        return loginForm(context)
-                .setError(Messages.INVALID_USER).createLogin();
-    }
-
-    protected Response setDuplicateUserChallenge(AuthenticatorContext context, String eventError, String loginFormError, AuthenticationProcessor.Error authenticatorError) {
-        context.getEvent().error(eventError);
-        Response challengeResponse = loginForm(context)
-                .setError(loginFormError).createLogin();
-        context.failureChallenge(authenticatorError, challengeResponse);
-        return challengeResponse;
-    }
-
-    public boolean invalidUser(AuthenticatorContext context, UserModel user) {
-        if (user == null) {
-            context.getEvent().error(Errors.USER_NOT_FOUND);
-            Response challengeResponse = invalidUser(context);
-            context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
-            return true;
-        }
-        if (!user.isEnabled()) {
-            context.getEvent().user(user);
-            context.getEvent().error(Errors.USER_DISABLED);
-            Response challengeResponse = disabledUser(context);
-            context.failureChallenge(AuthenticationProcessor.Error.USER_DISABLED, challengeResponse);
-            return true;
-        }
-        if (context.getRealm().isBruteForceProtected()) {
-            if (context.getProtector().isTemporarilyDisabled(context.getSession(), context.getRealm(), user.getUsername())) {
-                context.getEvent().user(user);
-                context.getEvent().error(Errors.USER_TEMPORARILY_DISABLED);
-                Response challengeResponse = temporarilyDisabledUser(context);
-                context.failureChallenge(AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED, challengeResponse);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean validateUser(AuthenticatorContext context, MultivaluedMap<String, String> inputData) {
-        String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
-        if (username == null) {
-            context.getEvent().error(Errors.USER_NOT_FOUND);
-            Response challengeResponse = invalidUser(context);
-            context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
-            return false;
-        }
-        context.getEvent().detail(Details.USERNAME, username);
-        context.getClientSession().setNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME, username);
-
-        UserModel user = null;
-        try {
-            user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
-        } catch (ModelDuplicateException mde) {
-            logger.error(mde.getMessage(), mde);
-
-            // Could happen during federation import
-            if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {
-                setDuplicateUserChallenge(context, Errors.EMAIL_IN_USE, Messages.EMAIL_EXISTS, AuthenticationProcessor.Error.INVALID_USER);
-            } else {
-                setDuplicateUserChallenge(context, Errors.USERNAME_IN_USE, Messages.USERNAME_EXISTS, AuthenticationProcessor.Error.INVALID_USER);
-            }
-
-            return false;
-        }
-
-        if (invalidUser(context, user)) return false;
-        String rememberMe = inputData.getFirst("rememberMe");
-        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
-        if (remember) {
-            context.getClientSession().setNote(Details.REMEMBER_ME, "true");
-            context.getEvent().detail(Details.REMEMBER_ME, "true");
-        } else {
-            context.getClientSession().removeNote(Details.REMEMBER_ME);
-        }
-        context.setUser(user);
-        return true;
-    }
-
-    public boolean validatePassword(AuthenticatorContext context, MultivaluedMap<String, String> inputData) {
-        List<UserCredentialModel> credentials = new LinkedList<>();
-        String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
-        if (password == null) {
-            if (context.getUser() != null) {
-                context.getEvent().user(context.getUser());
-            }
-            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-            Response challengeResponse = invalidCredentials(context);
-            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
-            return false;
-        }
-        credentials.add(UserCredentialModel.password(password));
-        boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
-        if (!valid) {
-            context.getEvent().user(context.getUser());
-            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-            Response challengeResponse = invalidCredentials(context);
-            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
-            return false;
-        }
-        return true;
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.jboss.logging.Logger;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorContext;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.resources.LoginActionsService;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractFormAuthenticator implements Authenticator {
+
+    private static final Logger logger = Logger.getLogger(AbstractFormAuthenticator.class);
+
+    public static final String REGISTRATION_FORM_ACTION = "registration_form";
+    public static final String EXECUTION = "execution";
+    public static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME";
+
+    @Override
+    public void action(AuthenticatorContext context) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    protected LoginFormsProvider loginForm(AuthenticatorContext context) {
+        String accessCode = context.generateAccessCode();
+        URI action = getActionUrl(context, accessCode);
+        LoginFormsProvider provider = context.getSession().getProvider(LoginFormsProvider.class)
+                    .setUser(context.getUser())
+                    .setActionUri(action)
+                    .setClientSessionCode(accessCode);
+        if (context.getForwardedErrorMessage() != null) {
+            provider.setError(context.getForwardedErrorMessage());
+        }
+        return provider;
+    }
+
+    public URI getActionUrl(AuthenticatorContext context, String code) {
+        return LoginActionsService.authenticationFormProcessor(context.getUriInfo())
+                .queryParam(OAuth2Constants.CODE, code)
+                .queryParam(EXECUTION, context.getExecution().getId())
+                    .build(context.getRealm().getName());
+    }
+
+    protected Response invalidUser(AuthenticatorContext context) {
+        return loginForm(context)
+                .setError(Messages.INVALID_USER)
+                .createLogin();
+    }
+
+    protected Response disabledUser(AuthenticatorContext context) {
+        return loginForm(context)
+                .setError(Messages.ACCOUNT_DISABLED).createLogin();
+    }
+
+    protected Response temporarilyDisabledUser(AuthenticatorContext context) {
+        return loginForm(context)
+                .setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).createLogin();
+    }
+
+    protected Response invalidCredentials(AuthenticatorContext context) {
+        return loginForm(context)
+                .setError(Messages.INVALID_USER).createLogin();
+    }
+
+    protected Response setDuplicateUserChallenge(AuthenticatorContext context, String eventError, String loginFormError, AuthenticationProcessor.Error authenticatorError) {
+        context.getEvent().error(eventError);
+        Response challengeResponse = loginForm(context)
+                .setError(loginFormError).createLogin();
+        context.failureChallenge(authenticatorError, challengeResponse);
+        return challengeResponse;
+    }
+
+    public boolean invalidUser(AuthenticatorContext context, UserModel user) {
+        if (user == null) {
+            context.getEvent().error(Errors.USER_NOT_FOUND);
+            Response challengeResponse = invalidUser(context);
+            context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
+            return true;
+        }
+        if (!user.isEnabled()) {
+            context.getEvent().user(user);
+            context.getEvent().error(Errors.USER_DISABLED);
+            Response challengeResponse = disabledUser(context);
+            context.failureChallenge(AuthenticationProcessor.Error.USER_DISABLED, challengeResponse);
+            return true;
+        }
+        if (context.getRealm().isBruteForceProtected()) {
+            if (context.getProtector().isTemporarilyDisabled(context.getSession(), context.getRealm(), user.getUsername())) {
+                context.getEvent().user(user);
+                context.getEvent().error(Errors.USER_TEMPORARILY_DISABLED);
+                Response challengeResponse = temporarilyDisabledUser(context);
+                context.failureChallenge(AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED, challengeResponse);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean validateUser(AuthenticatorContext context, MultivaluedMap<String, String> inputData) {
+        String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
+        if (username == null) {
+            context.getEvent().error(Errors.USER_NOT_FOUND);
+            Response challengeResponse = invalidUser(context);
+            context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
+            return false;
+        }
+        context.getEvent().detail(Details.USERNAME, username);
+        context.getClientSession().setNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME, username);
+
+        UserModel user = null;
+        try {
+            user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
+        } catch (ModelDuplicateException mde) {
+            logger.error(mde.getMessage(), mde);
+
+            // Could happen during federation import
+            if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {
+                setDuplicateUserChallenge(context, Errors.EMAIL_IN_USE, Messages.EMAIL_EXISTS, AuthenticationProcessor.Error.INVALID_USER);
+            } else {
+                setDuplicateUserChallenge(context, Errors.USERNAME_IN_USE, Messages.USERNAME_EXISTS, AuthenticationProcessor.Error.INVALID_USER);
+            }
+
+            return false;
+        }
+
+        if (invalidUser(context, user)) return false;
+        String rememberMe = inputData.getFirst("rememberMe");
+        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
+        if (remember) {
+            context.getClientSession().setNote(Details.REMEMBER_ME, "true");
+            context.getEvent().detail(Details.REMEMBER_ME, "true");
+        } else {
+            context.getClientSession().removeNote(Details.REMEMBER_ME);
+        }
+        context.setUser(user);
+        return true;
+    }
+
+    public boolean validatePassword(AuthenticatorContext context, MultivaluedMap<String, String> inputData) {
+        List<UserCredentialModel> credentials = new LinkedList<>();
+        String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
+        if (password == null) {
+            if (context.getUser() != null) {
+                context.getEvent().user(context.getUser());
+            }
+            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
+            Response challengeResponse = invalidCredentials(context);
+            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
+            return false;
+        }
+        credentials.add(UserCredentialModel.password(password));
+        boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
+        if (!valid) {
+            context.getEvent().user(context.getUser());
+            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
+            Response challengeResponse = invalidCredentials(context);
+            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
index bbeb73e..0d5a1fb 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
@@ -1,53 +1,53 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorContext;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.services.managers.AuthenticationManager;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CookieAuthenticator implements Authenticator {
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public void authenticate(AuthenticatorContext context) {
-        AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(context.getSession(),
-                context.getRealm(), true);
-        if (authResult == null) {
-            context.attempted();
-        } else {
-            context.setUser(authResult.getUser());
-            context.attachUserSession(authResult.getSession());
-            context.success();
-        }
-
-    }
-
-    @Override
-    public void action(AuthenticatorContext context) {
-
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorContext;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.managers.AuthenticationManager;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CookieAuthenticator implements Authenticator {
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public void authenticate(AuthenticatorContext context) {
+        AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(context.getSession(),
+                context.getRealm(), true);
+        if (authResult == null) {
+            context.attempted();
+        } else {
+            context.setUser(authResult.getUser());
+            context.attachUserSession(authResult.getSession());
+            context.success();
+        }
+
+    }
+
+    @Override
+    public void action(AuthenticatorContext context) {
+
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticatorFactory.java
index 5889b8c..5dcc99e 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticatorFactory.java
@@ -1,82 +1,82 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorFactory;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CookieAuthenticatorFactory implements AuthenticatorFactory {
-    public static final String PROVIDER_ID = "auth-cookie";
-    static CookieAuthenticator SINGLETON = new CookieAuthenticator();
-    @Override
-    public Authenticator create() {
-        return SINGLETON;
-    }
-
-    @Override
-    public Authenticator create(KeycloakSession session) {
-        throw new IllegalStateException("illegal call");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return "cookie";
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {AuthenticationExecutionModel.Requirement.ALTERNATIVE, AuthenticationExecutionModel.Requirement.DISABLED};
-
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Cookie";
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Validates the SSO cookie set by the auth server.";
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CookieAuthenticatorFactory implements AuthenticatorFactory {
+    public static final String PROVIDER_ID = "auth-cookie";
+    static CookieAuthenticator SINGLETON = new CookieAuthenticator();
+    @Override
+    public Authenticator create() {
+        return SINGLETON;
+    }
+
+    @Override
+    public Authenticator create(KeycloakSession session) {
+        throw new IllegalStateException("illegal call");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return "cookie";
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {AuthenticationExecutionModel.Requirement.ALTERNATIVE, AuthenticationExecutionModel.Requirement.DISABLED};
+
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Cookie";
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Validates the SSO cookie set by the auth server.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
index 357e313..2df69f1 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
@@ -1,96 +1,96 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorContext;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.messages.Messages;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import java.net.URI;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OTPFormAuthenticator extends AbstractFormAuthenticator implements Authenticator {
-    public static final String TOTP_FORM_ACTION = "totp";
-
-    @Override
-    public void action(AuthenticatorContext context) {
-        validateOTP(context);
-    }
-
-    @Override
-    public void authenticate(AuthenticatorContext context) {
-        Response challengeResponse = challenge(context, null);
-        context.challenge(challengeResponse);
-    }
-
-    public void validateOTP(AuthenticatorContext context) {
-        MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
-        List<UserCredentialModel> credentials = new LinkedList<>();
-        String password = inputData.getFirst(CredentialRepresentation.TOTP);
-        if (password == null) {
-            Response challengeResponse = challenge(context, null);
-            context.challenge(challengeResponse);
-            return;
-        }
-        credentials.add(UserCredentialModel.totp(password));
-        boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
-        if (!valid) {
-            context.getEvent().user(context.getUser())
-                    .error(Errors.INVALID_USER_CREDENTIALS);
-            Response challengeResponse = challenge(context, Messages.INVALID_TOTP);
-            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
-            return;
-        }
-        context.success();
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return true;
-    }
-
-    protected Response challenge(AuthenticatorContext context, String error) {
-        String accessCode = context.generateAccessCode();
-        URI action = getActionUrl(context, accessCode);
-        LoginFormsProvider forms = context.getSession().getProvider(LoginFormsProvider.class)
-                .setActionUri(action)
-                .setClientSessionCode(accessCode);
-        if (error != null) forms.setError(error);
-
-        return forms.createLoginTotp();
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return session.users().configuredForCredentialType(UserCredentialModel.TOTP, realm, user) && user.isTotp();
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-        if (!user.getRequiredActions().contains(UserModel.RequiredAction.CONFIGURE_TOTP.name())) {
-            user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
-        }
-
-    }
-
-
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorContext;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.messages.Messages;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OTPFormAuthenticator extends AbstractFormAuthenticator implements Authenticator {
+    public static final String TOTP_FORM_ACTION = "totp";
+
+    @Override
+    public void action(AuthenticatorContext context) {
+        validateOTP(context);
+    }
+
+    @Override
+    public void authenticate(AuthenticatorContext context) {
+        Response challengeResponse = challenge(context, null);
+        context.challenge(challengeResponse);
+    }
+
+    public void validateOTP(AuthenticatorContext context) {
+        MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
+        List<UserCredentialModel> credentials = new LinkedList<>();
+        String password = inputData.getFirst(CredentialRepresentation.TOTP);
+        if (password == null) {
+            Response challengeResponse = challenge(context, null);
+            context.challenge(challengeResponse);
+            return;
+        }
+        credentials.add(UserCredentialModel.totp(password));
+        boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
+        if (!valid) {
+            context.getEvent().user(context.getUser())
+                    .error(Errors.INVALID_USER_CREDENTIALS);
+            Response challengeResponse = challenge(context, Messages.INVALID_TOTP);
+            context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
+            return;
+        }
+        context.success();
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return true;
+    }
+
+    protected Response challenge(AuthenticatorContext context, String error) {
+        String accessCode = context.generateAccessCode();
+        URI action = getActionUrl(context, accessCode);
+        LoginFormsProvider forms = context.getSession().getProvider(LoginFormsProvider.class)
+                .setActionUri(action)
+                .setClientSessionCode(accessCode);
+        if (error != null) forms.setError(error);
+
+        return forms.createLoginTotp();
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return session.users().configuredForCredentialType(UserCredentialModel.TOTP, realm, user) && user.isTotp();
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+        if (!user.getRequiredActions().contains(UserModel.RequiredAction.CONFIGURE_TOTP.name())) {
+            user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+        }
+
+    }
+
+
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticatorFactory.java
index dd222fe..2215d84 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticatorFactory.java
@@ -1,87 +1,87 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorFactory;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OTPFormAuthenticatorFactory implements AuthenticatorFactory {
-
-    public static final String PROVIDER_ID = "auth-otp-form";
-
-    @Override
-    public Authenticator create() {
-        return new OTPFormAuthenticator();
-    }
-
-    @Override
-    public Authenticator create(KeycloakSession session) {
-        throw new IllegalStateException("illegal call");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return UserCredentialModel.TOTP;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.OPTIONAL,
-            AuthenticationExecutionModel.Requirement.DISABLED};
-
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "OTP Form";
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Validates a OTP on a separate OTP form.";
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OTPFormAuthenticatorFactory implements AuthenticatorFactory {
+
+    public static final String PROVIDER_ID = "auth-otp-form";
+
+    @Override
+    public Authenticator create() {
+        return new OTPFormAuthenticator();
+    }
+
+    @Override
+    public Authenticator create(KeycloakSession session) {
+        throw new IllegalStateException("illegal call");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return UserCredentialModel.TOTP;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.OPTIONAL,
+            AuthenticationExecutionModel.Requirement.DISABLED};
+
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "OTP Form";
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Validates a OTP on a separate OTP form.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
index 0696e06..902deb3 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
@@ -1,167 +1,167 @@
-package org.keycloak.authentication.authenticators;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorContext;
-import org.keycloak.constants.KerberosConstants;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.services.messages.Messages;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.keycloak.util.HtmlUtils.escapeAttribute;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SpnegoAuthenticator extends AbstractFormAuthenticator implements Authenticator{
-    public static final String KERBEROS_DISABLED = "kerberos_disabled";
-    protected static Logger logger = Logger.getLogger(SpnegoAuthenticator.class);
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public void action(AuthenticatorContext context) {
-        context.attempted();
-        return;
-    }
-
-    @Override
-    public void authenticate(AuthenticatorContext context) {
-        HttpRequest request = context.getHttpRequest();
-        String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
-        if (authHeader == null) {
-            Response challenge = challengeNegotiation(context, null);
-            context.forceChallenge(challenge);
-            return;
-        }
-
-        String[] tokens = authHeader.split(" ");
-        if (tokens.length == 0) { // assume not supported
-            logger.debug("Invalid length of tokens: " + tokens.length);
-            context.attempted();
-            return;
-        }
-        if (!KerberosConstants.NEGOTIATE.equalsIgnoreCase(tokens[0])) {
-            logger.debug("Unknown scheme " + tokens[0]);
-            context.attempted();
-            return;
-        }
-        if (tokens.length != 2) {
-            context.failure(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
-            return;
-        }
-
-        String spnegoToken = tokens[1];
-        UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
-
-        CredentialValidationOutput output = context.getSession().users().validCredentials(context.getRealm(), spnegoCredential);
-
-        if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
-            context.setUser(output.getAuthenticatedUser());
-            if (output.getState() != null && !output.getState().isEmpty()) {
-                for (Map.Entry<String, String> entry : output.getState().entrySet()) {
-                    context.getClientSession().setUserSessionNote(entry.getKey(), entry.getValue());
-                }
-            }
-            context.success();
-        } else if (output.getAuthStatus() == CredentialValidationOutput.Status.CONTINUE) {
-            String spnegoResponseToken = (String) output.getState().get(KerberosConstants.RESPONSE_TOKEN);
-            Response challenge =  challengeNegotiation(context, spnegoResponseToken);
-            context.challenge(challenge);
-        } else {
-            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-            context.failure(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
-        }
-    }
-
-    private Response challengeNegotiation(AuthenticatorContext context, final String negotiateToken) {
-        String negotiateHeader = negotiateToken == null ? KerberosConstants.NEGOTIATE : KerberosConstants.NEGOTIATE + " " + negotiateToken;
-
-        if (logger.isTraceEnabled()) {
-            logger.trace("Sending back " + HttpHeaders.WWW_AUTHENTICATE + ": " + negotiateHeader);
-        }
-        if (context.getExecution().isRequired()) {
-            return context.getSession().getProvider(LoginFormsProvider.class)
-                    .setStatus(Response.Status.UNAUTHORIZED)
-                    .setResponseHeader(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
-                    .setError(Messages.KERBEROS_NOT_ENABLED).createErrorPage();
-        } else {
-            return optionalChallengeRedirect(context, negotiateHeader);
-        }
-    }
-
-    // This is used for testing only.  Selenium will execute the HTML challenge sent back which results in the javascript
-    // redirecting.  Our old Selenium tests expect that the current URL will be the original openid redirect.
-    public static boolean bypassChallengeJavascript = false;
-
-    /**
-     * 401 challenge sent back that bypasses
-     * @param context
-     * @param negotiateHeader
-     * @return
-     */
-    protected Response optionalChallengeRedirect(AuthenticatorContext context, String negotiateHeader) {
-        String accessCode = context.generateAccessCode();
-        URI action = getActionUrl(context, accessCode);
-
-        StringBuilder builder = new StringBuilder();
-
-        builder.append("<HTML>");
-        builder.append("<HEAD>");
-
-        builder.append("<TITLE>Kerberos Unsupported</TITLE>");
-        builder.append("</HEAD>");
-        if (bypassChallengeJavascript) {
-            builder.append("<BODY>");
-
-        } else {
-            builder.append("<BODY Onload=\"document.forms[0].submit()\">");
-        }
-        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + action.toString() + "\">");
-        builder.append("<NOSCRIPT>");
-        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. You were unable to login via Kerberos.  Click the button below to login via an alternative method .</P>");
-        builder.append("<INPUT name=\"continue\" TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
-        builder.append("</NOSCRIPT>");
-
-        builder.append("</FORM></BODY></HTML>");
-        return Response.status(Response.Status.UNAUTHORIZED)
-                .header(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
-                .type(MediaType.TEXT_HTML_TYPE)
-                .entity(builder.toString()).build();
-    }
-
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorContext;
+import org.keycloak.constants.KerberosConstants;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.services.messages.Messages;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.keycloak.util.HtmlUtils.escapeAttribute;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SpnegoAuthenticator extends AbstractFormAuthenticator implements Authenticator{
+    public static final String KERBEROS_DISABLED = "kerberos_disabled";
+    protected static Logger logger = Logger.getLogger(SpnegoAuthenticator.class);
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public void action(AuthenticatorContext context) {
+        context.attempted();
+        return;
+    }
+
+    @Override
+    public void authenticate(AuthenticatorContext context) {
+        HttpRequest request = context.getHttpRequest();
+        String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
+        if (authHeader == null) {
+            Response challenge = challengeNegotiation(context, null);
+            context.forceChallenge(challenge);
+            return;
+        }
+
+        String[] tokens = authHeader.split(" ");
+        if (tokens.length == 0) { // assume not supported
+            logger.debug("Invalid length of tokens: " + tokens.length);
+            context.attempted();
+            return;
+        }
+        if (!KerberosConstants.NEGOTIATE.equalsIgnoreCase(tokens[0])) {
+            logger.debug("Unknown scheme " + tokens[0]);
+            context.attempted();
+            return;
+        }
+        if (tokens.length != 2) {
+            context.failure(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
+            return;
+        }
+
+        String spnegoToken = tokens[1];
+        UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
+
+        CredentialValidationOutput output = context.getSession().users().validCredentials(context.getRealm(), spnegoCredential);
+
+        if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
+            context.setUser(output.getAuthenticatedUser());
+            if (output.getState() != null && !output.getState().isEmpty()) {
+                for (Map.Entry<String, String> entry : output.getState().entrySet()) {
+                    context.getClientSession().setUserSessionNote(entry.getKey(), entry.getValue());
+                }
+            }
+            context.success();
+        } else if (output.getAuthStatus() == CredentialValidationOutput.Status.CONTINUE) {
+            String spnegoResponseToken = (String) output.getState().get(KerberosConstants.RESPONSE_TOKEN);
+            Response challenge =  challengeNegotiation(context, spnegoResponseToken);
+            context.challenge(challenge);
+        } else {
+            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
+            context.failure(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
+        }
+    }
+
+    private Response challengeNegotiation(AuthenticatorContext context, final String negotiateToken) {
+        String negotiateHeader = negotiateToken == null ? KerberosConstants.NEGOTIATE : KerberosConstants.NEGOTIATE + " " + negotiateToken;
+
+        if (logger.isTraceEnabled()) {
+            logger.trace("Sending back " + HttpHeaders.WWW_AUTHENTICATE + ": " + negotiateHeader);
+        }
+        if (context.getExecution().isRequired()) {
+            return context.getSession().getProvider(LoginFormsProvider.class)
+                    .setStatus(Response.Status.UNAUTHORIZED)
+                    .setResponseHeader(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
+                    .setError(Messages.KERBEROS_NOT_ENABLED).createErrorPage();
+        } else {
+            return optionalChallengeRedirect(context, negotiateHeader);
+        }
+    }
+
+    // This is used for testing only.  Selenium will execute the HTML challenge sent back which results in the javascript
+    // redirecting.  Our old Selenium tests expect that the current URL will be the original openid redirect.
+    public static boolean bypassChallengeJavascript = false;
+
+    /**
+     * 401 challenge sent back that bypasses
+     * @param context
+     * @param negotiateHeader
+     * @return
+     */
+    protected Response optionalChallengeRedirect(AuthenticatorContext context, String negotiateHeader) {
+        String accessCode = context.generateAccessCode();
+        URI action = getActionUrl(context, accessCode);
+
+        StringBuilder builder = new StringBuilder();
+
+        builder.append("<HTML>");
+        builder.append("<HEAD>");
+
+        builder.append("<TITLE>Kerberos Unsupported</TITLE>");
+        builder.append("</HEAD>");
+        if (bypassChallengeJavascript) {
+            builder.append("<BODY>");
+
+        } else {
+            builder.append("<BODY Onload=\"document.forms[0].submit()\">");
+        }
+        builder.append("<FORM METHOD=\"POST\" ACTION=\"" + action.toString() + "\">");
+        builder.append("<NOSCRIPT>");
+        builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. You were unable to login via Kerberos.  Click the button below to login via an alternative method .</P>");
+        builder.append("<INPUT name=\"continue\" TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
+        builder.append("</NOSCRIPT>");
+
+        builder.append("</FORM></BODY></HTML>");
+        return Response.status(Response.Status.UNAUTHORIZED)
+                .header(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
+                .type(MediaType.TEXT_HTML_TYPE)
+                .entity(builder.toString()).build();
+    }
+
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticatorFactory.java
index 4755810..36b84e0 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticatorFactory.java
@@ -1,88 +1,88 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorFactory;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SpnegoAuthenticatorFactory implements AuthenticatorFactory {
-
-    public static final String PROVIDER_ID = "auth-spnego";
-
-    @Override
-    public Authenticator create() {
-        return new SpnegoAuthenticator();
-    }
-
-    @Override
-    public Authenticator create(KeycloakSession session) {
-        throw new IllegalStateException("illegal call");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return UserCredentialModel.KERBEROS;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.ALTERNATIVE,
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED};
-
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Kerberos";
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Initiates the SPNEGO protocol.  Most often used with Kerberos.";
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SpnegoAuthenticatorFactory implements AuthenticatorFactory {
+
+    public static final String PROVIDER_ID = "auth-spnego";
+
+    @Override
+    public Authenticator create() {
+        return new SpnegoAuthenticator();
+    }
+
+    @Override
+    public Authenticator create(KeycloakSession session) {
+        throw new IllegalStateException("illegal call");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return UserCredentialModel.KERBEROS;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.ALTERNATIVE,
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED};
+
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Kerberos";
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Initiates the SPNEGO protocol.  Most often used with Kerberos.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordForm.java b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordForm.java
index 19f0f3e..6632c82 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordForm.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordForm.java
@@ -1,98 +1,98 @@
-package org.keycloak.authentication.authenticators;
-
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorContext;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.services.managers.AuthenticationManager;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernamePasswordForm extends AbstractFormAuthenticator implements Authenticator {
-
-   @Override
-    public void action(AuthenticatorContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        if (formData.containsKey("cancel")) {
-            context.getEvent().error(Errors.REJECTED_BY_USER);
-            LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
-            protocol.setRealm(context.getRealm())
-                    .setHttpHeaders(context.getHttpRequest().getHttpHeaders())
-                    .setUriInfo(context.getUriInfo());
-            Response response = protocol.cancelLogin(context.getClientSession());
-            context.forceChallenge(response);
-            return;
-        }
-        if (!validateForm(context, formData)) {
-            return;
-        }
-        context.success();
-    }
-
-    protected boolean validateForm(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
-        return validateUser(context, formData) && validatePassword(context, formData);
-    }
-
-    @Override
-    public void authenticate(AuthenticatorContext context) {
-        MultivaluedMap<String, String> formData = new MultivaluedMapImpl<>();
-        String loginHint = context.getClientSession().getNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
-
-        String rememberMeUsername = AuthenticationManager.getRememberMeUsername(context.getRealm(), context.getHttpRequest().getHttpHeaders());
-
-        if (loginHint != null || rememberMeUsername != null) {
-            if (loginHint != null) {
-                formData.add(AuthenticationManager.FORM_USERNAME, loginHint);
-            } else {
-                formData.add(AuthenticationManager.FORM_USERNAME, rememberMeUsername);
-                formData.add("rememberMe", "on");
-            }
-        }
-        Response challengeResponse = challenge(context, formData);
-        context.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, context.getExecution().getId());
-        context.challenge(challengeResponse);
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    protected Response challenge(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
-        LoginFormsProvider forms = loginForm(context);
-
-        if (formData.size() > 0) forms.setFormData(formData);
-
-        return forms.createLogin();
-    }
-
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        // never called
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-        // never called
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorContext;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.services.managers.AuthenticationManager;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernamePasswordForm extends AbstractFormAuthenticator implements Authenticator {
+
+   @Override
+    public void action(AuthenticatorContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        if (formData.containsKey("cancel")) {
+            context.getEvent().error(Errors.REJECTED_BY_USER);
+            LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
+            protocol.setRealm(context.getRealm())
+                    .setHttpHeaders(context.getHttpRequest().getHttpHeaders())
+                    .setUriInfo(context.getUriInfo());
+            Response response = protocol.cancelLogin(context.getClientSession());
+            context.forceChallenge(response);
+            return;
+        }
+        if (!validateForm(context, formData)) {
+            return;
+        }
+        context.success();
+    }
+
+    protected boolean validateForm(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
+        return validateUser(context, formData) && validatePassword(context, formData);
+    }
+
+    @Override
+    public void authenticate(AuthenticatorContext context) {
+        MultivaluedMap<String, String> formData = new MultivaluedMapImpl<>();
+        String loginHint = context.getClientSession().getNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
+
+        String rememberMeUsername = AuthenticationManager.getRememberMeUsername(context.getRealm(), context.getHttpRequest().getHttpHeaders());
+
+        if (loginHint != null || rememberMeUsername != null) {
+            if (loginHint != null) {
+                formData.add(AuthenticationManager.FORM_USERNAME, loginHint);
+            } else {
+                formData.add(AuthenticationManager.FORM_USERNAME, rememberMeUsername);
+                formData.add("rememberMe", "on");
+            }
+        }
+        Response challengeResponse = challenge(context, formData);
+        context.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, context.getExecution().getId());
+        context.challenge(challengeResponse);
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    protected Response challenge(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
+        LoginFormsProvider forms = loginForm(context);
+
+        if (formData.size() > 0) forms.setFormData(formData);
+
+        return forms.createLogin();
+    }
+
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        // never called
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+        // never called
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
index cee4f7d..ac2afee 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
@@ -1,85 +1,85 @@
-package org.keycloak.authentication.authenticators;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorFactory;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsernamePasswordFormFactory implements AuthenticatorFactory {
-
-    public static final String PROVIDER_ID = "auth-username-password-form";
-
-    @Override
-    public Authenticator create() {
-        return new UsernamePasswordForm();
-    }
-
-    @Override
-    public Authenticator create(KeycloakSession session) {
-        throw new IllegalStateException("illegal call");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return UserCredentialModel.PASSWORD;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED
-    };
-
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Username Password Form";
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Validates a username and password from login form.";
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-}
+package org.keycloak.authentication.authenticators;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsernamePasswordFormFactory implements AuthenticatorFactory {
+
+    public static final String PROVIDER_ID = "auth-username-password-form";
+
+    @Override
+    public Authenticator create() {
+        return new UsernamePasswordForm();
+    }
+
+    @Override
+    public Authenticator create(KeycloakSession session) {
+        throw new IllegalStateException("illegal call");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return UserCredentialModel.PASSWORD;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+    public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED
+    };
+
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Username Password Form";
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Validates a username and password from login form.";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
index 04962dd..45e8c3a 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
@@ -1,60 +1,60 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.RealmModel;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticatorUtil {
-
-    public static List<AuthenticationExecutionModel> getEnabledExecutionsRecursively(RealmModel realm, String flowId) {
-        List<AuthenticationExecutionModel> executions = new LinkedList<>();
-        recurseExecutions(realm, flowId, executions);
-        return executions;
-
-    }
-
-    public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
-        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
-            executions.add(model);
-            if (model.isAutheticatorFlow() && model.isEnabled()) {
-                recurseExecutions(realm, model.getFlowId(), executions);
-            }
-        }
-    }
-
-    public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
-        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
-            if (model.isAutheticatorFlow()) {
-                AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
-                if (recurse != null) return recurse;
-
-            }
-            if (model.getAuthenticator().equals(authProviderId)) {
-                return model;
-            }
-        }
-        return null;
-    }
-
-    public static boolean isEnabled(RealmModel realm, String flowId, String authProviderId) {
-        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
-        if (execution == null) {
-            return false;
-        }
-        return execution.isEnabled();
-    }
-    public static boolean isRequired(RealmModel realm, String flowId, String authProviderId) {
-        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
-        if (execution == null) {
-            return false;
-        }
-        return execution.isRequired();
-    }
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.RealmModel;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticatorUtil {
+
+    public static List<AuthenticationExecutionModel> getEnabledExecutionsRecursively(RealmModel realm, String flowId) {
+        List<AuthenticationExecutionModel> executions = new LinkedList<>();
+        recurseExecutions(realm, flowId, executions);
+        return executions;
+
+    }
+
+    public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
+        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
+            executions.add(model);
+            if (model.isAutheticatorFlow() && model.isEnabled()) {
+                recurseExecutions(realm, model.getFlowId(), executions);
+            }
+        }
+    }
+
+    public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
+        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
+            if (model.isAutheticatorFlow()) {
+                AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
+                if (recurse != null) return recurse;
+
+            }
+            if (model.getAuthenticator().equals(authProviderId)) {
+                return model;
+            }
+        }
+        return null;
+    }
+
+    public static boolean isEnabled(RealmModel realm, String flowId, String authProviderId) {
+        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
+        if (execution == null) {
+            return false;
+        }
+        return execution.isEnabled();
+    }
+    public static boolean isRequired(RealmModel realm, String flowId, String authProviderId) {
+        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
+        if (execution == null) {
+            return false;
+        }
+        return execution.isRequired();
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
index 5297674..9e8705a 100755
--- a/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
@@ -1,28 +1,28 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.provider.ConfiguredProvider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ConfigurableAuthenticatorFactory extends ConfiguredProvider {
-    String getDisplayType();
-
-    /**
-     * General authenticator type, i.e. totp, password, cert.
-     *
-     * @return null if not a referencable category
-     */
-    String getReferenceCategory();
-
-    boolean isConfigurable();
-
-    /**
-     * What requirement settings are allowed.
-     *
-     * @return
-     */
-    AuthenticationExecutionModel.Requirement[] getRequirementChoices();
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.provider.ConfiguredProvider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ConfigurableAuthenticatorFactory extends ConfiguredProvider {
+    String getDisplayType();
+
+    /**
+     * General authenticator type, i.e. totp, password, cert.
+     *
+     * @return null if not a referencable category
+     */
+    String getReferenceCategory();
+
+    boolean isConfigurable();
+
+    /**
+     * What requirement settings are allowed.
+     *
+     * @return
+     */
+    AuthenticationExecutionModel.Requirement[] getRequirementChoices();
+}
diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index 54da8ad..058903c 100755
--- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
@@ -1,210 +1,210 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.UserModel;
-
-import javax.ws.rs.core.Response;
-import java.util.Iterator;
-import java.util.List;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class DefaultAuthenticationFlow implements AuthenticationFlow {
-    Response alternativeChallenge = null;
-    AuthenticationExecutionModel challengedAlternativeExecution = null;
-    boolean alternativeSuccessful = false;
-    List<AuthenticationExecutionModel> executions;
-    Iterator<AuthenticationExecutionModel> executionIterator;
-    AuthenticationProcessor processor;
-    AuthenticationFlowModel flow;
-
-    public DefaultAuthenticationFlow(AuthenticationProcessor processor, AuthenticationFlowModel flow) {
-        this.processor = processor;
-        this.flow = flow;
-        this.executions = processor.getRealm().getAuthenticationExecutions(flow.getId());
-        this.executionIterator = executions.iterator();
-    }
-
-    protected boolean isProcessed(AuthenticationExecutionModel model) {
-        if (model.isDisabled()) return true;
-        ClientSessionModel.ExecutionStatus status = processor.getClientSession().getExecutionStatus().get(model.getId());
-        if (status == null) return false;
-        return status == ClientSessionModel.ExecutionStatus.SUCCESS || status == ClientSessionModel.ExecutionStatus.SKIPPED
-                || status == ClientSessionModel.ExecutionStatus.ATTEMPTED
-                || status == ClientSessionModel.ExecutionStatus.SETUP_REQUIRED;
-    }
-
-
-    @Override
-    public Response processAction(String actionExecution) {
-        while (executionIterator.hasNext()) {
-            AuthenticationExecutionModel model = executionIterator.next();
-            if (isProcessed(model)) {
-                AuthenticationProcessor.logger.debug("execution is processed");
-                if (!alternativeSuccessful && model.isAlternative() && processor.isSuccessful(model))
-                    alternativeSuccessful = true;
-                continue;
-            }
-            if (model.isAutheticatorFlow()) {
-                AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
-                return authenticationFlow.processAction(actionExecution);
-            } else if (model.getId().equals(actionExecution)) {
-                AuthenticatorFactory factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
-                Authenticator authenticator = factory.create();
-                AuthenticatorContext result = processor.createAuthenticatorContext(model, authenticator, executions);
-                authenticator.action(result);
-                Response response = processResult(result);
-                if (response == null) return processFlow();
-                else return response;
-            }
-        }
-        throw new AuthenticationProcessor.AuthException("action is not in current execution", AuthenticationProcessor.Error.INTERNAL_ERROR);
-    }
-
-    @Override
-    public Response processFlow() {
-        while (executionIterator.hasNext()) {
-            AuthenticationExecutionModel model = executionIterator.next();
-            if (isProcessed(model)) {
-                AuthenticationProcessor.logger.debug("execution is processed");
-                if (!alternativeSuccessful && model.isAlternative() && processor.isSuccessful(model))
-                    alternativeSuccessful = true;
-                continue;
-            }
-            if (model.isAlternative() && alternativeSuccessful) {
-                processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                continue;
-            }
-            if (model.isAutheticatorFlow()) {
-                AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
-                Response flowChallenge = authenticationFlow.processFlow();
-                if (flowChallenge == null) {
-                    processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
-                    if (model.isAlternative()) alternativeSuccessful = true;
-                    continue;
-                } else {
-                    if (model.isAlternative()) {
-                        alternativeChallenge = flowChallenge;
-                        challengedAlternativeExecution = model;
-                    } else if (model.isRequired()) {
-                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-                        return flowChallenge;
-                    } else if (model.isOptional()) {
-                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                        continue;
-                    } else {
-                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                        continue;
-                    }
-                    return flowChallenge;
-                }
-            }
-
-            AuthenticatorFactory factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
-            Authenticator authenticator = factory.create();
-            AuthenticationProcessor.logger.debugv("authenticator: {0}", factory.getId());
-            UserModel authUser = processor.getClientSession().getAuthenticatedUser();
-
-            if (authenticator.requiresUser() && authUser == null) {
-                if (alternativeChallenge != null) {
-                    processor.getClientSession().setExecutionStatus(challengedAlternativeExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-                    return alternativeChallenge;
-                }
-                throw new AuthenticationProcessor.AuthException("authenticator: " + factory.getId(), AuthenticationProcessor.Error.UNKNOWN_USER);
-            }
-            boolean configuredFor = false;
-            if (authenticator.requiresUser() && authUser != null) {
-                configuredFor = authenticator.configuredFor(processor.getSession(), processor.getRealm(), authUser);
-                if (!configuredFor) {
-                    if (model.isRequired()) {
-                        if (model.isUserSetupAllowed()) {
-                            AuthenticationProcessor.logger.debugv("authenticator SETUP_REQUIRED: {0}", factory.getId());
-                            processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
-                            authenticator.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
-                            continue;
-                        } else {
-                            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.CREDENTIAL_SETUP_REQUIRED);
-                        }
-                    } else if (model.isOptional()) {
-                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                        continue;
-                    }
-                }
-            }
-            AuthenticatorContext context = processor.createAuthenticatorContext(model, authenticator, executions);
-            authenticator.authenticate(context);
-            Response response = processResult(context);
-            if (response != null) return response;
-        }
-        return null;
-    }
-
-
-    public Response processResult(AuthenticatorContext result) {
-        AuthenticationExecutionModel execution = result.getExecution();
-        AuthenticationProcessor.Status status = result.getStatus();
-        if (status == AuthenticationProcessor.Status.SUCCESS) {
-            AuthenticationProcessor.logger.debugv("authenticator SUCCESS: {0}", execution.getAuthenticator());
-            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
-            if (execution.isAlternative()) alternativeSuccessful = true;
-            return null;
-        } else if (status == AuthenticationProcessor.Status.FAILED) {
-            AuthenticationProcessor.logger.debugv("authenticator FAILED: {0}", execution.getAuthenticator());
-            processor.logFailure();
-            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.FAILED);
-            if (result.getChallenge() != null) {
-                return sendChallenge(result, execution);
-            }
-            throw new AuthenticationProcessor.AuthException(result.getError());
-        } else if (status == AuthenticationProcessor.Status.FORCE_CHALLENGE) {
-            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-            return sendChallenge(result, execution);
-        } else if (status == AuthenticationProcessor.Status.CHALLENGE) {
-            AuthenticationProcessor.logger.debugv("authenticator CHALLENGE: {0}", execution.getAuthenticator());
-            if (execution.isRequired()) {
-                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-                return sendChallenge(result, execution);
-            }
-            UserModel authenticatedUser = processor.getClientSession().getAuthenticatedUser();
-            if (execution.isOptional() && authenticatedUser != null && result.getAuthenticator().configuredFor(processor.getSession(), processor.getRealm(), authenticatedUser)) {
-                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-                return sendChallenge(result, execution);
-            }
-            if (execution.isAlternative()) {
-                alternativeChallenge = result.getChallenge();
-                challengedAlternativeExecution = execution;
-            } else {
-                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-            }
-            return null;
-        } else if (status == AuthenticationProcessor.Status.FAILURE_CHALLENGE) {
-            AuthenticationProcessor.logger.debugv("authenticator FAILURE_CHALLENGE: {0}", execution.getAuthenticator());
-            processor.logFailure();
-            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-            return sendChallenge(result, execution);
-        } else if (status == AuthenticationProcessor.Status.ATTEMPTED) {
-            AuthenticationProcessor.logger.debugv("authenticator ATTEMPTED: {0}", execution.getAuthenticator());
-            if (execution.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
-                throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
-            }
-            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.ATTEMPTED);
-            return null;
-        } else {
-            AuthenticationProcessor.logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator());
-            AuthenticationProcessor.logger.error("Unknown result status");
-            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.INTERNAL_ERROR);
-        }
-
-    }
-
-    public Response sendChallenge(AuthenticatorContext result, AuthenticationExecutionModel execution) {
-        processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
-        return result.getChallenge();
-    }
-
-
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.UserModel;
+
+import javax.ws.rs.core.Response;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class DefaultAuthenticationFlow implements AuthenticationFlow {
+    Response alternativeChallenge = null;
+    AuthenticationExecutionModel challengedAlternativeExecution = null;
+    boolean alternativeSuccessful = false;
+    List<AuthenticationExecutionModel> executions;
+    Iterator<AuthenticationExecutionModel> executionIterator;
+    AuthenticationProcessor processor;
+    AuthenticationFlowModel flow;
+
+    public DefaultAuthenticationFlow(AuthenticationProcessor processor, AuthenticationFlowModel flow) {
+        this.processor = processor;
+        this.flow = flow;
+        this.executions = processor.getRealm().getAuthenticationExecutions(flow.getId());
+        this.executionIterator = executions.iterator();
+    }
+
+    protected boolean isProcessed(AuthenticationExecutionModel model) {
+        if (model.isDisabled()) return true;
+        ClientSessionModel.ExecutionStatus status = processor.getClientSession().getExecutionStatus().get(model.getId());
+        if (status == null) return false;
+        return status == ClientSessionModel.ExecutionStatus.SUCCESS || status == ClientSessionModel.ExecutionStatus.SKIPPED
+                || status == ClientSessionModel.ExecutionStatus.ATTEMPTED
+                || status == ClientSessionModel.ExecutionStatus.SETUP_REQUIRED;
+    }
+
+
+    @Override
+    public Response processAction(String actionExecution) {
+        while (executionIterator.hasNext()) {
+            AuthenticationExecutionModel model = executionIterator.next();
+            if (isProcessed(model)) {
+                AuthenticationProcessor.logger.debug("execution is processed");
+                if (!alternativeSuccessful && model.isAlternative() && processor.isSuccessful(model))
+                    alternativeSuccessful = true;
+                continue;
+            }
+            if (model.isAutheticatorFlow()) {
+                AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
+                return authenticationFlow.processAction(actionExecution);
+            } else if (model.getId().equals(actionExecution)) {
+                AuthenticatorFactory factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
+                Authenticator authenticator = factory.create();
+                AuthenticatorContext result = processor.createAuthenticatorContext(model, authenticator, executions);
+                authenticator.action(result);
+                Response response = processResult(result);
+                if (response == null) return processFlow();
+                else return response;
+            }
+        }
+        throw new AuthenticationProcessor.AuthException("action is not in current execution", AuthenticationProcessor.Error.INTERNAL_ERROR);
+    }
+
+    @Override
+    public Response processFlow() {
+        while (executionIterator.hasNext()) {
+            AuthenticationExecutionModel model = executionIterator.next();
+            if (isProcessed(model)) {
+                AuthenticationProcessor.logger.debug("execution is processed");
+                if (!alternativeSuccessful && model.isAlternative() && processor.isSuccessful(model))
+                    alternativeSuccessful = true;
+                continue;
+            }
+            if (model.isAlternative() && alternativeSuccessful) {
+                processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                continue;
+            }
+            if (model.isAutheticatorFlow()) {
+                AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
+                Response flowChallenge = authenticationFlow.processFlow();
+                if (flowChallenge == null) {
+                    processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+                    if (model.isAlternative()) alternativeSuccessful = true;
+                    continue;
+                } else {
+                    if (model.isAlternative()) {
+                        alternativeChallenge = flowChallenge;
+                        challengedAlternativeExecution = model;
+                    } else if (model.isRequired()) {
+                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+                        return flowChallenge;
+                    } else if (model.isOptional()) {
+                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                        continue;
+                    } else {
+                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                        continue;
+                    }
+                    return flowChallenge;
+                }
+            }
+
+            AuthenticatorFactory factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
+            Authenticator authenticator = factory.create();
+            AuthenticationProcessor.logger.debugv("authenticator: {0}", factory.getId());
+            UserModel authUser = processor.getClientSession().getAuthenticatedUser();
+
+            if (authenticator.requiresUser() && authUser == null) {
+                if (alternativeChallenge != null) {
+                    processor.getClientSession().setExecutionStatus(challengedAlternativeExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+                    return alternativeChallenge;
+                }
+                throw new AuthenticationProcessor.AuthException("authenticator: " + factory.getId(), AuthenticationProcessor.Error.UNKNOWN_USER);
+            }
+            boolean configuredFor = false;
+            if (authenticator.requiresUser() && authUser != null) {
+                configuredFor = authenticator.configuredFor(processor.getSession(), processor.getRealm(), authUser);
+                if (!configuredFor) {
+                    if (model.isRequired()) {
+                        if (model.isUserSetupAllowed()) {
+                            AuthenticationProcessor.logger.debugv("authenticator SETUP_REQUIRED: {0}", factory.getId());
+                            processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
+                            authenticator.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
+                            continue;
+                        } else {
+                            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.CREDENTIAL_SETUP_REQUIRED);
+                        }
+                    } else if (model.isOptional()) {
+                        processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                        continue;
+                    }
+                }
+            }
+            AuthenticatorContext context = processor.createAuthenticatorContext(model, authenticator, executions);
+            authenticator.authenticate(context);
+            Response response = processResult(context);
+            if (response != null) return response;
+        }
+        return null;
+    }
+
+
+    public Response processResult(AuthenticatorContext result) {
+        AuthenticationExecutionModel execution = result.getExecution();
+        AuthenticationProcessor.Status status = result.getStatus();
+        if (status == AuthenticationProcessor.Status.SUCCESS) {
+            AuthenticationProcessor.logger.debugv("authenticator SUCCESS: {0}", execution.getAuthenticator());
+            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+            if (execution.isAlternative()) alternativeSuccessful = true;
+            return null;
+        } else if (status == AuthenticationProcessor.Status.FAILED) {
+            AuthenticationProcessor.logger.debugv("authenticator FAILED: {0}", execution.getAuthenticator());
+            processor.logFailure();
+            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.FAILED);
+            if (result.getChallenge() != null) {
+                return sendChallenge(result, execution);
+            }
+            throw new AuthenticationProcessor.AuthException(result.getError());
+        } else if (status == AuthenticationProcessor.Status.FORCE_CHALLENGE) {
+            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+            return sendChallenge(result, execution);
+        } else if (status == AuthenticationProcessor.Status.CHALLENGE) {
+            AuthenticationProcessor.logger.debugv("authenticator CHALLENGE: {0}", execution.getAuthenticator());
+            if (execution.isRequired()) {
+                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+                return sendChallenge(result, execution);
+            }
+            UserModel authenticatedUser = processor.getClientSession().getAuthenticatedUser();
+            if (execution.isOptional() && authenticatedUser != null && result.getAuthenticator().configuredFor(processor.getSession(), processor.getRealm(), authenticatedUser)) {
+                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+                return sendChallenge(result, execution);
+            }
+            if (execution.isAlternative()) {
+                alternativeChallenge = result.getChallenge();
+                challengedAlternativeExecution = execution;
+            } else {
+                processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+            }
+            return null;
+        } else if (status == AuthenticationProcessor.Status.FAILURE_CHALLENGE) {
+            AuthenticationProcessor.logger.debugv("authenticator FAILURE_CHALLENGE: {0}", execution.getAuthenticator());
+            processor.logFailure();
+            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+            return sendChallenge(result, execution);
+        } else if (status == AuthenticationProcessor.Status.ATTEMPTED) {
+            AuthenticationProcessor.logger.debugv("authenticator ATTEMPTED: {0}", execution.getAuthenticator());
+            if (execution.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
+                throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.INVALID_CREDENTIALS);
+            }
+            processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.ATTEMPTED);
+            return null;
+        } else {
+            AuthenticationProcessor.logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator());
+            AuthenticationProcessor.logger.error("Unknown result status");
+            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.INTERNAL_ERROR);
+        }
+
+    }
+
+    public Response sendChallenge(AuthenticatorContext result, AuthenticationExecutionModel execution) {
+        processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
+        return result.getChallenge();
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormAction.java b/services/src/main/java/org/keycloak/authentication/FormAction.java
index a02b2fe..d555820 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAction.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAction.java
@@ -1,28 +1,28 @@
-package org.keycloak.authentication;
-
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.provider.Provider;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface FormAction extends Provider {
-    void validate(ValidationContext context);
-    void success(FormContext context);
-
-    boolean requiresUser();
-    boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
-
-    /**
-     * Set actions to configure authenticator
-     *
-     */
-    void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
-
-    void buildPage(FormContext context, LoginFormsProvider form);
-
-}
+package org.keycloak.authentication;
+
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface FormAction extends Provider {
+    void validate(ValidationContext context);
+    void success(FormContext context);
+
+    boolean requiresUser();
+    boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
+
+    /**
+     * Set actions to configure authenticator
+     *
+     */
+    void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
+
+    void buildPage(FormContext context, LoginFormsProvider form);
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormActionFactory.java b/services/src/main/java/org/keycloak/authentication/FormActionFactory.java
index 866cdfa..8708141 100755
--- a/services/src/main/java/org/keycloak/authentication/FormActionFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/FormActionFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.authentication;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface FormActionFactory extends ProviderFactory<FormAction>, ConfigurableAuthenticatorFactory {
-}
+package org.keycloak.authentication;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface FormActionFactory extends ProviderFactory<FormAction>, ConfigurableAuthenticatorFactory {
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
index 8cd6751..782c862 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
@@ -1,240 +1,240 @@
-package org.keycloak.authentication;
-
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.services.resources.LoginActionsService;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public class FormAuthenticationFlow implements AuthenticationFlow {
-    AuthenticationProcessor processor;
-    AuthenticationExecutionModel formExecution;
-    private final List<AuthenticationExecutionModel> formActionExecutions;
-    private final FormAuthenticator formAuthenticator;
-
-
-    public FormAuthenticationFlow(AuthenticationProcessor processor, AuthenticationExecutionModel execution) {
-        this.processor = processor;
-        this.formExecution = execution;
-        formActionExecutions = processor.getRealm().getAuthenticationExecutions(execution.getFlowId());
-        formAuthenticator = processor.getSession().getProvider(FormAuthenticator.class, execution.getAuthenticator());
-    }
-
-    private class FormContextImpl implements FormContext {
-        AuthenticationExecutionModel executionModel;
-        AuthenticatorConfigModel authenticatorConfig;
-
-        private FormContextImpl(AuthenticationExecutionModel executionModel) {
-            this.executionModel = executionModel;
-        }
-
-        @Override
-        public EventBuilder newEvent() {
-            return processor.newEvent();
-        }
-
-       @Override
-        public EventBuilder getEvent() {
-            return processor.getEvent();
-        }
-
-        @Override
-        public AuthenticationExecutionModel getExecution() {
-            return executionModel;
-        }
-
-        @Override
-        public AuthenticatorConfigModel getAuthenticatorConfig() {
-            if (executionModel.getAuthenticatorConfig() == null) return null;
-            if (authenticatorConfig != null) return authenticatorConfig;
-            authenticatorConfig = getRealm().getAuthenticatorConfigById(executionModel.getAuthenticatorConfig());
-            return authenticatorConfig;
-        }
-
-        @Override
-        public UserModel getUser() {
-            return getClientSession().getAuthenticatedUser();
-        }
-
-        @Override
-        public void setUser(UserModel user) {
-            processor.setAutheticatedUser(user);
-        }
-
-        @Override
-        public RealmModel getRealm() {
-            return processor.getRealm();
-        }
-
-        @Override
-        public ClientSessionModel getClientSession() {
-            return processor.getClientSession();
-        }
-
-        @Override
-        public ClientConnection getConnection() {
-            return processor.getConnection();
-        }
-
-        @Override
-        public UriInfo getUriInfo() {
-            return processor.getUriInfo();
-        }
-
-        @Override
-        public KeycloakSession getSession() {
-            return processor.getSession();
-        }
-
-        @Override
-        public HttpRequest getHttpRequest() {
-            return processor.getRequest();
-        }
-
-    }
-
-    private class ValidationContextImpl extends FormContextImpl implements ValidationContext {
-        FormAction action;
-
-        private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) {
-            super(executionModel);
-            this.action = action;
-        }
-
-        boolean success;
-        List<FormMessage> errors = null;
-        MultivaluedMap<String, String> formData = null;
-        @Override
-        public void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors) {
-            this.errors = errors;
-            this.formData = formData;
-        }
-
-        @Override
-        public void success() {
-           success = true;
-        }
-    }
-
-    @Override
-    public Response processAction(String actionExecution) {
-        if (!actionExecution.equals(formExecution.getId())) {
-            throw new AuthenticationProcessor.AuthException("action is not current execution", AuthenticationProcessor.Error.INTERNAL_ERROR);
-        }
-        Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
-        List<FormAction> requiredActions = new LinkedList<>();
-        List<ValidationContextImpl> successes = new LinkedList<>();
-        for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
-            if (!formActionExecution.isEnabled()) {
-                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                continue;
-            }
-            FormAction action = processor.getSession().getProvider(FormAction.class, formActionExecution.getAuthenticator());
-
-            UserModel authUser = processor.getClientSession().getAuthenticatedUser();
-            if (action.requiresUser() && authUser == null) {
-                throw new AuthenticationProcessor.AuthException("form action: " + formExecution.getAuthenticator() + " requires user", AuthenticationProcessor.Error.UNKNOWN_USER);
-            }
-            boolean configuredFor = false;
-            if (action.requiresUser() && authUser != null) {
-                configuredFor = action.configuredFor(processor.getSession(), processor.getRealm(), authUser);
-                if (!configuredFor) {
-                    if (formActionExecution.isRequired()) {
-                        if (formActionExecution.isUserSetupAllowed()) {
-                            AuthenticationProcessor.logger.debugv("authenticator SETUP_REQUIRED: {0}", formExecution.getAuthenticator());
-                            executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
-                            requiredActions.add(action);
-                            continue;
-                        } else {
-                            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.CREDENTIAL_SETUP_REQUIRED);
-                        }
-                    } else if (formActionExecution.isOptional()) {
-                        executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
-                        continue;
-                    }
-                }
-            }
-
-            ValidationContextImpl result = new ValidationContextImpl(formActionExecution, action);
-            action.validate(result);
-            if (result.success) {
-                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
-                successes.add(result);
-            } else {
-                processor.logFailure();
-                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
-                return renderForm(result.formData, result.errors);
-            }
-        }
-
-        for (ValidationContextImpl context : successes) {
-            context.action.success(context);
-        }
-        // set status and required actions only if form is fully successful
-        for (Map.Entry<String, ClientSessionModel.ExecutionStatus> entry : executionStatus.entrySet()) {
-            processor.getClientSession().setExecutionStatus(entry.getKey(), entry.getValue());
-        }
-        for (FormAction action : requiredActions) {
-            action.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
-
-        }
-        return null;
-
-    }
-
-    public URI getActionUrl(String executionId, String code) {
-        return LoginActionsService.registrationFormProcessor(processor.getUriInfo())
-                .queryParam(OAuth2Constants.CODE, code)
-                .queryParam("execution", executionId)
-                .build(processor.getRealm().getName());
-    }
-
-
-    @Override
-    public Response processFlow() {
-        return renderForm(null, null);
-    }
-
-    public Response renderForm(MultivaluedMap<String, String> formData, List<FormMessage> errors) {
-        String executionId = formExecution.getId();
-        processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, executionId);
-        String code = processor.generateCode();
-        URI actionUrl = getActionUrl(executionId, code);
-        LoginFormsProvider form = processor.getSession().getProvider(LoginFormsProvider.class)
-                .setActionUri(actionUrl)
-                .setClientSessionCode(code)
-                .setFormData(formData)
-                .setErrors(errors);
-        for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
-            if (!formActionExecution.isEnabled()) continue;
-            FormAction action = processor.getSession().getProvider(FormAction.class, formActionExecution.getAuthenticator());
-            FormContext result = new FormContextImpl(formActionExecution);
-            action.buildPage(result, form);
-        }
-        FormContext context = new FormContextImpl(formExecution);
-        return formAuthenticator.render(context, form);
-    }
-}
+package org.keycloak.authentication;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.resources.LoginActionsService;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class FormAuthenticationFlow implements AuthenticationFlow {
+    AuthenticationProcessor processor;
+    AuthenticationExecutionModel formExecution;
+    private final List<AuthenticationExecutionModel> formActionExecutions;
+    private final FormAuthenticator formAuthenticator;
+
+
+    public FormAuthenticationFlow(AuthenticationProcessor processor, AuthenticationExecutionModel execution) {
+        this.processor = processor;
+        this.formExecution = execution;
+        formActionExecutions = processor.getRealm().getAuthenticationExecutions(execution.getFlowId());
+        formAuthenticator = processor.getSession().getProvider(FormAuthenticator.class, execution.getAuthenticator());
+    }
+
+    private class FormContextImpl implements FormContext {
+        AuthenticationExecutionModel executionModel;
+        AuthenticatorConfigModel authenticatorConfig;
+
+        private FormContextImpl(AuthenticationExecutionModel executionModel) {
+            this.executionModel = executionModel;
+        }
+
+        @Override
+        public EventBuilder newEvent() {
+            return processor.newEvent();
+        }
+
+       @Override
+        public EventBuilder getEvent() {
+            return processor.getEvent();
+        }
+
+        @Override
+        public AuthenticationExecutionModel getExecution() {
+            return executionModel;
+        }
+
+        @Override
+        public AuthenticatorConfigModel getAuthenticatorConfig() {
+            if (executionModel.getAuthenticatorConfig() == null) return null;
+            if (authenticatorConfig != null) return authenticatorConfig;
+            authenticatorConfig = getRealm().getAuthenticatorConfigById(executionModel.getAuthenticatorConfig());
+            return authenticatorConfig;
+        }
+
+        @Override
+        public UserModel getUser() {
+            return getClientSession().getAuthenticatedUser();
+        }
+
+        @Override
+        public void setUser(UserModel user) {
+            processor.setAutheticatedUser(user);
+        }
+
+        @Override
+        public RealmModel getRealm() {
+            return processor.getRealm();
+        }
+
+        @Override
+        public ClientSessionModel getClientSession() {
+            return processor.getClientSession();
+        }
+
+        @Override
+        public ClientConnection getConnection() {
+            return processor.getConnection();
+        }
+
+        @Override
+        public UriInfo getUriInfo() {
+            return processor.getUriInfo();
+        }
+
+        @Override
+        public KeycloakSession getSession() {
+            return processor.getSession();
+        }
+
+        @Override
+        public HttpRequest getHttpRequest() {
+            return processor.getRequest();
+        }
+
+    }
+
+    private class ValidationContextImpl extends FormContextImpl implements ValidationContext {
+        FormAction action;
+
+        private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) {
+            super(executionModel);
+            this.action = action;
+        }
+
+        boolean success;
+        List<FormMessage> errors = null;
+        MultivaluedMap<String, String> formData = null;
+        @Override
+        public void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors) {
+            this.errors = errors;
+            this.formData = formData;
+        }
+
+        @Override
+        public void success() {
+           success = true;
+        }
+    }
+
+    @Override
+    public Response processAction(String actionExecution) {
+        if (!actionExecution.equals(formExecution.getId())) {
+            throw new AuthenticationProcessor.AuthException("action is not current execution", AuthenticationProcessor.Error.INTERNAL_ERROR);
+        }
+        Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
+        List<FormAction> requiredActions = new LinkedList<>();
+        List<ValidationContextImpl> successes = new LinkedList<>();
+        for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
+            if (!formActionExecution.isEnabled()) {
+                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                continue;
+            }
+            FormAction action = processor.getSession().getProvider(FormAction.class, formActionExecution.getAuthenticator());
+
+            UserModel authUser = processor.getClientSession().getAuthenticatedUser();
+            if (action.requiresUser() && authUser == null) {
+                throw new AuthenticationProcessor.AuthException("form action: " + formExecution.getAuthenticator() + " requires user", AuthenticationProcessor.Error.UNKNOWN_USER);
+            }
+            boolean configuredFor = false;
+            if (action.requiresUser() && authUser != null) {
+                configuredFor = action.configuredFor(processor.getSession(), processor.getRealm(), authUser);
+                if (!configuredFor) {
+                    if (formActionExecution.isRequired()) {
+                        if (formActionExecution.isUserSetupAllowed()) {
+                            AuthenticationProcessor.logger.debugv("authenticator SETUP_REQUIRED: {0}", formExecution.getAuthenticator());
+                            executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
+                            requiredActions.add(action);
+                            continue;
+                        } else {
+                            throw new AuthenticationProcessor.AuthException(AuthenticationProcessor.Error.CREDENTIAL_SETUP_REQUIRED);
+                        }
+                    } else if (formActionExecution.isOptional()) {
+                        executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+                        continue;
+                    }
+                }
+            }
+
+            ValidationContextImpl result = new ValidationContextImpl(formActionExecution, action);
+            action.validate(result);
+            if (result.success) {
+                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+                successes.add(result);
+            } else {
+                processor.logFailure();
+                executionStatus.put(formActionExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+                return renderForm(result.formData, result.errors);
+            }
+        }
+
+        for (ValidationContextImpl context : successes) {
+            context.action.success(context);
+        }
+        // set status and required actions only if form is fully successful
+        for (Map.Entry<String, ClientSessionModel.ExecutionStatus> entry : executionStatus.entrySet()) {
+            processor.getClientSession().setExecutionStatus(entry.getKey(), entry.getValue());
+        }
+        for (FormAction action : requiredActions) {
+            action.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
+
+        }
+        return null;
+
+    }
+
+    public URI getActionUrl(String executionId, String code) {
+        return LoginActionsService.registrationFormProcessor(processor.getUriInfo())
+                .queryParam(OAuth2Constants.CODE, code)
+                .queryParam("execution", executionId)
+                .build(processor.getRealm().getName());
+    }
+
+
+    @Override
+    public Response processFlow() {
+        return renderForm(null, null);
+    }
+
+    public Response renderForm(MultivaluedMap<String, String> formData, List<FormMessage> errors) {
+        String executionId = formExecution.getId();
+        processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, executionId);
+        String code = processor.generateCode();
+        URI actionUrl = getActionUrl(executionId, code);
+        LoginFormsProvider form = processor.getSession().getProvider(LoginFormsProvider.class)
+                .setActionUri(actionUrl)
+                .setClientSessionCode(code)
+                .setFormData(formData)
+                .setErrors(errors);
+        for (AuthenticationExecutionModel formActionExecution : formActionExecutions) {
+            if (!formActionExecution.isEnabled()) continue;
+            FormAction action = processor.getSession().getProvider(FormAction.class, formActionExecution.getAuthenticator());
+            FormContext result = new FormContextImpl(formActionExecution);
+            action.buildPage(result, form);
+        }
+        FormContext context = new FormContextImpl(formExecution);
+        return formAuthenticator.render(context, form);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticator.java
index 02efebe..5fb0dc0 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticator.java
@@ -1,17 +1,17 @@
-package org.keycloak.authentication;
-
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.provider.Provider;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface FormAuthenticator extends Provider {
-    Response render(FormContext context, LoginFormsProvider form);
-}
+package org.keycloak.authentication;
+
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.provider.Provider;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface FormAuthenticator extends Provider {
+    Response render(FormContext context, LoginFormsProvider form);
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticatorFactory.java
index a388f43..d5455f1 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticatorFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.authentication;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface FormAuthenticatorFactory extends ProviderFactory<FormAuthenticator>, ConfigurableAuthenticatorFactory {
-}
+package org.keycloak.authentication;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface FormAuthenticatorFactory extends ProviderFactory<FormAuthenticator>, ConfigurableAuthenticatorFactory {
+}
diff --git a/services/src/main/java/org/keycloak/authentication/FormContext.java b/services/src/main/java/org/keycloak/authentication/FormContext.java
index f135945..21ccb05 100755
--- a/services/src/main/java/org/keycloak/authentication/FormContext.java
+++ b/services/src/main/java/org/keycloak/authentication/FormContext.java
@@ -1,33 +1,33 @@
-package org.keycloak.authentication;
-
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-
-import javax.ws.rs.core.UriInfo;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public interface FormContext {
-    EventBuilder getEvent();
-    EventBuilder newEvent();
-    AuthenticationExecutionModel getExecution();
-    UserModel getUser();
-    void setUser(UserModel user);
-    RealmModel getRealm();
-    ClientSessionModel getClientSession();
-    ClientConnection getConnection();
-    UriInfo getUriInfo();
-    KeycloakSession getSession();
-    HttpRequest getHttpRequest();
-    AuthenticatorConfigModel getAuthenticatorConfig();
-
-}
+package org.keycloak.authentication;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+
+import javax.ws.rs.core.UriInfo;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public interface FormContext {
+    EventBuilder getEvent();
+    EventBuilder newEvent();
+    AuthenticationExecutionModel getExecution();
+    UserModel getUser();
+    void setUser(UserModel user);
+    RealmModel getRealm();
+    ClientSessionModel getClientSession();
+    ClientConnection getConnection();
+    UriInfo getUriInfo();
+    KeycloakSession getSession();
+    HttpRequest getHttpRequest();
+    AuthenticatorConfigModel getAuthenticatorConfig();
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
index 4b64333..37c0d23 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
@@ -1,94 +1,94 @@
-package org.keycloak.authentication.forms;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.FormAuthenticator;
-import org.keycloak.authentication.FormAuthenticatorFactory;
-import org.keycloak.authentication.FormContext;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.provider.ProviderConfigProperty;
-
-import javax.ws.rs.core.Response;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RegistrationPage implements FormAuthenticator, FormAuthenticatorFactory {
-
-    public static final String EXECUTION = "execution";
-    public static final String FIELD_PASSWORD_CONFIRM = "password-confirm";
-    public static final String FIELD_PASSWORD = "password";
-    public static final String FIELD_EMAIL = "email";
-    public static final String FIELD_USERNAME = "username";
-    public static final String FIELD_LAST_NAME = "lastName";
-    public static final String FIELD_FIRST_NAME = "firstName";
-    public static final String PROVIDER_ID = "registration-page-form";
-
-    @Override
-    public Response render(FormContext context, LoginFormsProvider form) {
-        return form.createRegistration();
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Registration Page";
-    }
-
-    @Override
-    public String getHelpText() {
-        return null;
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return null;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED
-    };
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-    @Override
-    public FormAuthenticator create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-}
+package org.keycloak.authentication.forms;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.FormAuthenticator;
+import org.keycloak.authentication.FormAuthenticatorFactory;
+import org.keycloak.authentication.FormContext;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RegistrationPage implements FormAuthenticator, FormAuthenticatorFactory {
+
+    public static final String EXECUTION = "execution";
+    public static final String FIELD_PASSWORD_CONFIRM = "password-confirm";
+    public static final String FIELD_PASSWORD = "password";
+    public static final String FIELD_EMAIL = "email";
+    public static final String FIELD_USERNAME = "username";
+    public static final String FIELD_LAST_NAME = "lastName";
+    public static final String FIELD_FIRST_NAME = "firstName";
+    public static final String PROVIDER_ID = "registration-page-form";
+
+    @Override
+    public Response render(FormContext context, LoginFormsProvider form) {
+        return form.createRegistration();
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Registration Page";
+    }
+
+    @Override
+    public String getHelpText() {
+        return null;
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return null;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED
+    };
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public FormAuthenticator create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
index 648f9de..92c87f6 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
@@ -1,156 +1,156 @@
-package org.keycloak.authentication.forms;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.FormAction;
-import org.keycloak.authentication.FormActionFactory;
-import org.keycloak.authentication.FormContext;
-import org.keycloak.authentication.ValidationContext;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.validation.Validation;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RegistrationPassword implements FormAction, FormActionFactory {
-    public static final String PROVIDER_ID = "registration-password-action";
-
-    @Override
-    public String getHelpText() {
-        return null;
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-
-    @Override
-    public void validate(ValidationContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        List<FormMessage> errors = new ArrayList<>();
-        context.getEvent().detail(Details.REGISTER_METHOD, "form");
-        if (Validation.isBlank(formData.getFirst(RegistrationPage.FIELD_PASSWORD))) {
-            errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, Messages.MISSING_PASSWORD));
-        } else if (!formData.getFirst(RegistrationPage.FIELD_PASSWORD).equals(formData.getFirst(RegistrationPage.FIELD_PASSWORD_CONFIRM))) {
-            errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM));
-        }
-        if (formData.getFirst(RegistrationPage.FIELD_PASSWORD) != null) {
-            PasswordPolicy.Error err = context.getRealm().getPasswordPolicy().validate(context.getRealm().isRegistrationEmailAsUsername() ? formData.getFirst(RegistrationPage.FIELD_EMAIL) : formData.getFirst(RegistrationPage.FIELD_USERNAME), formData.getFirst(RegistrationPage.FIELD_PASSWORD));
-            if (err != null)
-                errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, err.getMessage(), err.getParameters()));
-        }
-
-        if (errors.size() > 0) {
-            context.getEvent().error(Errors.INVALID_REGISTRATION);
-            formData.remove(RegistrationPage.FIELD_PASSWORD);
-            formData.remove(RegistrationPage.FIELD_PASSWORD_CONFIRM);
-            context.validationError(formData, errors);
-            return;
-        } else {
-            context.success();
-        }
-    }
-
-    @Override
-    public void success(FormContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        String password = formData.getFirst(RegistrationPage.FIELD_PASSWORD);
-        UserCredentialModel credentials = new UserCredentialModel();
-        credentials.setType(CredentialRepresentation.PASSWORD);
-        credentials.setValue(password);
-        UserModel user = context.getUser();
-        try {
-            context.getSession().users().updateCredential(context.getRealm(), user, UserCredentialModel.password(formData.getFirst("password")));
-        } catch (Exception me) {
-            user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-        }
-
-    }
-
-    @Override
-    public void buildPage(FormContext context, LoginFormsProvider form) {
-        form.setAttribute("passwordRequired", true);
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Password Validation";
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return UserCredentialModel.PASSWORD;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED
-    };
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-
-    @Override
-    public FormAction create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-}
+package org.keycloak.authentication.forms;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.FormAction;
+import org.keycloak.authentication.FormActionFactory;
+import org.keycloak.authentication.FormContext;
+import org.keycloak.authentication.ValidationContext;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.validation.Validation;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RegistrationPassword implements FormAction, FormActionFactory {
+    public static final String PROVIDER_ID = "registration-password-action";
+
+    @Override
+    public String getHelpText() {
+        return null;
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+
+    @Override
+    public void validate(ValidationContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        List<FormMessage> errors = new ArrayList<>();
+        context.getEvent().detail(Details.REGISTER_METHOD, "form");
+        if (Validation.isBlank(formData.getFirst(RegistrationPage.FIELD_PASSWORD))) {
+            errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, Messages.MISSING_PASSWORD));
+        } else if (!formData.getFirst(RegistrationPage.FIELD_PASSWORD).equals(formData.getFirst(RegistrationPage.FIELD_PASSWORD_CONFIRM))) {
+            errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM));
+        }
+        if (formData.getFirst(RegistrationPage.FIELD_PASSWORD) != null) {
+            PasswordPolicy.Error err = context.getRealm().getPasswordPolicy().validate(context.getRealm().isRegistrationEmailAsUsername() ? formData.getFirst(RegistrationPage.FIELD_EMAIL) : formData.getFirst(RegistrationPage.FIELD_USERNAME), formData.getFirst(RegistrationPage.FIELD_PASSWORD));
+            if (err != null)
+                errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, err.getMessage(), err.getParameters()));
+        }
+
+        if (errors.size() > 0) {
+            context.getEvent().error(Errors.INVALID_REGISTRATION);
+            formData.remove(RegistrationPage.FIELD_PASSWORD);
+            formData.remove(RegistrationPage.FIELD_PASSWORD_CONFIRM);
+            context.validationError(formData, errors);
+            return;
+        } else {
+            context.success();
+        }
+    }
+
+    @Override
+    public void success(FormContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        String password = formData.getFirst(RegistrationPage.FIELD_PASSWORD);
+        UserCredentialModel credentials = new UserCredentialModel();
+        credentials.setType(CredentialRepresentation.PASSWORD);
+        credentials.setValue(password);
+        UserModel user = context.getUser();
+        try {
+            context.getSession().users().updateCredential(context.getRealm(), user, UserCredentialModel.password(formData.getFirst("password")));
+        } catch (Exception me) {
+            user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+        }
+
+    }
+
+    @Override
+    public void buildPage(FormContext context, LoginFormsProvider form) {
+        form.setAttribute("passwordRequired", true);
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Password Validation";
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return UserCredentialModel.PASSWORD;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED
+    };
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+
+    @Override
+    public FormAction create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
index 5ac7341..46c4bda 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
@@ -1,160 +1,160 @@
-package org.keycloak.authentication.forms;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.FormAction;
-import org.keycloak.authentication.FormActionFactory;
-import org.keycloak.authentication.FormContext;
-import org.keycloak.authentication.ValidationContext;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.validation.Validation;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RegistrationProfile implements FormAction, FormActionFactory {
-    public static final String PROVIDER_ID = "registration-profile-action";
-
-    @Override
-    public String getHelpText() {
-        return null;
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-
-    @Override
-    public void validate(ValidationContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        List<FormMessage> errors = new ArrayList<>();
-
-        context.getEvent().detail(Details.REGISTER_METHOD, "form");
-        String eventError = Errors.INVALID_REGISTRATION;
-
-        if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_FIRST_NAME)))) {
-            errors.add(new FormMessage(RegistrationPage.FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME));
-        }
-
-        if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_LAST_NAME)))) {
-            errors.add(new FormMessage(RegistrationPage.FIELD_LAST_NAME, Messages.MISSING_LAST_NAME));
-        }
-
-        String email = formData.getFirst(Validation.FIELD_EMAIL);
-        if (Validation.isBlank(email)) {
-            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
-        } else if (!Validation.isEmailValid(email)) {
-            formData.remove(Validation.FIELD_EMAIL);
-            context.getEvent().detail(Details.EMAIL, email);
-            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
-        }
-
-        if (context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
-            eventError = Errors.EMAIL_IN_USE;
-            formData.remove(Validation.FIELD_EMAIL);
-            context.getEvent().detail(Details.EMAIL, email);
-            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.EMAIL_EXISTS));
-        }
-
-        if (errors.size() > 0) {
-            context.getEvent().error(eventError);
-            context.validationError(formData, errors);
-            return;
-
-        } else {
-            context.success();
-        }
-    }
-
-    @Override
-    public void success(FormContext context) {
-        UserModel user = context.getUser();
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        user.setFirstName(formData.getFirst(RegistrationPage.FIELD_FIRST_NAME));
-        user.setLastName(formData.getFirst(RegistrationPage.FIELD_LAST_NAME));
-        user.setEmail(formData.getFirst(RegistrationPage.FIELD_EMAIL));
-    }
-
-    @Override
-    public void buildPage(FormContext context, LoginFormsProvider form) {
-        // complete
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Profile Validation";
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return null;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED
-    };
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-    @Override
-    public FormAction create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-}
+package org.keycloak.authentication.forms;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.FormAction;
+import org.keycloak.authentication.FormActionFactory;
+import org.keycloak.authentication.FormContext;
+import org.keycloak.authentication.ValidationContext;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.validation.Validation;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RegistrationProfile implements FormAction, FormActionFactory {
+    public static final String PROVIDER_ID = "registration-profile-action";
+
+    @Override
+    public String getHelpText() {
+        return null;
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+
+    @Override
+    public void validate(ValidationContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        List<FormMessage> errors = new ArrayList<>();
+
+        context.getEvent().detail(Details.REGISTER_METHOD, "form");
+        String eventError = Errors.INVALID_REGISTRATION;
+
+        if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_FIRST_NAME)))) {
+            errors.add(new FormMessage(RegistrationPage.FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME));
+        }
+
+        if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_LAST_NAME)))) {
+            errors.add(new FormMessage(RegistrationPage.FIELD_LAST_NAME, Messages.MISSING_LAST_NAME));
+        }
+
+        String email = formData.getFirst(Validation.FIELD_EMAIL);
+        if (Validation.isBlank(email)) {
+            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
+        } else if (!Validation.isEmailValid(email)) {
+            formData.remove(Validation.FIELD_EMAIL);
+            context.getEvent().detail(Details.EMAIL, email);
+            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
+        }
+
+        if (context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
+            eventError = Errors.EMAIL_IN_USE;
+            formData.remove(Validation.FIELD_EMAIL);
+            context.getEvent().detail(Details.EMAIL, email);
+            errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.EMAIL_EXISTS));
+        }
+
+        if (errors.size() > 0) {
+            context.getEvent().error(eventError);
+            context.validationError(formData, errors);
+            return;
+
+        } else {
+            context.success();
+        }
+    }
+
+    @Override
+    public void success(FormContext context) {
+        UserModel user = context.getUser();
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        user.setFirstName(formData.getFirst(RegistrationPage.FIELD_FIRST_NAME));
+        user.setLastName(formData.getFirst(RegistrationPage.FIELD_LAST_NAME));
+        user.setEmail(formData.getFirst(RegistrationPage.FIELD_EMAIL));
+    }
+
+    @Override
+    public void buildPage(FormContext context, LoginFormsProvider form) {
+        // complete
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Profile Validation";
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return null;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED
+    };
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+    @Override
+    public FormAction create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+}
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 7009704..8f143ed 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
@@ -1,215 +1,215 @@
-package org.keycloak.authentication.forms;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-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;
-import org.keycloak.authentication.FormContext;
-import org.keycloak.authentication.ValidationContext;
-import org.keycloak.connections.httpclient.HttpClientProvider;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
-import org.keycloak.provider.ConfiguredProvider;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.validation.Validation;
-import org.keycloak.util.JsonSerialization;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RegistrationRecaptcha implements FormAction, FormActionFactory, ConfiguredProvider {
-    public static final String G_RECAPTCHA_RESPONSE = "g-recaptcha-response";
-    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 Logger logger = Logger.getLogger(RegistrationRecaptcha.class);
-
-    public static final String PROVIDER_ID = "registration-recaptcha-action";
-
-    @Override
-    public String getDisplayType() {
-        return "Recaptcha";
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return RECAPTCHA_REFERENCE_CATEGORY;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return true;
-    }
-
-    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED
-    };
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-    @Override
-    public void buildPage(FormContext context, LoginFormsProvider form) {
-        AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
-        if (captchaConfig == null || captchaConfig.getConfig() == null
-                || captchaConfig.getConfig().get(SITE_KEY) == null
-                || captchaConfig.getConfig().get(SITE_SECRET) == null
-                ) {
-            form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED));
-            return;
-        }
-        String siteKey = captchaConfig.getConfig().get(SITE_KEY);
-        form.setAttribute("recaptchaRequired", true);
-        form.setAttribute("recaptchaSiteKey", siteKey);
-        List<String> scripts = new LinkedList<>();
-        scripts.add("https://www.google.com/recaptcha/api.js");
-        form.setAttribute("scripts", scripts);
-    }
-
-    @Override
-    public void validate(ValidationContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        List<FormMessage> errors = new ArrayList<>();
-        boolean success = false;
-        context.getEvent().detail(Details.REGISTER_METHOD, "form");
-
-        String captcha = formData.getFirst(G_RECAPTCHA_RESPONSE);
-        if (!Validation.isBlank(captcha)) {
-            AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
-            String secret = captchaConfig.getConfig().get(SITE_SECRET);
-
-            HttpClient httpClient = context.getSession().getProvider(HttpClientProvider.class).getHttpClient();
-            HttpPost post = new HttpPost("https://www.google.com/recaptcha/api/siteverify");
-            List<NameValuePair> formparams = new LinkedList<>();
-            formparams.add(new BasicNameValuePair("secret", secret));
-            formparams.add(new BasicNameValuePair("response", captcha));
-            formparams.add(new BasicNameValuePair("remoteip", context.getConnection().getRemoteAddr()));
-            try {
-                UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
-                post.setEntity(form);
-                HttpResponse response = httpClient.execute(post);
-                InputStream content = response.getEntity().getContent();
-                try {
-                    Map json = JsonSerialization.readValue(content, Map.class);
-                    Object val = json.get("success");
-                    success = Boolean.TRUE.equals(val);
-                } finally {
-                    content.close();
-                }
-            } catch (Exception e) {
-                logger.error("Recaptcha failed", e);
-            }
-        }
-        if (success) {
-            context.success();
-        } else {
-            errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED));
-            formData.remove(G_RECAPTCHA_RESPONSE);
-            context.getEvent().error(Errors.INVALID_REGISTRATION);
-            context.validationError(formData, errors);
-            return;
-
-
-        }
-    }
-
-    @Override
-    public void success(FormContext context) {
-
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public FormAction create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getHelpText() {
-        return null;
-    }
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(SITE_KEY);
-        property.setLabel("Recaptcha Site Key");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText("Google Recaptcha Site Key");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(SITE_SECRET);
-        property.setLabel("Recaptcha Secret");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText("Google Recaptcha Secret");
-        configProperties.add(property);
-
-    }
-
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-}
+package org.keycloak.authentication.forms;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+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;
+import org.keycloak.authentication.FormContext;
+import org.keycloak.authentication.ValidationContext;
+import org.keycloak.connections.httpclient.HttpClientProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
+import org.keycloak.provider.ConfiguredProvider;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.validation.Validation;
+import org.keycloak.util.JsonSerialization;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RegistrationRecaptcha implements FormAction, FormActionFactory, ConfiguredProvider {
+    public static final String G_RECAPTCHA_RESPONSE = "g-recaptcha-response";
+    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 Logger logger = Logger.getLogger(RegistrationRecaptcha.class);
+
+    public static final String PROVIDER_ID = "registration-recaptcha-action";
+
+    @Override
+    public String getDisplayType() {
+        return "Recaptcha";
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return RECAPTCHA_REFERENCE_CATEGORY;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return true;
+    }
+
+    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED
+    };
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+    @Override
+    public void buildPage(FormContext context, LoginFormsProvider form) {
+        AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
+        if (captchaConfig == null || captchaConfig.getConfig() == null
+                || captchaConfig.getConfig().get(SITE_KEY) == null
+                || captchaConfig.getConfig().get(SITE_SECRET) == null
+                ) {
+            form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED));
+            return;
+        }
+        String siteKey = captchaConfig.getConfig().get(SITE_KEY);
+        form.setAttribute("recaptchaRequired", true);
+        form.setAttribute("recaptchaSiteKey", siteKey);
+        List<String> scripts = new LinkedList<>();
+        scripts.add("https://www.google.com/recaptcha/api.js");
+        form.setAttribute("scripts", scripts);
+    }
+
+    @Override
+    public void validate(ValidationContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        List<FormMessage> errors = new ArrayList<>();
+        boolean success = false;
+        context.getEvent().detail(Details.REGISTER_METHOD, "form");
+
+        String captcha = formData.getFirst(G_RECAPTCHA_RESPONSE);
+        if (!Validation.isBlank(captcha)) {
+            AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
+            String secret = captchaConfig.getConfig().get(SITE_SECRET);
+
+            HttpClient httpClient = context.getSession().getProvider(HttpClientProvider.class).getHttpClient();
+            HttpPost post = new HttpPost("https://www.google.com/recaptcha/api/siteverify");
+            List<NameValuePair> formparams = new LinkedList<>();
+            formparams.add(new BasicNameValuePair("secret", secret));
+            formparams.add(new BasicNameValuePair("response", captcha));
+            formparams.add(new BasicNameValuePair("remoteip", context.getConnection().getRemoteAddr()));
+            try {
+                UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
+                post.setEntity(form);
+                HttpResponse response = httpClient.execute(post);
+                InputStream content = response.getEntity().getContent();
+                try {
+                    Map json = JsonSerialization.readValue(content, Map.class);
+                    Object val = json.get("success");
+                    success = Boolean.TRUE.equals(val);
+                } finally {
+                    content.close();
+                }
+            } catch (Exception e) {
+                logger.error("Recaptcha failed", e);
+            }
+        }
+        if (success) {
+            context.success();
+        } else {
+            errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED));
+            formData.remove(G_RECAPTCHA_RESPONSE);
+            context.getEvent().error(Errors.INVALID_REGISTRATION);
+            context.validationError(formData, errors);
+            return;
+
+
+        }
+    }
+
+    @Override
+    public void success(FormContext context) {
+
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public FormAction create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getHelpText() {
+        return null;
+    }
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(SITE_KEY);
+        property.setLabel("Recaptcha Site Key");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setHelpText("Google Recaptcha Site Key");
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(SITE_SECRET);
+        property.setLabel("Recaptcha Secret");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setHelpText("Google Recaptcha Secret");
+        configProperties.add(property);
+
+    }
+
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
index 75f2818..9865957 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
@@ -1,199 +1,199 @@
-package org.keycloak.authentication.forms;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.FormAction;
-import org.keycloak.authentication.FormActionFactory;
-import org.keycloak.authentication.FormContext;
-import org.keycloak.authentication.ValidationContext;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.EventType;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.AttributeFormDataProcessor;
-import org.keycloak.services.validation.Validation;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RegistrationUserCreation implements FormAction, FormActionFactory {
-
-    public static final String PROVIDER_ID = "registration-user-creation";
-
-    @Override
-    public String getHelpText() {
-        return null;
-    }
-
-    @Override
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return null;
-    }
-
-    @Override
-    public void validate(ValidationContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        List<FormMessage> errors = new ArrayList<>();
-        context.getEvent().detail(Details.REGISTER_METHOD, "form");
-
-        String email = formData.getFirst(Validation.FIELD_EMAIL);
-        String username = formData.getFirst(RegistrationPage.FIELD_USERNAME);
-        context.getEvent().detail(Details.USERNAME, username);
-        context.getEvent().detail(Details.EMAIL, email);
-
-        String usernameField = RegistrationPage.FIELD_USERNAME;
-        if (context.getRealm().isRegistrationEmailAsUsername()) {
-            username = email;
-            context.getEvent().detail(Details.USERNAME, username);
-            usernameField = RegistrationPage.FIELD_EMAIL;
-            if (Validation.isBlank(email)) {
-                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
-            } else if (!Validation.isEmailValid(email)) {
-                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
-                formData.remove(Validation.FIELD_EMAIL);
-            }
-            if (errors.size() > 0) {
-                context.getEvent().error(Errors.INVALID_REGISTRATION);
-                context.validationError(formData, errors);
-                return;
-            }
-            if (email != null && context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
-                context.getEvent().error(Errors.USERNAME_IN_USE);
-                formData.remove(Validation.FIELD_EMAIL);
-                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.USERNAME_EXISTS));
-                context.validationError(formData, errors);
-                return;
-            }
-        } else {
-            if (Validation.isBlank(username)) {
-                context.getEvent().error(Errors.INVALID_REGISTRATION);
-                errors.add(new FormMessage(RegistrationPage.FIELD_USERNAME, Messages.MISSING_USERNAME));
-                context.validationError(formData, errors);
-                return;
-            }
-
-        }
-        if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
-            context.getEvent().error(Errors.USERNAME_IN_USE);
-            errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
-            formData.remove(Validation.FIELD_USERNAME);
-            formData.remove(Validation.FIELD_EMAIL);
-            context.validationError(formData, errors);
-            return;
-
-        }
-        context.success();
-    }
-
-    @Override
-    public void buildPage(FormContext context, LoginFormsProvider form) {
-
-    }
-
-    @Override
-    public void success(FormContext context) {
-        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
-        String email = formData.getFirst(Validation.FIELD_EMAIL);
-        String username = formData.getFirst(RegistrationPage.FIELD_USERNAME);
-        if (context.getRealm().isRegistrationEmailAsUsername()) {
-            username = formData.getFirst(RegistrationPage.FIELD_EMAIL);
-        }
-        context.getEvent().detail(Details.USERNAME, username)
-                .detail(Details.REGISTER_METHOD, "form")
-                .detail(Details.EMAIL, email)
-        ;
-        UserModel user = context.getSession().users().addUser(context.getRealm(), username);
-        user.setEnabled(true);
-
-        user.setEmail(email);
-        context.getClientSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
-        AttributeFormDataProcessor.process(formData, context.getRealm(), user);
-        context.setUser(user);
-        context.getEvent().user(user);
-        context.getEvent().success();
-        context.newEvent().event(EventType.LOGIN);
-        context.getEvent().client(context.getClientSession().getClient().getClientId())
-                .detail(Details.REDIRECT_URI, context.getClientSession().getRedirectUri())
-                .detail(Details.AUTH_METHOD, context.getClientSession().getAuthMethod());
-        String authType = context.getClientSession().getNote(Details.AUTH_TYPE);
-        if (authType != null) {
-            context.getEvent().detail(Details.AUTH_TYPE, authType);
-        }
-    }
-
-    @Override
-    public boolean requiresUser() {
-        return false;
-    }
-
-    @Override
-    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Registration User Creation";
-    }
-
-    @Override
-    public String getReferenceCategory() {
-        return null;
-    }
-
-    @Override
-    public boolean isConfigurable() {
-        return false;
-    }
-
-    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
-            AuthenticationExecutionModel.Requirement.REQUIRED,
-            AuthenticationExecutionModel.Requirement.DISABLED
-    };
-    @Override
-    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
-        return REQUIREMENT_CHOICES;
-    }
-    @Override
-    public FormAction create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-}
+package org.keycloak.authentication.forms;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.FormAction;
+import org.keycloak.authentication.FormActionFactory;
+import org.keycloak.authentication.FormContext;
+import org.keycloak.authentication.ValidationContext;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.resources.AttributeFormDataProcessor;
+import org.keycloak.services.validation.Validation;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RegistrationUserCreation implements FormAction, FormActionFactory {
+
+    public static final String PROVIDER_ID = "registration-user-creation";
+
+    @Override
+    public String getHelpText() {
+        return null;
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return null;
+    }
+
+    @Override
+    public void validate(ValidationContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        List<FormMessage> errors = new ArrayList<>();
+        context.getEvent().detail(Details.REGISTER_METHOD, "form");
+
+        String email = formData.getFirst(Validation.FIELD_EMAIL);
+        String username = formData.getFirst(RegistrationPage.FIELD_USERNAME);
+        context.getEvent().detail(Details.USERNAME, username);
+        context.getEvent().detail(Details.EMAIL, email);
+
+        String usernameField = RegistrationPage.FIELD_USERNAME;
+        if (context.getRealm().isRegistrationEmailAsUsername()) {
+            username = email;
+            context.getEvent().detail(Details.USERNAME, username);
+            usernameField = RegistrationPage.FIELD_EMAIL;
+            if (Validation.isBlank(email)) {
+                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL));
+            } else if (!Validation.isEmailValid(email)) {
+                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL));
+                formData.remove(Validation.FIELD_EMAIL);
+            }
+            if (errors.size() > 0) {
+                context.getEvent().error(Errors.INVALID_REGISTRATION);
+                context.validationError(formData, errors);
+                return;
+            }
+            if (email != null && context.getSession().users().getUserByEmail(email, context.getRealm()) != null) {
+                context.getEvent().error(Errors.USERNAME_IN_USE);
+                formData.remove(Validation.FIELD_EMAIL);
+                errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.USERNAME_EXISTS));
+                context.validationError(formData, errors);
+                return;
+            }
+        } else {
+            if (Validation.isBlank(username)) {
+                context.getEvent().error(Errors.INVALID_REGISTRATION);
+                errors.add(new FormMessage(RegistrationPage.FIELD_USERNAME, Messages.MISSING_USERNAME));
+                context.validationError(formData, errors);
+                return;
+            }
+
+        }
+        if (context.getSession().users().getUserByUsername(username, context.getRealm()) != null) {
+            context.getEvent().error(Errors.USERNAME_IN_USE);
+            errors.add(new FormMessage(usernameField, Messages.USERNAME_EXISTS));
+            formData.remove(Validation.FIELD_USERNAME);
+            formData.remove(Validation.FIELD_EMAIL);
+            context.validationError(formData, errors);
+            return;
+
+        }
+        context.success();
+    }
+
+    @Override
+    public void buildPage(FormContext context, LoginFormsProvider form) {
+
+    }
+
+    @Override
+    public void success(FormContext context) {
+        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
+        String email = formData.getFirst(Validation.FIELD_EMAIL);
+        String username = formData.getFirst(RegistrationPage.FIELD_USERNAME);
+        if (context.getRealm().isRegistrationEmailAsUsername()) {
+            username = formData.getFirst(RegistrationPage.FIELD_EMAIL);
+        }
+        context.getEvent().detail(Details.USERNAME, username)
+                .detail(Details.REGISTER_METHOD, "form")
+                .detail(Details.EMAIL, email)
+        ;
+        UserModel user = context.getSession().users().addUser(context.getRealm(), username);
+        user.setEnabled(true);
+
+        user.setEmail(email);
+        context.getClientSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
+        AttributeFormDataProcessor.process(formData, context.getRealm(), user);
+        context.setUser(user);
+        context.getEvent().user(user);
+        context.getEvent().success();
+        context.newEvent().event(EventType.LOGIN);
+        context.getEvent().client(context.getClientSession().getClient().getClientId())
+                .detail(Details.REDIRECT_URI, context.getClientSession().getRedirectUri())
+                .detail(Details.AUTH_METHOD, context.getClientSession().getAuthMethod());
+        String authType = context.getClientSession().getNote(Details.AUTH_TYPE);
+        if (authType != null) {
+            context.getEvent().detail(Details.AUTH_TYPE, authType);
+        }
+    }
+
+    @Override
+    public boolean requiresUser() {
+        return false;
+    }
+
+    @Override
+    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+        return true;
+    }
+
+    @Override
+    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Registration User Creation";
+    }
+
+    @Override
+    public String getReferenceCategory() {
+        return null;
+    }
+
+    @Override
+    public boolean isConfigurable() {
+        return false;
+    }
+
+    private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+            AuthenticationExecutionModel.Requirement.REQUIRED,
+            AuthenticationExecutionModel.Requirement.DISABLED
+    };
+    @Override
+    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+        return REQUIREMENT_CHOICES;
+    }
+    @Override
+    public FormAction create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/RequiredActionContext.java b/services/src/main/java/org/keycloak/authentication/RequiredActionContext.java
index 4a838a3..8345f48 100755
--- a/services/src/main/java/org/keycloak/authentication/RequiredActionContext.java
+++ b/services/src/main/java/org/keycloak/authentication/RequiredActionContext.java
@@ -1,29 +1,29 @@
-package org.keycloak.authentication;
-
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-
-import javax.ws.rs.core.UriInfo;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RequiredActionContext {
-    EventBuilder getEvent();
-    UserModel getUser();
-    RealmModel getRealm();
-    ClientSessionModel getClientSession();
-    UserSessionModel getUserSession();
-    ClientConnection getConnection();
-    UriInfo getUriInfo();
-    KeycloakSession getSession();
-    HttpRequest getHttpRequest();
-    String generateAccessCode(String action);
-}
+package org.keycloak.authentication;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RequiredActionContext {
+    EventBuilder getEvent();
+    UserModel getUser();
+    RealmModel getRealm();
+    ClientSessionModel getClientSession();
+    UserSessionModel getUserSession();
+    ClientConnection getConnection();
+    UriInfo getUriInfo();
+    KeycloakSession getSession();
+    HttpRequest getHttpRequest();
+    String generateAccessCode(String action);
+}
diff --git a/services/src/main/java/org/keycloak/authentication/RequiredActionFactory.java b/services/src/main/java/org/keycloak/authentication/RequiredActionFactory.java
index b049781..120f014 100755
--- a/services/src/main/java/org/keycloak/authentication/RequiredActionFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/RequiredActionFactory.java
@@ -1,11 +1,11 @@
-package org.keycloak.authentication;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RequiredActionFactory extends ProviderFactory<RequiredActionProvider> {
-    String getDisplayText();
-}
+package org.keycloak.authentication;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RequiredActionFactory extends ProviderFactory<RequiredActionProvider> {
+    String getDisplayText();
+}
diff --git a/services/src/main/java/org/keycloak/authentication/RequiredActionProvider.java b/services/src/main/java/org/keycloak/authentication/RequiredActionProvider.java
index 628f5c7..81c41a3 100755
--- a/services/src/main/java/org/keycloak/authentication/RequiredActionProvider.java
+++ b/services/src/main/java/org/keycloak/authentication/RequiredActionProvider.java
@@ -1,16 +1,16 @@
-package org.keycloak.authentication;
-
-import org.keycloak.provider.Provider;
-
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface RequiredActionProvider extends Provider {
-    void evaluateTriggers(RequiredActionContext context);
-    Response invokeRequiredAction(RequiredActionContext context);
-    Object jaxrsService(RequiredActionContext context);
-    String getProviderId();
-}
+package org.keycloak.authentication;
+
+import org.keycloak.provider.Provider;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RequiredActionProvider extends Provider {
+    void evaluateTriggers(RequiredActionContext context);
+    Response invokeRequiredAction(RequiredActionContext context);
+    Object jaxrsService(RequiredActionContext context);
+    String getProviderId();
+}
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/TermsAndConditions.java b/services/src/main/java/org/keycloak/authentication/requiredactions/TermsAndConditions.java
index da6d061..5ad5132 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/TermsAndConditions.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/TermsAndConditions.java
@@ -1,112 +1,112 @@
-package org.keycloak.authentication.requiredactions;
-
-import org.keycloak.Config;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.events.Errors;
-import org.keycloak.freemarker.FreeMarkerException;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.services.managers.AuthenticationManager;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class TermsAndConditions implements RequiredActionProvider, RequiredActionFactory {
-
-    public static final String PROVIDER_ID = "terms_and_conditions";
-
-    public static class Resource {
-
-        public Resource(RequiredActionContext context) {
-            this.context = context;
-        }
-
-        protected RequiredActionContext context;
-
-        @POST
-        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-        public Response agree(final MultivaluedMap<String, String> formData)  throws URISyntaxException, IOException, FreeMarkerException {
-            if (formData.containsKey("cancel")) {
-                LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
-                protocol.setRealm(context.getRealm())
-                        .setHttpHeaders(context.getHttpRequest().getHttpHeaders())
-                        .setUriInfo(context.getUriInfo());
-                context.getEvent().error(Errors.REJECTED_BY_USER);
-                return protocol.consentDenied(context.getClientSession());
-            }
-            context.getUser().removeRequiredAction(PROVIDER_ID);
-            return AuthenticationManager.nextActionAfterAuthentication(context.getSession(), context.getUserSession(), context.getClientSession(), context.getConnection(), context.getHttpRequest(), context.getUriInfo(), context.getEvent());
-        }
-
-    }
-
-    @Override
-    public RequiredActionProvider create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-
-    @Override
-    public String getProviderId() {
-        return getId();
-    }
-
-
-
-    @Override
-    public void evaluateTriggers(RequiredActionContext context) {
-
-    }
-
-    @Override
-    public Response invokeRequiredAction(RequiredActionContext context) {
-        return context.getSession().getProvider(LoginFormsProvider.class)
-                .setClientSessionCode(context.generateAccessCode(getProviderId()))
-                .setUser(context.getUser())
-                .createForm("terms.ftl", new HashMap<String, Object>());
-    }
-
-    @Override
-    public Object jaxrsService(RequiredActionContext context) {
-        return new Resource(context);
-    }
-
-    @Override
-    public String getDisplayText() {
-        return "Terms and Conditions";
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.authentication.requiredactions;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.events.Errors;
+import org.keycloak.freemarker.FreeMarkerException;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.services.managers.AuthenticationManager;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class TermsAndConditions implements RequiredActionProvider, RequiredActionFactory {
+
+    public static final String PROVIDER_ID = "terms_and_conditions";
+
+    public static class Resource {
+
+        public Resource(RequiredActionContext context) {
+            this.context = context;
+        }
+
+        protected RequiredActionContext context;
+
+        @POST
+        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+        public Response agree(final MultivaluedMap<String, String> formData)  throws URISyntaxException, IOException, FreeMarkerException {
+            if (formData.containsKey("cancel")) {
+                LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
+                protocol.setRealm(context.getRealm())
+                        .setHttpHeaders(context.getHttpRequest().getHttpHeaders())
+                        .setUriInfo(context.getUriInfo());
+                context.getEvent().error(Errors.REJECTED_BY_USER);
+                return protocol.consentDenied(context.getClientSession());
+            }
+            context.getUser().removeRequiredAction(PROVIDER_ID);
+            return AuthenticationManager.nextActionAfterAuthentication(context.getSession(), context.getUserSession(), context.getClientSession(), context.getConnection(), context.getHttpRequest(), context.getUriInfo(), context.getEvent());
+        }
+
+    }
+
+    @Override
+    public RequiredActionProvider create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+
+    @Override
+    public String getProviderId() {
+        return getId();
+    }
+
+
+
+    @Override
+    public void evaluateTriggers(RequiredActionContext context) {
+
+    }
+
+    @Override
+    public Response invokeRequiredAction(RequiredActionContext context) {
+        return context.getSession().getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(context.generateAccessCode(getProviderId()))
+                .setUser(context.getUser())
+                .createForm("terms.ftl", new HashMap<String, Object>());
+    }
+
+    @Override
+    public Object jaxrsService(RequiredActionContext context) {
+        return new Resource(context);
+    }
+
+    @Override
+    public String getDisplayText() {
+        return "Terms and Conditions";
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
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 ab6eb27..d59a827 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
@@ -1,102 +1,102 @@
-package org.keycloak.authentication.requiredactions;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.Response;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UpdatePassword implements RequiredActionProvider, RequiredActionFactory {
-    protected static Logger logger = Logger.getLogger(UpdatePassword.class);
-    @Override
-    public void evaluateTriggers(RequiredActionContext context) {
-        int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
-        if(daysToExpirePassword != -1) {
-            for (UserCredentialValueModel entity : context.getUser().getCredentialsDirectly()) {
-                if (entity.getType().equals(UserCredentialModel.PASSWORD)) {
-
-                    if(entity.getCreatedDate() == null) {
-                        context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                        logger.debug("User is required to update password");
-                    } else {
-                        long timeElapsed = Time.toMillis(Time.currentTime()) - entity.getCreatedDate();
-                        long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
-
-                        if(timeElapsed > timeToExpire) {
-                            context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                            logger.debug("User is required to update password");
-                        }
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-    @Override
-    public Response invokeRequiredAction(RequiredActionContext context) {
-        LoginFormsProvider loginFormsProvider = context.getSession()
-                .getProvider(LoginFormsProvider.class)
-                .setClientSessionCode(context.generateAccessCode(getProviderId()))
-                .setUser(context.getUser());
-        return loginFormsProvider.createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
-    }
-
-    @Override
-    public Object jaxrsService(RequiredActionContext context) {
-        // this is handled by LoginActionsService at the moment
-        return null;
-    }
-
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public RequiredActionProvider create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getDisplayText() {
-        return "Update Password";
-    }
-
-
-    @Override
-    public String getId() {
-        return UserModel.RequiredAction.UPDATE_PASSWORD.name();
-    }
-
-    @Override
-    public String getProviderId() {
-        return getId();
-    }
-
-}
+package org.keycloak.authentication.requiredactions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.Response;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UpdatePassword implements RequiredActionProvider, RequiredActionFactory {
+    protected static Logger logger = Logger.getLogger(UpdatePassword.class);
+    @Override
+    public void evaluateTriggers(RequiredActionContext context) {
+        int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
+        if(daysToExpirePassword != -1) {
+            for (UserCredentialValueModel entity : context.getUser().getCredentialsDirectly()) {
+                if (entity.getType().equals(UserCredentialModel.PASSWORD)) {
+
+                    if(entity.getCreatedDate() == null) {
+                        context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                        logger.debug("User is required to update password");
+                    } else {
+                        long timeElapsed = Time.toMillis(Time.currentTime()) - entity.getCreatedDate();
+                        long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
+
+                        if(timeElapsed > timeToExpire) {
+                            context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                            logger.debug("User is required to update password");
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public Response invokeRequiredAction(RequiredActionContext context) {
+        LoginFormsProvider loginFormsProvider = context.getSession()
+                .getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(context.generateAccessCode(getProviderId()))
+                .setUser(context.getUser());
+        return loginFormsProvider.createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
+    }
+
+    @Override
+    public Object jaxrsService(RequiredActionContext context) {
+        // this is handled by LoginActionsService at the moment
+        return null;
+    }
+
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public RequiredActionProvider create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getDisplayText() {
+        return "Update Password";
+    }
+
+
+    @Override
+    public String getId() {
+        return UserModel.RequiredAction.UPDATE_PASSWORD.name();
+    }
+
+    @Override
+    public String getProviderId() {
+        return getId();
+    }
+
+}
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 e353cce..1b30df1 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java
@@ -1,81 +1,81 @@
-package org.keycloak.authentication.requiredactions;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserModel;
-
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory {
-    protected static Logger logger = Logger.getLogger(UpdateProfile.class);
-    @Override
-    public void evaluateTriggers(RequiredActionContext context) {
-        if (context.getRealm().isVerifyEmail() && !context.getUser().isEmailVerified()) {
-            context.getUser().addRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL);
-            logger.debug("User is required to verify email");
-        }
-    }
-
-    @Override
-    public Response invokeRequiredAction(RequiredActionContext context) {
-        LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
-                .setClientSessionCode(context.generateAccessCode(getProviderId()))
-                .setUser(context.getUser());
-        return loginFormsProvider.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
-    }
-
-    @Override
-    public Object jaxrsService(RequiredActionContext context) {
-        // this is handled by LoginActionsService at the moment
-        // todo should be refactored to contain it here
-        return null;
-    }
-
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public RequiredActionProvider create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getDisplayText() {
-        return "Update Profile";
-    }
-
-
-    @Override
-    public String getId() {
-        return UserModel.RequiredAction.UPDATE_PROFILE.name();
-    }
-
-    @Override
-    public String getProviderId() {
-        return getId();
-    }
-
-}
+package org.keycloak.authentication.requiredactions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserModel;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory {
+    protected static Logger logger = Logger.getLogger(UpdateProfile.class);
+    @Override
+    public void evaluateTriggers(RequiredActionContext context) {
+        if (context.getRealm().isVerifyEmail() && !context.getUser().isEmailVerified()) {
+            context.getUser().addRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL);
+            logger.debug("User is required to verify email");
+        }
+    }
+
+    @Override
+    public Response invokeRequiredAction(RequiredActionContext context) {
+        LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(context.generateAccessCode(getProviderId()))
+                .setUser(context.getUser());
+        return loginFormsProvider.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
+    }
+
+    @Override
+    public Object jaxrsService(RequiredActionContext context) {
+        // this is handled by LoginActionsService at the moment
+        // todo should be refactored to contain it here
+        return null;
+    }
+
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public RequiredActionProvider create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getDisplayText() {
+        return "Update Profile";
+    }
+
+
+    @Override
+    public String getId() {
+        return UserModel.RequiredAction.UPDATE_PROFILE.name();
+    }
+
+    @Override
+    public String getProviderId() {
+        return getId();
+    }
+
+}
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 dd41927..dca0ed8 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
@@ -1,88 +1,88 @@
-package org.keycloak.authentication.requiredactions;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.CredentialRepresentation;
-
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory {
-    protected static Logger logger = Logger.getLogger(UpdateTotp.class);
-    @Override
-    public void evaluateTriggers(RequiredActionContext context) {
-        // I don't think we need this check here.  AuthenticationProcessor should be setting the required action
-        // if OTP changes from required from optional or disabled
-        for (RequiredCredentialModel c : context.getRealm().getRequiredCredentials()) {
-            if (c.getType().equals(CredentialRepresentation.TOTP) && !context.getUser().isTotp()) {
-                context.getUser().addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
-                logger.debug("User is required to configure totp");
-            }
-        }
-    }
-
-    @Override
-    public Response invokeRequiredAction(RequiredActionContext context) {
-         LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
-                 .setClientSessionCode(context.generateAccessCode(getProviderId()))
-                .setUser(context.getUser());
-        return loginFormsProvider.createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
-    }
-
-    @Override
-    public Object jaxrsService(RequiredActionContext context) {
-        // this is handled by LoginActionsService at the moment
-        // todo should be refactored to contain it here
-        return null;
-    }
-
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public RequiredActionProvider create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getDisplayText() {
-        return "Configure Totp";
-    }
-
-
-    @Override
-    public String getId() {
-        return UserModel.RequiredAction.CONFIGURE_TOTP.name();
-    }
-
-    @Override
-    public String getProviderId() {
-        return getId();
-    }
-
-
-}
+package org.keycloak.authentication.requiredactions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory {
+    protected static Logger logger = Logger.getLogger(UpdateTotp.class);
+    @Override
+    public void evaluateTriggers(RequiredActionContext context) {
+        // I don't think we need this check here.  AuthenticationProcessor should be setting the required action
+        // if OTP changes from required from optional or disabled
+        for (RequiredCredentialModel c : context.getRealm().getRequiredCredentials()) {
+            if (c.getType().equals(CredentialRepresentation.TOTP) && !context.getUser().isTotp()) {
+                context.getUser().addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
+                logger.debug("User is required to configure totp");
+            }
+        }
+    }
+
+    @Override
+    public Response invokeRequiredAction(RequiredActionContext context) {
+         LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
+                 .setClientSessionCode(context.generateAccessCode(getProviderId()))
+                .setUser(context.getUser());
+        return loginFormsProvider.createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
+    }
+
+    @Override
+    public Object jaxrsService(RequiredActionContext context) {
+        // this is handled by LoginActionsService at the moment
+        // todo should be refactored to contain it here
+        return null;
+    }
+
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public RequiredActionProvider create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getDisplayText() {
+        return "Configure Totp";
+    }
+
+
+    @Override
+    public String getId() {
+        return UserModel.RequiredAction.CONFIGURE_TOTP.name();
+    }
+
+    @Override
+    public String getProviderId() {
+        return getId();
+    }
+
+
+}
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 33b4333..ca0a153 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
@@ -1,113 +1,113 @@
-package org.keycloak.authentication.requiredactions;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventType;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.services.resources.LoginActionsService;
-import org.keycloak.services.validation.Validation;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.Response;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class VerifyEmail implements RequiredActionProvider, RequiredActionFactory {
-    protected static Logger logger = Logger.getLogger(VerifyEmail.class);
-    @Override
-    public void evaluateTriggers(RequiredActionContext context) {
-        int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
-        if(daysToExpirePassword != -1) {
-            for (UserCredentialValueModel entity : context.getUser().getCredentialsDirectly()) {
-                if (entity.getType().equals(UserCredentialModel.PASSWORD)) {
-
-                    if(entity.getCreatedDate() == null) {
-                        context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                        logger.debug("User is required to update password");
-                    } else {
-                        long timeElapsed = Time.toMillis(Time.currentTime()) - entity.getCreatedDate();
-                        long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
-
-                        if(timeElapsed > timeToExpire) {
-                            context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                            logger.debug("User is required to update password");
-                        }
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-    @Override
-    public Response invokeRequiredAction(RequiredActionContext context) {
-        if (Validation.isBlank(context.getUser().getEmail())) {
-            return null;
-        }
-
-        context.getEvent().clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, context.getUser().getEmail()).success();
-        LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getUserSession().getId());
-
-        LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
-                .setClientSessionCode(context.generateAccessCode(getProviderId()))
-                .setUser(context.getUser());
-        return loginFormsProvider.createResponse(UserModel.RequiredAction.VERIFY_EMAIL);
-    }
-
-    @Override
-    public Object jaxrsService(RequiredActionContext context) {
-        // this is handled by LoginActionsService at the moment
-        return null;
-    }
-
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public RequiredActionProvider create(KeycloakSession session) {
-        return this;
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public String getDisplayText() {
-        return "Verify Email";
-    }
-
-
-    @Override
-    public String getId() {
-        return UserModel.RequiredAction.VERIFY_EMAIL.name();
-    }
-
-    @Override
-    public String getProviderId() {
-        return getId();
-    }
-
-
-}
+package org.keycloak.authentication.requiredactions;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.services.validation.Validation;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.Response;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class VerifyEmail implements RequiredActionProvider, RequiredActionFactory {
+    protected static Logger logger = Logger.getLogger(VerifyEmail.class);
+    @Override
+    public void evaluateTriggers(RequiredActionContext context) {
+        int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
+        if(daysToExpirePassword != -1) {
+            for (UserCredentialValueModel entity : context.getUser().getCredentialsDirectly()) {
+                if (entity.getType().equals(UserCredentialModel.PASSWORD)) {
+
+                    if(entity.getCreatedDate() == null) {
+                        context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                        logger.debug("User is required to update password");
+                    } else {
+                        long timeElapsed = Time.toMillis(Time.currentTime()) - entity.getCreatedDate();
+                        long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
+
+                        if(timeElapsed > timeToExpire) {
+                            context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                            logger.debug("User is required to update password");
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public Response invokeRequiredAction(RequiredActionContext context) {
+        if (Validation.isBlank(context.getUser().getEmail())) {
+            return null;
+        }
+
+        context.getEvent().clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, context.getUser().getEmail()).success();
+        LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getUserSession().getId());
+
+        LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(context.generateAccessCode(getProviderId()))
+                .setUser(context.getUser());
+        return loginFormsProvider.createResponse(UserModel.RequiredAction.VERIFY_EMAIL);
+    }
+
+    @Override
+    public Object jaxrsService(RequiredActionContext context) {
+        // this is handled by LoginActionsService at the moment
+        return null;
+    }
+
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public RequiredActionProvider create(KeycloakSession session) {
+        return this;
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public String getDisplayText() {
+        return "Verify Email";
+    }
+
+
+    @Override
+    public String getId() {
+        return UserModel.RequiredAction.VERIFY_EMAIL.name();
+    }
+
+    @Override
+    public String getProviderId() {
+        return getId();
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/ValidationContext.java b/services/src/main/java/org/keycloak/authentication/ValidationContext.java
index 7a4eb44..8ff791d 100755
--- a/services/src/main/java/org/keycloak/authentication/ValidationContext.java
+++ b/services/src/main/java/org/keycloak/authentication/ValidationContext.java
@@ -1,15 +1,15 @@
-package org.keycloak.authentication;
-
-import org.keycloak.models.utils.FormMessage;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.List;
-
-/**
-* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-* @version $Revision: 1 $
-*/
-public interface ValidationContext extends FormContext {
-    void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
-    void success();
-}
+package org.keycloak.authentication;
+
+import org.keycloak.models.utils.FormMessage;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.List;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public interface ValidationContext extends FormContext {
+    void validationError(MultivaluedMap<String, String> formData, List<FormMessage> errors);
+    void success();
+}
diff --git a/services/src/main/java/org/keycloak/exportimport/ClientImporter.java b/services/src/main/java/org/keycloak/exportimport/ClientImporter.java
index 3d236fb..e4f7821 100755
--- a/services/src/main/java/org/keycloak/exportimport/ClientImporter.java
+++ b/services/src/main/java/org/keycloak/exportimport/ClientImporter.java
@@ -1,15 +1,15 @@
-package org.keycloak.exportimport;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.provider.Provider;
-import org.keycloak.services.resources.admin.RealmAuth;
-
-/**
- * Provider plugin interface for importing clients from an arbitrary configuration format
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ClientImporter extends Provider {
-    public Object createJaxrsService(RealmModel realm, RealmAuth auth);
-}
+package org.keycloak.exportimport;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.provider.Provider;
+import org.keycloak.services.resources.admin.RealmAuth;
+
+/**
+ * Provider plugin interface for importing clients from an arbitrary configuration format
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientImporter extends Provider {
+    public Object createJaxrsService(RealmModel realm, RealmAuth auth);
+}
diff --git a/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java b/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java
index e70bbfa..4cb47cd 100755
--- a/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java
+++ b/services/src/main/java/org/keycloak/exportimport/ClientImporterFactory.java
@@ -1,13 +1,13 @@
-package org.keycloak.exportimport;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * Provider plugin interface for importing clients from an arbitrary configuration format
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ClientImporterFactory extends ProviderFactory<ClientImporter> {
-    public String getDisplayName();
-}
+package org.keycloak.exportimport;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * Provider plugin interface for importing clients from an arbitrary configuration format
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ClientImporterFactory extends ProviderFactory<ClientImporter> {
+    public String getDisplayName();
+}
diff --git a/services/src/main/java/org/keycloak/messages/MessagesProvider.java b/services/src/main/java/org/keycloak/messages/MessagesProvider.java
index ddb72dd..8643acb 100644
--- a/services/src/main/java/org/keycloak/messages/MessagesProvider.java
+++ b/services/src/main/java/org/keycloak/messages/MessagesProvider.java
@@ -1,12 +1,12 @@
-package org.keycloak.messages;
-
-import org.keycloak.provider.Provider;
-
-/**
- * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
- */
-public interface MessagesProvider extends Provider {
-
-    String getMessage(String messageKey, Object... parameters);
-
-}
+package org.keycloak.messages;
+
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public interface MessagesProvider extends Provider {
+
+    String getMessage(String messageKey, Object... parameters);
+
+}
diff --git a/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java b/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java
index 92c0df8..ae6079b 100644
--- a/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java
+++ b/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.messages;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
- */
-public interface MessagesProviderFactory extends ProviderFactory<MessagesProvider> {
-
-}
+package org.keycloak.messages;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public interface MessagesProviderFactory extends ProviderFactory<MessagesProvider> {
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
index aa86a26..3fd29c2 100755
--- a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
@@ -1,39 +1,39 @@
-package org.keycloak.protocol;
-
-import org.keycloak.Config;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.provider.ProviderEvent;
-import org.keycloak.provider.ProviderEventListener;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory {
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-        factory.register(new ProviderEventListener() {
-            @Override
-            public void onEvent(ProviderEvent event) {
-                if (event instanceof RealmModel.ClientCreationEvent) {
-                    ClientModel client = ((RealmModel.ClientCreationEvent)event).getCreatedClient();
-                    addDefaults(client);
-                }
-            }
-        });
-    }
-
-    protected abstract void addDefaults(ClientModel realm);
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.protocol;
+
+import org.keycloak.Config;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.provider.ProviderEvent;
+import org.keycloak.provider.ProviderEventListener;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory {
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+        factory.register(new ProviderEventListener() {
+            @Override
+            public void onEvent(ProviderEvent event) {
+                if (event instanceof RealmModel.ClientCreationEvent) {
+                    ClientModel client = ((RealmModel.ClientCreationEvent)event).getCreatedClient();
+                    addDefaults(client);
+                }
+            }
+        });
+    }
+
+    protected abstract void addDefaults(ClientModel realm);
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocol.java b/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
index 51676f3..4a7836d 100755
--- a/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
@@ -1,37 +1,37 @@
-package org.keycloak.protocol;
-
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.provider.Provider;
-import org.keycloak.services.managers.ClientSessionCode;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface LoginProtocol extends Provider {
-    LoginProtocol setSession(KeycloakSession session);
-
-    LoginProtocol setRealm(RealmModel realm);
-
-    LoginProtocol setUriInfo(UriInfo uriInfo);
-
-    LoginProtocol setHttpHeaders(HttpHeaders headers);
-
-    LoginProtocol setEventBuilder(EventBuilder event);
-
-    Response cancelLogin(ClientSessionModel clientSession);
-    Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode);
-    Response consentDenied(ClientSessionModel clientSession);
-
-    void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
-    Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
-    Response finishLogout(UserSessionModel userSession);
-}
+package org.keycloak.protocol;
+
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.provider.Provider;
+import org.keycloak.services.managers.ClientSessionCode;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface LoginProtocol extends Provider {
+    LoginProtocol setSession(KeycloakSession session);
+
+    LoginProtocol setRealm(RealmModel realm);
+
+    LoginProtocol setUriInfo(UriInfo uriInfo);
+
+    LoginProtocol setHttpHeaders(HttpHeaders headers);
+
+    LoginProtocol setEventBuilder(EventBuilder event);
+
+    Response cancelLogin(ClientSessionModel clientSession);
+    Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode);
+    Response consentDenied(ClientSessionModel clientSession);
+
+    void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
+    Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
+    Response finishLogout(UserSessionModel userSession);
+}
diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
index 5e5bf0b..5742381 100755
--- a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
@@ -1,30 +1,30 @@
-package org.keycloak.protocol;
-
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.services.managers.AuthenticationManager;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
-    /**
-     * List of built in protocol mappers that can be used to apply to clients.
-     *
-     * @return
-     */
-    List<ProtocolMapperModel> getBuiltinMappers();
-
-    /**
-     * List of mappers, which are added to new clients by default
-     * @return
-     */
-    List<ProtocolMapperModel> getDefaultBuiltinMappers();
-
-    Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager);
-}
+package org.keycloak.protocol;
+
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.services.managers.AuthenticationManager;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
+    /**
+     * List of built in protocol mappers that can be used to apply to clients.
+     *
+     * @return
+     */
+    List<ProtocolMapperModel> getBuiltinMappers();
+
+    /**
+     * List of mappers, which are added to new clients by default
+     * @return
+     */
+    List<ProtocolMapperModel> getDefaultBuiltinMappers();
+
+    Object createProtocolEndpoint(RealmModel realm, EventBuilder event, 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 603f3dd..0919cf7 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
@@ -1,314 +1,314 @@
-package org.keycloak.protocol.oidc.endpoints;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.utils.RedirectUtils;
-import org.keycloak.services.ErrorPageException;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.Urls;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.List;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class AuthorizationEndpoint {
-
-    private static final Logger logger = Logger.getLogger(AuthorizationEndpoint.class);
-    public static final String CODE_AUTH_TYPE = "code";
-
-    private enum Action {
-        REGISTER, CODE
-    }
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private HttpRequest request;
-
-    @Context
-    private HttpHeaders headers;
-
-    @Context
-    private UriInfo uriInfo;
-
-    @Context
-    private ClientConnection clientConnection;
-
-    private final AuthenticationManager authManager;
-    private final RealmModel realm;
-    private final EventBuilder event;
-
-    private ClientModel client;
-    private ClientSessionModel clientSession;
-
-    private Action action;
-
-    private String clientId;
-    private String redirectUri;
-    private String redirectUriParam;
-    private String responseType;
-    private String state;
-    private String scope;
-    private String loginHint;
-    private String prompt;
-    private String nonce;
-    private String idpHint;
-
-    private String legacyResponseType;
-
-    public AuthorizationEndpoint(AuthenticationManager authManager, RealmModel realm, EventBuilder event) {
-        this.authManager = authManager;
-        this.realm = realm;
-        this.event = event;
-        event.event(EventType.LOGIN);
-    }
-
-    @GET
-    public Response build() {
-        MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
-
-        clientId = params.getFirst(OIDCLoginProtocol.CLIENT_ID_PARAM);
-        responseType = params.getFirst(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
-        redirectUriParam = params.getFirst(OIDCLoginProtocol.REDIRECT_URI_PARAM);
-        state = params.getFirst(OIDCLoginProtocol.STATE_PARAM);
-        scope = params.getFirst(OIDCLoginProtocol.SCOPE_PARAM);
-        loginHint = params.getFirst(OIDCLoginProtocol.LOGIN_HINT_PARAM);
-        prompt = params.getFirst(OIDCLoginProtocol.PROMPT_PARAM);
-        idpHint = params.getFirst(AdapterConstants.KC_IDP_HINT);
-        nonce = params.getFirst(OIDCLoginProtocol.NONCE_PARAM);
-
-        checkSsl();
-        checkRealm();
-        checkClient();
-        checkResponseType();
-        checkRedirectUri();
-
-        createClientSession();
-
-        switch (action) {
-            case REGISTER:
-                return buildRegister();
-            case CODE:
-                return buildAuthorizationCodeAuthorizationResponse();
-        }
-
-        throw new RuntimeException("Unknown action " + action);
-    }
-
-    /**
-     * @deprecated
-     */
-    public AuthorizationEndpoint legacy(String legacyResponseType) {
-        logger.warnv("Invoking deprecated endpoint {0}", uriInfo.getRequestUri());
-        this.legacyResponseType = legacyResponseType;
-        return this;
-    }
-
-    public AuthorizationEndpoint register() {
-        event.event(EventType.REGISTER);
-        action = Action.REGISTER;
-
-        if (!realm.isRegistrationAllowed()) {
-            throw new ErrorPageException(session, Messages.REGISTRATION_NOT_ALLOWED);
-        }
-
-        return this;
-    }
-
-    private void checkSsl() {
-        if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
-            event.error(Errors.SSL_REQUIRED);
-            throw new ErrorPageException(session, Messages.HTTPS_REQUIRED);
-        }
-    }
-
-    private void checkRealm() {
-        if (!realm.isEnabled()) {
-            event.error(Errors.REALM_DISABLED);
-            throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
-        }
-    }
-
-    private void checkClient() {
-        if (clientId == null) {
-            event.error(Errors.INVALID_REQUEST);
-            throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
-        }
-
-        event.client(clientId);
-
-        client = realm.getClientByClientId(clientId);
-        if (client == null) {
-            event.error(Errors.CLIENT_NOT_FOUND);
-            throw new ErrorPageException(session, Messages.CLIENT_NOT_FOUND );
-        }
-
-        if (client.isBearerOnly()) {
-            event.error(Errors.NOT_ALLOWED);
-            throw new ErrorPageException(session, Messages.BEARER_ONLY );
-        }
-
-        if (client.isDirectGrantsOnly()) {
-            event.error(Errors.NOT_ALLOWED);
-            throw new ErrorPageException(session, Messages.DIRECT_GRANTS_ONLY);
-        }
-
-        session.getContext().setClient(client);
-    }
-
-    private void checkResponseType() {
-        if (responseType == null) {
-            if (legacyResponseType != null) {
-                responseType = legacyResponseType;
-            } else {
-                event.error(Errors.INVALID_REQUEST);
-                throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
-            }
-        }
-
-        event.detail(Details.RESPONSE_TYPE, responseType);
-
-        if (responseType.equals(OAuth2Constants.CODE)) {
-            if (action == null) {
-                action = Action.CODE;
-            }
-        } else {
-            event.error(Errors.INVALID_REQUEST);
-            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
-        }
-    }
-
-    private void checkRedirectUri() {
-        event.detail(Details.REDIRECT_URI, redirectUriParam);
-
-        redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUriParam, realm, client);
-        if (redirectUri == null) {
-            event.error(Errors.INVALID_REDIRECT_URI);
-            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
-        }
-    }
-
-    private void createClientSession() {
-        clientSession = session.sessions().createClientSession(realm, client);
-        clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        clientSession.setRedirectUri(redirectUri);
-        clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
-        clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, responseType);
-        clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUriParam);
-        clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
-
-        if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
-        if (nonce != null) clientSession.setNote(OIDCLoginProtocol.NONCE_PARAM, nonce);
-        if (scope != null) clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
-        if (loginHint != null) clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
-        if (prompt != null) clientSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, prompt);
-        if (idpHint != null) clientSession.setNote(AdapterConstants.KC_IDP_HINT, idpHint);
-    }
-
-    private Response buildAuthorizationCodeAuthorizationResponse() {
-        String accessCode = new ClientSessionCode(realm, clientSession).getCode();
-
-        if (idpHint != null && !"".equals(idpHint)) {
-            IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
-
-            if (identityProviderModel == null) {
-                return session.getProvider(LoginFormsProvider.class)
-                        .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
-                        .createErrorPage();
-            }
-            return buildRedirectToIdentityProvider(idpHint, accessCode);
-        }
-
-        return browserAuthentication(accessCode);
-    }
-
-    protected Response browserAuthentication(String accessCode) {
-        this.event.event(EventType.LOGIN);
-        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
-        for (IdentityProviderModel identityProvider : identityProviders) {
-            if (identityProvider.isAuthenticateByDefault()) {
-                return buildRedirectToIdentityProvider(identityProvider.getAlias(), accessCode);
-            }
-        }
-        clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
-
-        AuthenticationFlowModel flow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
-        String flowId = flow.getId();
-        AuthenticationProcessor processor = new AuthenticationProcessor();
-        processor.setClientSession(clientSession)
-                .setFlowId(flowId)
-                .setConnection(clientConnection)
-                .setEventBuilder(event)
-                .setProtector(authManager.getProtector())
-                .setRealm(realm)
-                .setSession(session)
-                .setUriInfo(uriInfo)
-                .setRequest(request);
-
-        Response challenge = null;
-        try {
-            challenge = processor.authenticateOnly();
-        } catch (Exception e) {
-            return processor.handleBrowserException(e);
-        }
-
-        if (challenge != null && prompt != null && prompt.equals("none")) {
-            if (processor.isUserSessionCreated()) {
-                session.sessions().removeUserSession(realm, processor.getUserSession());
-            }
-            OIDCLoginProtocol oauth = new OIDCLoginProtocol(session, realm, uriInfo, headers, event);
-            return oauth.cancelLogin(clientSession);
-        }
-
-        if (challenge == null) {
-            return processor.finishAuthentication();
-        } else {
-            return challenge;
-        }
-    }
-
-    private Response buildRegister() {
-        authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
-
-        return session.getProvider(LoginFormsProvider.class)
-                .setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode())
-                .createRegistration();
-    }
-
-    private Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
-        logger.debug("Automatically redirect to identity provider: " + providerId);
-        return Response.temporaryRedirect(
-                Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, this.realm.getName(), accessCode))
-                .build();
-    }
-
+package org.keycloak.protocol.oidc.endpoints;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.authentication.AuthenticationProcessor;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.utils.RedirectUtils;
+import org.keycloak.services.ErrorPageException;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.Urls;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AuthorizationEndpoint {
+
+    private static final Logger logger = Logger.getLogger(AuthorizationEndpoint.class);
+    public static final String CODE_AUTH_TYPE = "code";
+
+    private enum Action {
+        REGISTER, CODE
+    }
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private HttpRequest request;
+
+    @Context
+    private HttpHeaders headers;
+
+    @Context
+    private UriInfo uriInfo;
+
+    @Context
+    private ClientConnection clientConnection;
+
+    private final AuthenticationManager authManager;
+    private final RealmModel realm;
+    private final EventBuilder event;
+
+    private ClientModel client;
+    private ClientSessionModel clientSession;
+
+    private Action action;
+
+    private String clientId;
+    private String redirectUri;
+    private String redirectUriParam;
+    private String responseType;
+    private String state;
+    private String scope;
+    private String loginHint;
+    private String prompt;
+    private String nonce;
+    private String idpHint;
+
+    private String legacyResponseType;
+
+    public AuthorizationEndpoint(AuthenticationManager authManager, RealmModel realm, EventBuilder event) {
+        this.authManager = authManager;
+        this.realm = realm;
+        this.event = event;
+        event.event(EventType.LOGIN);
+    }
+
+    @GET
+    public Response build() {
+        MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
+
+        clientId = params.getFirst(OIDCLoginProtocol.CLIENT_ID_PARAM);
+        responseType = params.getFirst(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
+        redirectUriParam = params.getFirst(OIDCLoginProtocol.REDIRECT_URI_PARAM);
+        state = params.getFirst(OIDCLoginProtocol.STATE_PARAM);
+        scope = params.getFirst(OIDCLoginProtocol.SCOPE_PARAM);
+        loginHint = params.getFirst(OIDCLoginProtocol.LOGIN_HINT_PARAM);
+        prompt = params.getFirst(OIDCLoginProtocol.PROMPT_PARAM);
+        idpHint = params.getFirst(AdapterConstants.KC_IDP_HINT);
+        nonce = params.getFirst(OIDCLoginProtocol.NONCE_PARAM);
+
+        checkSsl();
+        checkRealm();
+        checkClient();
+        checkResponseType();
+        checkRedirectUri();
+
+        createClientSession();
+
+        switch (action) {
+            case REGISTER:
+                return buildRegister();
+            case CODE:
+                return buildAuthorizationCodeAuthorizationResponse();
+        }
+
+        throw new RuntimeException("Unknown action " + action);
+    }
+
+    /**
+     * @deprecated
+     */
+    public AuthorizationEndpoint legacy(String legacyResponseType) {
+        logger.warnv("Invoking deprecated endpoint {0}", uriInfo.getRequestUri());
+        this.legacyResponseType = legacyResponseType;
+        return this;
+    }
+
+    public AuthorizationEndpoint register() {
+        event.event(EventType.REGISTER);
+        action = Action.REGISTER;
+
+        if (!realm.isRegistrationAllowed()) {
+            throw new ErrorPageException(session, Messages.REGISTRATION_NOT_ALLOWED);
+        }
+
+        return this;
+    }
+
+    private void checkSsl() {
+        if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
+            event.error(Errors.SSL_REQUIRED);
+            throw new ErrorPageException(session, Messages.HTTPS_REQUIRED);
+        }
+    }
+
+    private void checkRealm() {
+        if (!realm.isEnabled()) {
+            event.error(Errors.REALM_DISABLED);
+            throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
+        }
+    }
+
+    private void checkClient() {
+        if (clientId == null) {
+            event.error(Errors.INVALID_REQUEST);
+            throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
+        }
+
+        event.client(clientId);
+
+        client = realm.getClientByClientId(clientId);
+        if (client == null) {
+            event.error(Errors.CLIENT_NOT_FOUND);
+            throw new ErrorPageException(session, Messages.CLIENT_NOT_FOUND );
+        }
+
+        if (client.isBearerOnly()) {
+            event.error(Errors.NOT_ALLOWED);
+            throw new ErrorPageException(session, Messages.BEARER_ONLY );
+        }
+
+        if (client.isDirectGrantsOnly()) {
+            event.error(Errors.NOT_ALLOWED);
+            throw new ErrorPageException(session, Messages.DIRECT_GRANTS_ONLY);
+        }
+
+        session.getContext().setClient(client);
+    }
+
+    private void checkResponseType() {
+        if (responseType == null) {
+            if (legacyResponseType != null) {
+                responseType = legacyResponseType;
+            } else {
+                event.error(Errors.INVALID_REQUEST);
+                throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
+            }
+        }
+
+        event.detail(Details.RESPONSE_TYPE, responseType);
+
+        if (responseType.equals(OAuth2Constants.CODE)) {
+            if (action == null) {
+                action = Action.CODE;
+            }
+        } else {
+            event.error(Errors.INVALID_REQUEST);
+            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
+        }
+    }
+
+    private void checkRedirectUri() {
+        event.detail(Details.REDIRECT_URI, redirectUriParam);
+
+        redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUriParam, realm, client);
+        if (redirectUri == null) {
+            event.error(Errors.INVALID_REDIRECT_URI);
+            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
+        }
+    }
+
+    private void createClientSession() {
+        clientSession = session.sessions().createClientSession(realm, client);
+        clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        clientSession.setRedirectUri(redirectUri);
+        clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
+        clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, responseType);
+        clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUriParam);
+        clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+
+        if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
+        if (nonce != null) clientSession.setNote(OIDCLoginProtocol.NONCE_PARAM, nonce);
+        if (scope != null) clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
+        if (loginHint != null) clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
+        if (prompt != null) clientSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, prompt);
+        if (idpHint != null) clientSession.setNote(AdapterConstants.KC_IDP_HINT, idpHint);
+    }
+
+    private Response buildAuthorizationCodeAuthorizationResponse() {
+        String accessCode = new ClientSessionCode(realm, clientSession).getCode();
+
+        if (idpHint != null && !"".equals(idpHint)) {
+            IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
+
+            if (identityProviderModel == null) {
+                return session.getProvider(LoginFormsProvider.class)
+                        .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
+                        .createErrorPage();
+            }
+            return buildRedirectToIdentityProvider(idpHint, accessCode);
+        }
+
+        return browserAuthentication(accessCode);
+    }
+
+    protected Response browserAuthentication(String accessCode) {
+        this.event.event(EventType.LOGIN);
+        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
+        for (IdentityProviderModel identityProvider : identityProviders) {
+            if (identityProvider.isAuthenticateByDefault()) {
+                return buildRedirectToIdentityProvider(identityProvider.getAlias(), accessCode);
+            }
+        }
+        clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
+
+        AuthenticationFlowModel flow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
+        String flowId = flow.getId();
+        AuthenticationProcessor processor = new AuthenticationProcessor();
+        processor.setClientSession(clientSession)
+                .setFlowId(flowId)
+                .setConnection(clientConnection)
+                .setEventBuilder(event)
+                .setProtector(authManager.getProtector())
+                .setRealm(realm)
+                .setSession(session)
+                .setUriInfo(uriInfo)
+                .setRequest(request);
+
+        Response challenge = null;
+        try {
+            challenge = processor.authenticateOnly();
+        } catch (Exception e) {
+            return processor.handleBrowserException(e);
+        }
+
+        if (challenge != null && prompt != null && prompt.equals("none")) {
+            if (processor.isUserSessionCreated()) {
+                session.sessions().removeUserSession(realm, processor.getUserSession());
+            }
+            OIDCLoginProtocol oauth = new OIDCLoginProtocol(session, realm, uriInfo, headers, event);
+            return oauth.cancelLogin(clientSession);
+        }
+
+        if (challenge == null) {
+            return processor.finishAuthentication();
+        } else {
+            return challenge;
+        }
+    }
+
+    private Response buildRegister() {
+        authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
+
+        return session.getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode())
+                .createRegistration();
+    }
+
+    private Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
+        logger.debug("Automatically redirect to identity provider: " + providerId);
+        return Response.temporaryRedirect(
+                Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, this.realm.getName(), accessCode))
+                .build();
+    }
+
 }
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index 7900d90..f17cc27 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -1,145 +1,145 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Copyright 2013 Red Hat, Inc. and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.keycloak.protocol.oidc.endpoints;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.jboss.resteasy.spi.HttpResponse;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuthErrorException;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.resources.Cors;
-import org.keycloak.services.Urls;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriInfo;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author pedroigor
- */
-public class UserInfoEndpoint {
-
-    @Context
-    private HttpRequest request;
-
-    @Context
-    private HttpResponse response;
-
-    @Context
-    private UriInfo uriInfo;
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private ClientConnection clientConnection;
-
-    private final TokenManager tokenManager;
-    private final AppAuthManager appAuthManager;
-    private final RealmModel realm;
-
-    public UserInfoEndpoint(TokenManager tokenManager, RealmModel realm) {
-        this.realm = realm;
-        this.tokenManager = tokenManager;
-        this.appAuthManager = new AppAuthManager();
-    }
-
-    @Path("/")
-    @OPTIONS
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoPreflight() {
-        return Cors.add(this.request, Response.ok()).auth().preflight().build();
-    }
-
-    @Path("/")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoGet(@Context final HttpHeaders headers) {
-        String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
-        return issueUserInfo(accessToken);
-    }
-
-    @Path("/")
-    @POST
-    @NoCache
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
-        return issueUserInfo(accessToken);
-    }
-
-    private Response issueUserInfo(String tokenString) {
-        EventBuilder event = new EventBuilder(realm, session, clientConnection)
-                .event(EventType.USER_INFO_REQUEST)
-                .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
-
-        AccessToken token = null;
-        try {
-            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
-        } catch (Exception e) {
-            throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
-        }
-
-        UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
-        ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession());
-        ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
-        UserModel userModel = userSession.getUser();
-        AccessToken userInfo = new AccessToken();
-        tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
-
-        event
-            .detail(Details.USERNAME, userModel.getUsername())
-            .client(clientModel)
-            .session(userSession)
-            .user(userModel)
-            .success();
-
-        Map<String, Object> claims = new HashMap<String, Object>();
-        claims.putAll(userInfo.getOtherClaims());
-        claims.put("sub", userModel.getId());
-        return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(token).build();
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.protocol.oidc.endpoints;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.HttpResponse;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuthErrorException;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.resources.Cors;
+import org.keycloak.services.Urls;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author pedroigor
+ */
+public class UserInfoEndpoint {
+
+    @Context
+    private HttpRequest request;
+
+    @Context
+    private HttpResponse response;
+
+    @Context
+    private UriInfo uriInfo;
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private ClientConnection clientConnection;
+
+    private final TokenManager tokenManager;
+    private final AppAuthManager appAuthManager;
+    private final RealmModel realm;
+
+    public UserInfoEndpoint(TokenManager tokenManager, RealmModel realm) {
+        this.realm = realm;
+        this.tokenManager = tokenManager;
+        this.appAuthManager = new AppAuthManager();
+    }
+
+    @Path("/")
+    @OPTIONS
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoPreflight() {
+        return Cors.add(this.request, Response.ok()).auth().preflight().build();
+    }
+
+    @Path("/")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoGet(@Context final HttpHeaders headers) {
+        String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
+        return issueUserInfo(accessToken);
+    }
+
+    @Path("/")
+    @POST
+    @NoCache
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
+        return issueUserInfo(accessToken);
+    }
+
+    private Response issueUserInfo(String tokenString) {
+        EventBuilder event = new EventBuilder(realm, session, clientConnection)
+                .event(EventType.USER_INFO_REQUEST)
+                .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
+
+        AccessToken token = null;
+        try {
+            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+        } catch (Exception e) {
+            throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
+        }
+
+        UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
+        ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession());
+        ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
+        UserModel userModel = userSession.getUser();
+        AccessToken userInfo = new AccessToken();
+        tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
+
+        event
+            .detail(Details.USERNAME, userModel.getUsername())
+            .client(clientModel)
+            .session(userSession)
+            .user(userModel)
+            .success();
+
+        Map<String, Object> claims = new HashMap<String, Object>();
+        claims.putAll(userInfo.getOtherClaims());
+        claims.put("sub", userModel.getId());
+        return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(token).build();
+    }
+
+}
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 4675f3d..b890603 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
@@ -1,40 +1,40 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
-
-    public static final String TOKEN_MAPPER_CATEGORY = "Token mapper";
-
-    @Override
-    public String getProtocol() {
-        return OIDCLoginProtocol.LOGIN_PROTOCOL;
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public final ProtocolMapper create(KeycloakSession session) {
-        throw new RuntimeException("UNSUPPORTED METHOD");
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
+
+    public static final String TOKEN_MAPPER_CATEGORY = "Token mapper";
+
+    @Override
+    public String getProtocol() {
+        return OIDCLoginProtocol.LOGIN_PROTOCOL;
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public final ProtocolMapper create(KeycloakSession session) {
+        throw new RuntimeException("UNSUPPORTED METHOD");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+}
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 64fc4cd..0dab5c5 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
@@ -1,129 +1,129 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.AddressClaimSet;
-import org.keycloak.representations.IDToken;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Set the 'name' claim to be first + last name.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-
-    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);
-    }
-
-    public static final String PROVIDER_ID = "oidc-address-mapper";
-
-    public static ProtocolMapperModel createAddressMapper() {
-        Map<String, String> config;
-        ProtocolMapperModel address = new ProtocolMapperModel();
-        address.setName("address");
-        address.setProtocolMapper(PROVIDER_ID);
-        address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        address.setConsentRequired(true);
-        address.setConsentText("${address}");
-        config = new HashMap<String, String>();
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
-        address.setConfig(config);
-        return address;
-    }
-    public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) {
-        Map<String, String> config;
-        ProtocolMapperModel address = new ProtocolMapperModel();
-        address.setName("address");
-        address.setProtocolMapper(PROVIDER_ID);
-        address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        address.setConsentRequired(true);
-        address.setConsentText("${address}");
-        config = new HashMap<String, String>();
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken));
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken));
-        address.setConfig(config);
-        return address;
-    }
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Address";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Maps user address attributes (street, locality, region, postal_code, and country) to the OpenID Connect 'address' claim.";
-    }
-
-    @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) {
-        UserModel user = userSession.getUser();
-        AddressClaimSet addressSet = new AddressClaimSet();
-        addressSet.setStreetAddress(user.getFirstAttribute("street"));
-        addressSet.setLocality(user.getFirstAttribute("locality"));
-        addressSet.setRegion(user.getFirstAttribute("region"));
-        addressSet.setPostalCode(user.getFirstAttribute("postal_code"));
-        addressSet.setCountry(user.getFirstAttribute("country"));
-        token.getOtherClaims().put("address", addressSet);
-    }
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.AddressClaimSet;
+import org.keycloak.representations.IDToken;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Set the 'name' claim to be first + last name.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+
+    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);
+    }
+
+    public static final String PROVIDER_ID = "oidc-address-mapper";
+
+    public static ProtocolMapperModel createAddressMapper() {
+        Map<String, String> config;
+        ProtocolMapperModel address = new ProtocolMapperModel();
+        address.setName("address");
+        address.setProtocolMapper(PROVIDER_ID);
+        address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        address.setConsentRequired(true);
+        address.setConsentText("${address}");
+        config = new HashMap<String, String>();
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+        address.setConfig(config);
+        return address;
+    }
+    public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) {
+        Map<String, String> config;
+        ProtocolMapperModel address = new ProtocolMapperModel();
+        address.setName("address");
+        address.setProtocolMapper(PROVIDER_ID);
+        address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        address.setConsentRequired(true);
+        address.setConsentText("${address}");
+        config = new HashMap<String, String>();
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken));
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken));
+        address.setConfig(config);
+        return address;
+    }
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Address";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Maps user address attributes (street, locality, region, postal_code, and country) to the OpenID Connect 'address' claim.";
+    }
+
+    @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) {
+        UserModel user = userSession.getUser();
+        AddressClaimSet addressSet = new AddressClaimSet();
+        addressSet.setStreetAddress(user.getFirstAttribute("street"));
+        addressSet.setLocality(user.getFirstAttribute("locality"));
+        addressSet.setRegion(user.getFirstAttribute("region"));
+        addressSet.setPostalCode(user.getFirstAttribute("postal_code"));
+        addressSet.setCountry(user.getFirstAttribute("country"));
+        token.getOtherClaims().put("address", addressSet);
+    }
+
+}
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 caeeedf..dc7480e 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
@@ -1,113 +1,113 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.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.AccessToken;
-import org.keycloak.representations.IDToken;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Set the 'name' claim to be first + last name.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-
-    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);
-
-    }
-
-    public static final String PROVIDER_ID = "oidc-full-name-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User's full name";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        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) {
-        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) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(PROVIDER_ID);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(consentRequired);
-        mapper.setConsentText(consentText);
-        Map<String, String> config = new HashMap<String, String>();
-        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
-        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
-        mapper.setConfig(config);
-        return mapper;
-    }
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.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.AccessToken;
+import org.keycloak.representations.IDToken;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Set the 'name' claim to be first + last name.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+
+    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);
+
+    }
+
+    public static final String PROVIDER_ID = "oidc-full-name-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User's full name";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        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) {
+        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) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(PROVIDER_ID);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(consentRequired);
+        mapper.setConsentText(consentText);
+        Map<String, String> config = new HashMap<String, String>();
+        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+        mapper.setConfig(config);
+        return mapper;
+    }
+
+}
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 f0bebf6..e951312 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
@@ -1,146 +1,146 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.ProtocolMapperUtils;
-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;
-import java.util.List;
-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 {
-
-    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();
-        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);
-
-    }
-
-    public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Hardcoded claim";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        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,
-                                      boolean consentRequired, String consentText,
-                                      boolean accessToken, boolean idToken) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(PROVIDER_ID);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(consentRequired);
-        mapper.setConsentText(consentText);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, hardcodedName);
-        config.put(CLAIM_VALUE, hardcodedValue);
-        config.put(OIDCAttributeMapperHelper.JSON_TYPE, claimType);
-        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
-        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
-        mapper.setConfig(config);
-        return mapper;
-    }
-
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.ProtocolMapperUtils;
+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;
+import java.util.List;
+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 {
+
+    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();
+        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);
+
+    }
+
+    public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded claim";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        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,
+                                      boolean consentRequired, String consentText,
+                                      boolean accessToken, boolean idToken) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(PROVIDER_ID);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(consentRequired);
+        mapper.setConsentText(consentText);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, hardcodedName);
+        config.put(CLAIM_VALUE, hardcodedValue);
+        config.put(OIDCAttributeMapperHelper.JSON_TYPE, claimType);
+        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+        mapper.setConfig(config);
+        return mapper;
+    }
+
+
+}
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 66ef2db..c49eebb 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
@@ -1,100 +1,100 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Add a role to a token
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String ROLE_CONFIG = "role";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ROLE_CONFIG);
-        property.setLabel("Role");
-        property.setHelpText("Role you want added to the token.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To specify an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.ROLE_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "oidc-hardcoded-role-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Hardcoded Role";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Hardcode a role into the access token.";
-    }
-
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        String role = mappingModel.getConfig().get(ROLE_CONFIG);
-        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
-        String appName = scopedRole[0];
-        String roleName = scopedRole[1];
-        if (appName != null) {
-            token.addAccess(appName).addRole(roleName);
-        } else {
-            AccessToken.Access access = token.getRealmAccess();
-            if (access == null) {
-                access = new AccessToken.Access();
-                token.setRealmAccess(access);
-            }
-            access.addRole(role);
-        }
-        return token;
-    }
-
-    public static ProtocolMapperModel create(String name,
-                                             String role) {
-        String mapperId = PROVIDER_ID;
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(ROLE_CONFIG, role);
-        mapper.setConfig(config);
-        return mapper;
-
-    }
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.AccessToken;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Add a role to a token
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String ROLE_CONFIG = "role";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ROLE_CONFIG);
+        property.setLabel("Role");
+        property.setHelpText("Role you want added to the token.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To specify an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.ROLE_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "oidc-hardcoded-role-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded Role";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Hardcode a role into the access token.";
+    }
+
+    @Override
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        String role = mappingModel.getConfig().get(ROLE_CONFIG);
+        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
+        String appName = scopedRole[0];
+        String roleName = scopedRole[1];
+        if (appName != null) {
+            token.addAccess(appName).addRole(roleName);
+        } else {
+            AccessToken.Access access = token.getRealmAccess();
+            if (access == null) {
+                access = new AccessToken.Access();
+                token.setRealmAccess(access);
+            }
+            access.addRole(role);
+        }
+        return token;
+    }
+
+    public static ProtocolMapperModel create(String name,
+                                             String role) {
+        String mapperId = PROVIDER_ID;
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(ROLE_CONFIG, role);
+        mapper.setConfig(config);
+        return mapper;
+
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
index eebda6f..cf83def 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
@@ -1,17 +1,17 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.representations.AccessToken;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface OIDCAccessTokenMapper {
-
-    AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                     UserSessionModel userSession, ClientSessionModel clientSession);
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface OIDCAccessTokenMapper {
+
+    AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                     UserSessionModel userSession, ClientSessionModel clientSession);
+}
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 92e66e9..ed83068 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
@@ -1,171 +1,171 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.jboss.logging.Logger;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.ProtocolMapperUtils;
-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;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OIDCAttributeMapperHelper {
-    private static final Logger logger = Logger.getLogger(OIDCAttributeMapperHelper.class);
-
-    public static final String TOKEN_CLAIM_NAME = "claim.name";
-    public static final String TOKEN_CLAIM_NAME_LABEL = "Token Claim Name";
-    public static final String JSON_TYPE = "Claim JSON Type";
-    public static final String INCLUDE_IN_ACCESS_TOKEN = "access.token.claim";
-    public static final String INCLUDE_IN_ACCESS_TOKEN_LABEL = "Add to access token";
-    public static final String INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT = "Should the claim be added to the access token?";
-    public static final String INCLUDE_IN_ID_TOKEN = "id.token.claim";
-    public static final String INCLUDE_IN_ID_TOKEN_LABEL = "Add to ID token";
-    public static final String INCLUDE_IN_ID_TOKEN_HELP_TEXT = "Should the claim be added to the ID token?";
-
-    public static Object mapAttributeValue(ProtocolMapperModel mappingModel, Object attributeValue) {
-        if (attributeValue == null) return null;
-
-        if (attributeValue instanceof List) {
-            List<Object> valueAsList = (List<Object>) attributeValue;
-            if (valueAsList.size() == 0) return null;
-
-            if (isMultivalued(mappingModel)) {
-                List<Object> result = new ArrayList<>();
-                for (Object valueItem : valueAsList) {
-                    result.add(mapAttributeValue(mappingModel, valueItem));
-                }
-                return result;
-            } else {
-                if (valueAsList.size() > 1) {
-                    logger.warnf("Multiple values found '%s' for protocol mapper '%s' but expected just single value", attributeValue.toString(), mappingModel.getName());
-                }
-
-                attributeValue = valueAsList.get(0);
-            }
-        }
-
-        String type = mappingModel.getConfig().get(JSON_TYPE);
-        if (type == null) return attributeValue;
-        if (type.equals("boolean")) {
-            if (attributeValue instanceof Boolean) return attributeValue;
-            if (attributeValue instanceof String) return Boolean.valueOf((String)attributeValue);
-            throw new RuntimeException("cannot map type for token claim");
-        } else if (type.equals("String")) {
-            if (attributeValue instanceof String) return attributeValue;
-            return attributeValue.toString();
-        } else if (type.equals("long")) {
-            if (attributeValue instanceof Long) return attributeValue;
-            if (attributeValue instanceof String) return Long.valueOf((String)attributeValue);
-            throw new RuntimeException("cannot map type for token claim");
-        } else if (type.equals("int")) {
-            if (attributeValue instanceof Integer) return attributeValue;
-            if (attributeValue instanceof String) return Integer.valueOf((String)attributeValue);
-            throw new RuntimeException("cannot map type for token claim");
-        }
-        return attributeValue;
-    }
-
-    public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
-        attributeValue = mapAttributeValue(mappingModel, attributeValue);
-        if (attributeValue == null) return;
-
-        String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME);
-        String[] split = protocolClaim.split("\\.");
-        Map<String, Object> jsonObject = token.getOtherClaims();
-        for (int i = 0; i < split.length; i++) {
-            if (i == split.length - 1) {
-                jsonObject.put(split[i], attributeValue);
-            } else {
-                Map<String, Object> nested = (Map<String, Object>)jsonObject.get(split[i]);
-
-                if (nested == null) {
-                    nested = new HashMap<String, Object>();
-                    jsonObject.put(split[i], nested);
-                }
-
-                jsonObject = nested;
-            }
-        }
-    }
-
-    public static ProtocolMapperModel createClaimMapper(String name,
-                                  String userAttribute,
-                                  String tokenClaimName, String claimType,
-                                  boolean consentRequired, String consentText,
-                                  boolean accessToken, boolean idToken,
-                                  String mapperId) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(consentRequired);
-        mapper.setConsentText(consentText);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
-        config.put(TOKEN_CLAIM_NAME, tokenClaimName);
-        config.put(JSON_TYPE, claimType);
-        if (accessToken) config.put(INCLUDE_IN_ACCESS_TOKEN, "true");
-        if (idToken) config.put(INCLUDE_IN_ID_TOKEN, "true");
-        mapper.setConfig(config);
-        return mapper;
-    }
-
-    public static boolean includeInIDToken(ProtocolMapperModel mappingModel) {
-        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ID_TOKEN));
-    }
-
-    public static boolean includeInAccessToken(ProtocolMapperModel mappingModel) {
-        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
-    }
-
-
-    public static boolean isMultivalued(ProtocolMapperModel mappingModel) {
-        return "true".equals(mappingModel.getConfig().get(ProtocolMapperUtils.MULTIVALUED));
-    }
-
-    public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(TOKEN_CLAIM_NAME);
-        property.setLabel(TOKEN_CLAIM_NAME_LABEL);
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText("Name of the claim to insert into the token.  This can be a fully qualified name like 'address.street'.  In this case, a nested json object will be created.");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(JSON_TYPE);
-        property.setLabel(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 to populate the json claim in the token.  long, int, boolean, and String are valid values.");
-        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);
-    }
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.jboss.logging.Logger;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.ProtocolMapperUtils;
+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;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCAttributeMapperHelper {
+    private static final Logger logger = Logger.getLogger(OIDCAttributeMapperHelper.class);
+
+    public static final String TOKEN_CLAIM_NAME = "claim.name";
+    public static final String TOKEN_CLAIM_NAME_LABEL = "Token Claim Name";
+    public static final String JSON_TYPE = "Claim JSON Type";
+    public static final String INCLUDE_IN_ACCESS_TOKEN = "access.token.claim";
+    public static final String INCLUDE_IN_ACCESS_TOKEN_LABEL = "Add to access token";
+    public static final String INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT = "Should the claim be added to the access token?";
+    public static final String INCLUDE_IN_ID_TOKEN = "id.token.claim";
+    public static final String INCLUDE_IN_ID_TOKEN_LABEL = "Add to ID token";
+    public static final String INCLUDE_IN_ID_TOKEN_HELP_TEXT = "Should the claim be added to the ID token?";
+
+    public static Object mapAttributeValue(ProtocolMapperModel mappingModel, Object attributeValue) {
+        if (attributeValue == null) return null;
+
+        if (attributeValue instanceof List) {
+            List<Object> valueAsList = (List<Object>) attributeValue;
+            if (valueAsList.size() == 0) return null;
+
+            if (isMultivalued(mappingModel)) {
+                List<Object> result = new ArrayList<>();
+                for (Object valueItem : valueAsList) {
+                    result.add(mapAttributeValue(mappingModel, valueItem));
+                }
+                return result;
+            } else {
+                if (valueAsList.size() > 1) {
+                    logger.warnf("Multiple values found '%s' for protocol mapper '%s' but expected just single value", attributeValue.toString(), mappingModel.getName());
+                }
+
+                attributeValue = valueAsList.get(0);
+            }
+        }
+
+        String type = mappingModel.getConfig().get(JSON_TYPE);
+        if (type == null) return attributeValue;
+        if (type.equals("boolean")) {
+            if (attributeValue instanceof Boolean) return attributeValue;
+            if (attributeValue instanceof String) return Boolean.valueOf((String)attributeValue);
+            throw new RuntimeException("cannot map type for token claim");
+        } else if (type.equals("String")) {
+            if (attributeValue instanceof String) return attributeValue;
+            return attributeValue.toString();
+        } else if (type.equals("long")) {
+            if (attributeValue instanceof Long) return attributeValue;
+            if (attributeValue instanceof String) return Long.valueOf((String)attributeValue);
+            throw new RuntimeException("cannot map type for token claim");
+        } else if (type.equals("int")) {
+            if (attributeValue instanceof Integer) return attributeValue;
+            if (attributeValue instanceof String) return Integer.valueOf((String)attributeValue);
+            throw new RuntimeException("cannot map type for token claim");
+        }
+        return attributeValue;
+    }
+
+    public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
+        attributeValue = mapAttributeValue(mappingModel, attributeValue);
+        if (attributeValue == null) return;
+
+        String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME);
+        String[] split = protocolClaim.split("\\.");
+        Map<String, Object> jsonObject = token.getOtherClaims();
+        for (int i = 0; i < split.length; i++) {
+            if (i == split.length - 1) {
+                jsonObject.put(split[i], attributeValue);
+            } else {
+                Map<String, Object> nested = (Map<String, Object>)jsonObject.get(split[i]);
+
+                if (nested == null) {
+                    nested = new HashMap<String, Object>();
+                    jsonObject.put(split[i], nested);
+                }
+
+                jsonObject = nested;
+            }
+        }
+    }
+
+    public static ProtocolMapperModel createClaimMapper(String name,
+                                  String userAttribute,
+                                  String tokenClaimName, String claimType,
+                                  boolean consentRequired, String consentText,
+                                  boolean accessToken, boolean idToken,
+                                  String mapperId) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(consentRequired);
+        mapper.setConsentText(consentText);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
+        config.put(TOKEN_CLAIM_NAME, tokenClaimName);
+        config.put(JSON_TYPE, claimType);
+        if (accessToken) config.put(INCLUDE_IN_ACCESS_TOKEN, "true");
+        if (idToken) config.put(INCLUDE_IN_ID_TOKEN, "true");
+        mapper.setConfig(config);
+        return mapper;
+    }
+
+    public static boolean includeInIDToken(ProtocolMapperModel mappingModel) {
+        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ID_TOKEN));
+    }
+
+    public static boolean includeInAccessToken(ProtocolMapperModel mappingModel) {
+        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
+    }
+
+
+    public static boolean isMultivalued(ProtocolMapperModel mappingModel) {
+        return "true".equals(mappingModel.getConfig().get(ProtocolMapperUtils.MULTIVALUED));
+    }
+
+    public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(TOKEN_CLAIM_NAME);
+        property.setLabel(TOKEN_CLAIM_NAME_LABEL);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setHelpText("Name of the claim to insert into the token.  This can be a fully qualified name like 'address.street'.  In this case, a nested json object will be created.");
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(JSON_TYPE);
+        property.setLabel(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 to populate the json claim in the token.  long, int, boolean, and String are valid values.");
+        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);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
index 932b431..858cfec 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
@@ -1,18 +1,18 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface OIDCIDTokenMapper {
-
-    IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                               UserSessionModel userSession, ClientSessionModel clientSession);
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface OIDCIDTokenMapper {
+
+    IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                               UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index ac79736..c4618ea 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
@@ -1,128 +1,128 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.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.AccessToken;
-import org.keycloak.representations.IDToken;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Map an assigned role to a different position and name in the token
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    public static final String ROLE_CONFIG = "role";
-    public static String NEW_ROLE_NAME = "new.role.name";
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ROLE_CONFIG);
-        property.setLabel("Role");
-        property.setHelpText("Role name you want changed.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(NEW_ROLE_NAME);
-        property.setLabel("New Role Name");
-        property.setHelpText("The new role name.  The new name format corresponds to where in the access token the role will be mapped to.  So, a new name of 'myapp.newname' will map the role to that position in the access token.  A new name of 'newname' will map the role to the realm roles in the token.");
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-    }
-
-    public static final String PROVIDER_ID = "oidc-role-name-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "Role Name Mapper";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Map an assigned role to a new name or position in the token.";
-    }
-
-    @Override
-    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);
-
-        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
-        String[] newScopedRole = ProtocolMapperUtils.parseRole(newName);
-        String appName = scopedRole[0];
-        String roleName = scopedRole[1];
-        if (appName != null) {
-            AccessToken.Access access = token.getResourceAccess(appName);
-            if (access == null) return token;
-            if (!access.getRoles().contains(roleName)) return token;
-            access.getRoles().remove(roleName);
-        } else {
-            AccessToken.Access access = token.getRealmAccess();
-            if (access == null) return token;
-            access.getRoles().remove(roleName);
-        }
-
-        String newAppName = newScopedRole[0];
-        String newRoleName = newScopedRole[1];
-        AccessToken.Access access = null;
-        if (newAppName == null) {
-            access = token.getRealmAccess();
-            if (access == null) {
-                access = new AccessToken.Access();
-                token.setRealmAccess(access);
-            }
-        } else {
-            access = token.addAccess(newAppName);
-        }
-        access.addRole(newRoleName);
-        return token;
-    }
-
-    public static ProtocolMapperModel create(String name,
-                                             String role,
-                                             String newName) {
-        String mapperId = PROVIDER_ID;
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(mapperId);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(ROLE_CONFIG, role);
-        config.put(NEW_ROLE_NAME, newName);
-        mapper.setConfig(config);
-        return mapper;
-
-    }
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.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.AccessToken;
+import org.keycloak.representations.IDToken;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Map an assigned role to a different position and name in the token
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    public static final String ROLE_CONFIG = "role";
+    public static String NEW_ROLE_NAME = "new.role.name";
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ROLE_CONFIG);
+        property.setLabel("Role");
+        property.setHelpText("Role name you want changed.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        property = new ProviderConfigProperty();
+        property.setName(NEW_ROLE_NAME);
+        property.setLabel("New Role Name");
+        property.setHelpText("The new role name.  The new name format corresponds to where in the access token the role will be mapped to.  So, a new name of 'myapp.newname' will map the role to that position in the access token.  A new name of 'newname' will map the role to the realm roles in the token.");
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+    }
+
+    public static final String PROVIDER_ID = "oidc-role-name-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Role Name Mapper";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Map an assigned role to a new name or position in the token.";
+    }
+
+    @Override
+    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);
+
+        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
+        String[] newScopedRole = ProtocolMapperUtils.parseRole(newName);
+        String appName = scopedRole[0];
+        String roleName = scopedRole[1];
+        if (appName != null) {
+            AccessToken.Access access = token.getResourceAccess(appName);
+            if (access == null) return token;
+            if (!access.getRoles().contains(roleName)) return token;
+            access.getRoles().remove(roleName);
+        } else {
+            AccessToken.Access access = token.getRealmAccess();
+            if (access == null) return token;
+            access.getRoles().remove(roleName);
+        }
+
+        String newAppName = newScopedRole[0];
+        String newRoleName = newScopedRole[1];
+        AccessToken.Access access = null;
+        if (newAppName == null) {
+            access = token.getRealmAccess();
+            if (access == null) {
+                access = new AccessToken.Access();
+                token.setRealmAccess(access);
+            }
+        } else {
+            access = token.addAccess(newAppName);
+        }
+        access.addRole(newRoleName);
+        return token;
+    }
+
+    public static ProtocolMapperModel create(String name,
+                                             String role,
+                                             String newName) {
+        String mapperId = PROVIDER_ID;
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(mapperId);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(ROLE_CONFIG, role);
+        config.put(NEW_ROLE_NAME, newName);
+        mapper.setConfig(config);
+        return mapper;
+
+    }
+
+}
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 b4c9c76..246b82e 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
@@ -1,118 +1,118 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.jboss.logging.Logger;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Mappings UserModel.attribute to an ID Token claim.  Token claim name can be a full qualified nested object name,
- * i.e. "address.country".  This will create a nested
- * json object within the toke claim.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
-        property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
-        property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
-
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.MULTIVALUED);
-        property.setLabel(ProtocolMapperUtils.MULTIVALUED_LABEL);
-        property.setHelpText(ProtocolMapperUtils.MULTIVALUED_HELP_TEXT);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        configProperties.add(property);
-
-    }
-
-    public static final String PROVIDER_ID = "oidc-usermodel-attribute-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Attribute";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        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 = user.getAttribute(attributeName);
-        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 createClaimMapper(String name,
-                                      String userAttribute,
-                                      String tokenClaimName, String claimType,
-                                      boolean consentRequired, String consentText,
-                                      boolean accessToken, boolean idToken, boolean multivalued) {
-        ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, userAttribute,
-                tokenClaimName, claimType,
-                consentRequired, consentText,
-                accessToken, idToken,
-                PROVIDER_ID);
-
-        if (multivalued) {
-            mapper.getConfig().put(ProtocolMapperUtils.MULTIVALUED, "true");
-        }
-        
-        return mapper;
-    }
-
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.jboss.logging.Logger;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserModel.attribute to an ID Token claim.  Token claim name can be a full qualified nested object name,
+ * i.e. "address.country".  This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
+        property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
+        property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.MULTIVALUED);
+        property.setLabel(ProtocolMapperUtils.MULTIVALUED_LABEL);
+        property.setHelpText(ProtocolMapperUtils.MULTIVALUED_HELP_TEXT);
+        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
+        configProperties.add(property);
+
+    }
+
+    public static final String PROVIDER_ID = "oidc-usermodel-attribute-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Attribute";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        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 = user.getAttribute(attributeName);
+        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 createClaimMapper(String name,
+                                      String userAttribute,
+                                      String tokenClaimName, String claimType,
+                                      boolean consentRequired, String consentText,
+                                      boolean accessToken, boolean idToken, boolean multivalued) {
+        ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, userAttribute,
+                tokenClaimName, claimType,
+                consentRequired, consentText,
+                accessToken, idToken,
+                PROVIDER_ID);
+
+        if (multivalued) {
+            mapper.getConfig().put(ProtocolMapperUtils.MULTIVALUED, "true");
+        }
+        
+        return mapper;
+    }
+
+
+}
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 8b5eb2f..153715a 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
@@ -1,102 +1,102 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.ProtocolMapperUtils;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Mappings UserModel property (the property name of a getter method) to an ID Token claim.  Token claim name can be a full qualified nested object name,
- * i.e. "address.country".  This will create a nested
- * json object within the toke claim.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
-        property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
-        configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
-    }
-
-    public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Property";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        return "Map a built in user property 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);
-        OIDCAttributeMapperHelper.mapClaim(token, mappingModel, propertyValue);
-    }
-
-    public static ProtocolMapperModel createClaimMapper(String name,
-                                      String userAttribute,
-                                      String tokenClaimName, String claimType,
-                                      boolean consentRequired, String consentText,
-                                      boolean accessToken, boolean idToken) {
-        return OIDCAttributeMapperHelper.createClaimMapper(name, userAttribute,
-                tokenClaimName, claimType,
-                consentRequired, consentText,
-                accessToken, idToken,
-                PROVIDER_ID);
-    }
-
-
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mappings UserModel property (the property name of a getter method) to an ID Token claim.  Token claim name can be a full qualified nested object name,
+ * i.e. "address.country".  This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
+        property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
+        configProperties.add(property);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+    }
+
+    public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Property";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        return "Map a built in user property 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);
+        OIDCAttributeMapperHelper.mapClaim(token, mappingModel, propertyValue);
+    }
+
+    public static ProtocolMapperModel createClaimMapper(String name,
+                                      String userAttribute,
+                                      String tokenClaimName, String claimType,
+                                      boolean consentRequired, String consentText,
+                                      boolean accessToken, boolean idToken) {
+        return OIDCAttributeMapperHelper.createClaimMapper(name, userAttribute,
+                tokenClaimName, claimType,
+                consentRequired, consentText,
+                accessToken, idToken,
+                PROVIDER_ID);
+    }
+
+
+}
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 2023525..d52a9a0 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
@@ -1,108 +1,108 @@
-package org.keycloak.protocol.oidc.mappers;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-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.AccessToken;
-import org.keycloak.representations.IDToken;
-
-/**
- * Mappings UserSessionModel.note to an ID Token claim.
- *
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-
-    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
-
-    static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(ProtocolMapperUtils.USER_SESSION_NOTE);
-        property.setLabel(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_LABEL);
-        property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
-    }
-
-    public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";
-
-
-    public List<ProviderConfigProperty> getConfigProperties() {
-        return configProperties;
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_ID;
-    }
-
-    @Override
-    public String getDisplayType() {
-        return "User Session Note";
-    }
-
-    @Override
-    public String getDisplayCategory() {
-        return TOKEN_MAPPER_CATEGORY;
-    }
-
-    @Override
-    public String getHelpText() {
-        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,
-                                                        boolean consentRequired, String consentText,
-                                                        boolean accessToken, boolean idToken) {
-        ProtocolMapperModel mapper = new ProtocolMapperModel();
-        mapper.setName(name);
-        mapper.setProtocolMapper(PROVIDER_ID);
-        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        mapper.setConsentRequired(consentRequired);
-        mapper.setConsentText(consentText);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(ProtocolMapperUtils.USER_SESSION_NOTE, userSessionNote);
-        config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, tokenClaimName);
-        config.put(OIDCAttributeMapperHelper.JSON_TYPE, jsonType);
-        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
-        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
-        mapper.setConfig(config);
-        return mapper;
-    }
-}
+package org.keycloak.protocol.oidc.mappers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+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.AccessToken;
+import org.keycloak.representations.IDToken;
+
+/**
+ * Mappings UserSessionModel.note to an ID Token claim.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+
+    private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty property;
+        property = new ProviderConfigProperty();
+        property.setName(ProtocolMapperUtils.USER_SESSION_NOTE);
+        property.setLabel(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_LABEL);
+        property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
+        property.setType(ProviderConfigProperty.STRING_TYPE);
+        configProperties.add(property);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+    }
+
+    public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";
+
+
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "User Session Note";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return TOKEN_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getHelpText() {
+        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,
+                                                        boolean consentRequired, String consentText,
+                                                        boolean accessToken, boolean idToken) {
+        ProtocolMapperModel mapper = new ProtocolMapperModel();
+        mapper.setName(name);
+        mapper.setProtocolMapper(PROVIDER_ID);
+        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        mapper.setConsentRequired(consentRequired);
+        mapper.setConsentText(consentText);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(ProtocolMapperUtils.USER_SESSION_NOTE, userSessionNote);
+        config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, tokenClaimName);
+        config.put(OIDCAttributeMapperHelper.JSON_TYPE, jsonType);
+        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+        mapper.setConfig(config);
+        return mapper;
+    }
+}
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 ded0fbb..8748079 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -1,203 +1,203 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.protocol.oidc;
-
-import org.jboss.logging.Logger;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.managers.ResourceAdminManager;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class OIDCLoginProtocol implements LoginProtocol {
-
-    public static final String LOGIN_PROTOCOL = "openid-connect";
-    public static final String STATE_PARAM = "state";
-    public static final String LOGOUT_STATE_PARAM = "OIDC_LOGOUT_STATE_PARAM";
-    public static final String SCOPE_PARAM = "scope";
-    public static final String CODE_PARAM = "code";
-    public static final String RESPONSE_TYPE_PARAM = "response_type";
-    public static final String GRANT_TYPE_PARAM = "grant_type";
-    public static final String REDIRECT_URI_PARAM = "redirect_uri";
-    public static final String CLIENT_ID_PARAM = "client_id";
-    public static final String NONCE_PARAM = "nonce";
-    public static final String PROMPT_PARAM = "prompt";
-    public static final String LOGIN_HINT_PARAM = "login_hint";
-    public static final String LOGOUT_REDIRECT_URI = "OIDC_LOGOUT_REDIRECT_URI";
-    public static final String ISSUER = "iss";
-
-    private static final Logger log = Logger.getLogger(OIDCLoginProtocol.class);
-
-    protected KeycloakSession session;
-
-    protected RealmModel realm;
-
-    protected UriInfo uriInfo;
-
-    protected HttpHeaders headers;
-
-    protected EventBuilder event;
-
-    public OIDCLoginProtocol(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, EventBuilder event) {
-        this.session = session;
-        this.realm = realm;
-        this.uriInfo = uriInfo;
-        this.headers = headers;
-        this.event = event;
-    }
-
-    public OIDCLoginProtocol(){
-
-    }
-
-    @Override
-    public OIDCLoginProtocol setSession(KeycloakSession session) {
-        this.session = session;
-        return this;
-    }
-
-    @Override
-    public OIDCLoginProtocol setRealm(RealmModel realm) {
-        this.realm = realm;
-        return this;
-    }
-
-    @Override
-    public OIDCLoginProtocol setUriInfo(UriInfo uriInfo) {
-        this.uriInfo = uriInfo;
-        return this;
-    }
-
-    @Override
-    public OIDCLoginProtocol setHttpHeaders(HttpHeaders headers){
-        this.headers = headers;
-        return this;
-    }
-
-    @Override
-    public OIDCLoginProtocol setEventBuilder(EventBuilder event) {
-        this.event = event;
-        return this;
-    }
-
-    @Override
-    public Response cancelLogin(ClientSessionModel clientSession) {
-        String redirect = clientSession.getRedirectUri();
-        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
-        if (state != null) {
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        }
-        session.sessions().removeClientSession(realm, clientSession);
-        return Response.status(302).location(redirectUri.build()).build();
-    }
-
-    @Override
-    public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
-        ClientSessionModel clientSession = accessCode.getClientSession();
-        String redirect = clientSession.getRedirectUri();
-        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
-        accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.CODE, accessCode.getCode());
-        log.debugv("redirectAccessCode: state: {0}", state);
-        if (state != null)
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
-
-        return location.build();
-    }
-
-    public Response consentDenied(ClientSessionModel clientSession) {
-        String redirect = clientSession.getRedirectUri();
-        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
-        if (state != null)
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
-        return location.build();
-    }
-
-
-    public Response invalidSessionError(ClientSessionModel clientSession) {
-        String redirect = clientSession.getRedirectUri();
-        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
-        if (state != null) {
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        }
-        return Response.status(302).location(redirectUri.build()).build();
-    }
-
-    @Override
-    public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!(clientSession.getClient() instanceof ClientModel)) return;
-        ClientModel app = clientSession.getClient();
-        new ResourceAdminManager(session).logoutClientSession(uriInfo.getRequestUri(), realm, app, clientSession);
-    }
-
-    @Override
-    public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
-        // todo oidc redirect support
-        throw new RuntimeException("NOT IMPLEMENTED");
-    }
-
-    @Override
-    public Response finishLogout(UserSessionModel userSession) {
-        String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI);
-        String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM);
-        event.event(EventType.LOGOUT);
-        if (redirectUri != null) {
-            event.detail(Details.REDIRECT_URI, redirectUri);
-        }
-        event.user(userSession.getUser()).session(userSession).success();
-
-
-        if (redirectUri != null) {
-            UriBuilder uriBuilder = UriBuilder.fromUri(redirectUri);
-            if (state != null) uriBuilder.queryParam(STATE_PARAM, state);
-            return Response.status(302).location(uriBuilder.build()).build();
-        } else {
-            return Response.ok().build();
-        }
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.protocol.oidc;
+
+import org.jboss.logging.Logger;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.managers.ResourceAdminManager;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class OIDCLoginProtocol implements LoginProtocol {
+
+    public static final String LOGIN_PROTOCOL = "openid-connect";
+    public static final String STATE_PARAM = "state";
+    public static final String LOGOUT_STATE_PARAM = "OIDC_LOGOUT_STATE_PARAM";
+    public static final String SCOPE_PARAM = "scope";
+    public static final String CODE_PARAM = "code";
+    public static final String RESPONSE_TYPE_PARAM = "response_type";
+    public static final String GRANT_TYPE_PARAM = "grant_type";
+    public static final String REDIRECT_URI_PARAM = "redirect_uri";
+    public static final String CLIENT_ID_PARAM = "client_id";
+    public static final String NONCE_PARAM = "nonce";
+    public static final String PROMPT_PARAM = "prompt";
+    public static final String LOGIN_HINT_PARAM = "login_hint";
+    public static final String LOGOUT_REDIRECT_URI = "OIDC_LOGOUT_REDIRECT_URI";
+    public static final String ISSUER = "iss";
+
+    private static final Logger log = Logger.getLogger(OIDCLoginProtocol.class);
+
+    protected KeycloakSession session;
+
+    protected RealmModel realm;
+
+    protected UriInfo uriInfo;
+
+    protected HttpHeaders headers;
+
+    protected EventBuilder event;
+
+    public OIDCLoginProtocol(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, EventBuilder event) {
+        this.session = session;
+        this.realm = realm;
+        this.uriInfo = uriInfo;
+        this.headers = headers;
+        this.event = event;
+    }
+
+    public OIDCLoginProtocol(){
+
+    }
+
+    @Override
+    public OIDCLoginProtocol setSession(KeycloakSession session) {
+        this.session = session;
+        return this;
+    }
+
+    @Override
+    public OIDCLoginProtocol setRealm(RealmModel realm) {
+        this.realm = realm;
+        return this;
+    }
+
+    @Override
+    public OIDCLoginProtocol setUriInfo(UriInfo uriInfo) {
+        this.uriInfo = uriInfo;
+        return this;
+    }
+
+    @Override
+    public OIDCLoginProtocol setHttpHeaders(HttpHeaders headers){
+        this.headers = headers;
+        return this;
+    }
+
+    @Override
+    public OIDCLoginProtocol setEventBuilder(EventBuilder event) {
+        this.event = event;
+        return this;
+    }
+
+    @Override
+    public Response cancelLogin(ClientSessionModel clientSession) {
+        String redirect = clientSession.getRedirectUri();
+        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
+        if (state != null) {
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        }
+        session.sessions().removeClientSession(realm, clientSession);
+        return Response.status(302).location(redirectUri.build()).build();
+    }
+
+    @Override
+    public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
+        ClientSessionModel clientSession = accessCode.getClientSession();
+        String redirect = clientSession.getRedirectUri();
+        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
+        accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.CODE, accessCode.getCode());
+        log.debugv("redirectAccessCode: state: {0}", state);
+        if (state != null)
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
+
+        return location.build();
+    }
+
+    public Response consentDenied(ClientSessionModel clientSession) {
+        String redirect = clientSession.getRedirectUri();
+        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
+        if (state != null)
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
+        return location.build();
+    }
+
+
+    public Response invalidSessionError(ClientSessionModel clientSession) {
+        String redirect = clientSession.getRedirectUri();
+        String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, "access_denied");
+        if (state != null) {
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        }
+        return Response.status(302).location(redirectUri.build()).build();
+    }
+
+    @Override
+    public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!(clientSession.getClient() instanceof ClientModel)) return;
+        ClientModel app = clientSession.getClient();
+        new ResourceAdminManager(session).logoutClientSession(uriInfo.getRequestUri(), realm, app, clientSession);
+    }
+
+    @Override
+    public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+        // todo oidc redirect support
+        throw new RuntimeException("NOT IMPLEMENTED");
+    }
+
+    @Override
+    public Response finishLogout(UserSessionModel userSession) {
+        String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI);
+        String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM);
+        event.event(EventType.LOGOUT);
+        if (redirectUri != null) {
+            event.detail(Details.REDIRECT_URI, redirectUri);
+        }
+        event.user(userSession.getUser()).session(userSession).success();
+
+
+        if (redirectUri != null) {
+            UriBuilder uriBuilder = UriBuilder.fromUri(redirectUri);
+            if (state != null) uriBuilder.queryParam(STATE_PARAM, state);
+            return Response.status(302).location(uriBuilder.build()).build();
+        } else {
+            return Response.ok().build();
+        }
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
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 0c81a3b..8f62a52 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -1,137 +1,137 @@
-package org.keycloak.protocol.oidc;
-
-import org.keycloak.constants.KerberosConstants;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.AbstractLoginProtocolFactory;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.oidc.mappers.AddressMapper;
-import org.keycloak.protocol.oidc.mappers.FullNameMapper;
-import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
-import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
-import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
-import org.keycloak.services.managers.AuthenticationManager;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
-
-    public static final String USERNAME = "username";
-    public static final String EMAIL = "email";
-    public static final String EMAIL_VERIFIED = "email verified";
-    public static final String GIVEN_NAME = "given name";
-    public static final String FAMILY_NAME = "family name";
-    public static final String FULL_NAME = "full name";
-    public static final String USERNAME_CONSENT_TEXT = "${username}";
-    public static final String EMAIL_CONSENT_TEXT = "${email}";
-    public static final String EMAIL_VERIFIED_CONSENT_TEXT = "${emailVerified}";
-    public static final String GIVEN_NAME_CONSENT_TEXT = "${givenName}";
-    public static final String FAMILY_NAME_CONSENT_TEXT = "${familyName}";
-    public static final String FULL_NAME_CONSENT_TEXT = "${fullName}";
-
-
-    @Override
-    public LoginProtocol create(KeycloakSession session) {
-        return new OIDCLoginProtocol().setSession(session);
-    }
-
-    @Override
-    public List<ProtocolMapperModel> getBuiltinMappers() {
-        return builtins;
-    }
-
-    @Override
-    public List<ProtocolMapperModel> getDefaultBuiltinMappers() {
-        return defaultBuiltins;
-    }
-
-    static List<ProtocolMapperModel> builtins = new ArrayList<>();
-    static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
-
-    static {
-
-        ProtocolMapperModel model;
-        model = UserPropertyMapper.createClaimMapper(USERNAME,
-                "username",
-                "preferred_username", "String",
-                true, USERNAME_CONSENT_TEXT,
-                true, true);
-        builtins.add(model);
-        defaultBuiltins.add(model);
-        model = UserPropertyMapper.createClaimMapper(EMAIL,
-                "email",
-                "email", "String",
-                true, EMAIL_CONSENT_TEXT,
-                true, true);
-        builtins.add(model);
-        defaultBuiltins.add(model);
-        model = UserPropertyMapper.createClaimMapper(GIVEN_NAME,
-                "firstName",
-                "given_name", "String",
-                true, GIVEN_NAME_CONSENT_TEXT,
-                true, true);
-        builtins.add(model);
-        defaultBuiltins.add(model);
-        model = UserPropertyMapper.createClaimMapper(FAMILY_NAME,
-                "lastName",
-                "family_name", "String",
-                true, FAMILY_NAME_CONSENT_TEXT,
-                true, true);
-        builtins.add(model);
-        defaultBuiltins.add(model);
-        model = UserPropertyMapper.createClaimMapper(EMAIL_VERIFIED,
-                "emailVerified",
-                "email_verified", "boolean",
-                false, EMAIL_VERIFIED_CONSENT_TEXT,
-                true, true);
-        builtins.add(model);
-
-        ProtocolMapperModel fullName = new ProtocolMapperModel();
-        fullName.setName(FULL_NAME);
-        fullName.setProtocolMapper(FullNameMapper.PROVIDER_ID);
-        fullName.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        fullName.setConsentRequired(true);
-        fullName.setConsentText(FULL_NAME_CONSENT_TEXT);
-        Map<String, String> config = new HashMap<String, String>();
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
-        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
-        fullName.setConfig(config);
-        builtins.add(fullName);
-        defaultBuiltins.add(fullName);
-
-        ProtocolMapperModel address = AddressMapper.createAddressMapper();
-        builtins.add(address);
-
-        model = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
-                KerberosConstants.GSS_DELEGATION_CREDENTIAL,
-                KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
-                true, "${gssDelegationCredential}",
-                true, false);
-        builtins.add(model);
-    }
-
-    @Override
-    protected void addDefaults(ClientModel client) {
-        for (ProtocolMapperModel model : defaultBuiltins) client.addProtocolMapper(model);
-    }
-
-    @Override
-    public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
-        return new OIDCLoginProtocolService(realm, event, authManager);
-    }
-
-    @Override
-    public String getId() {
-        return "openid-connect";
-    }
-}
+package org.keycloak.protocol.oidc;
+
+import org.keycloak.constants.KerberosConstants;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.AbstractLoginProtocolFactory;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.oidc.mappers.AddressMapper;
+import org.keycloak.protocol.oidc.mappers.FullNameMapper;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
+import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
+import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
+import org.keycloak.services.managers.AuthenticationManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
+
+    public static final String USERNAME = "username";
+    public static final String EMAIL = "email";
+    public static final String EMAIL_VERIFIED = "email verified";
+    public static final String GIVEN_NAME = "given name";
+    public static final String FAMILY_NAME = "family name";
+    public static final String FULL_NAME = "full name";
+    public static final String USERNAME_CONSENT_TEXT = "${username}";
+    public static final String EMAIL_CONSENT_TEXT = "${email}";
+    public static final String EMAIL_VERIFIED_CONSENT_TEXT = "${emailVerified}";
+    public static final String GIVEN_NAME_CONSENT_TEXT = "${givenName}";
+    public static final String FAMILY_NAME_CONSENT_TEXT = "${familyName}";
+    public static final String FULL_NAME_CONSENT_TEXT = "${fullName}";
+
+
+    @Override
+    public LoginProtocol create(KeycloakSession session) {
+        return new OIDCLoginProtocol().setSession(session);
+    }
+
+    @Override
+    public List<ProtocolMapperModel> getBuiltinMappers() {
+        return builtins;
+    }
+
+    @Override
+    public List<ProtocolMapperModel> getDefaultBuiltinMappers() {
+        return defaultBuiltins;
+    }
+
+    static List<ProtocolMapperModel> builtins = new ArrayList<>();
+    static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>();
+
+    static {
+
+        ProtocolMapperModel model;
+        model = UserPropertyMapper.createClaimMapper(USERNAME,
+                "username",
+                "preferred_username", "String",
+                true, USERNAME_CONSENT_TEXT,
+                true, true);
+        builtins.add(model);
+        defaultBuiltins.add(model);
+        model = UserPropertyMapper.createClaimMapper(EMAIL,
+                "email",
+                "email", "String",
+                true, EMAIL_CONSENT_TEXT,
+                true, true);
+        builtins.add(model);
+        defaultBuiltins.add(model);
+        model = UserPropertyMapper.createClaimMapper(GIVEN_NAME,
+                "firstName",
+                "given_name", "String",
+                true, GIVEN_NAME_CONSENT_TEXT,
+                true, true);
+        builtins.add(model);
+        defaultBuiltins.add(model);
+        model = UserPropertyMapper.createClaimMapper(FAMILY_NAME,
+                "lastName",
+                "family_name", "String",
+                true, FAMILY_NAME_CONSENT_TEXT,
+                true, true);
+        builtins.add(model);
+        defaultBuiltins.add(model);
+        model = UserPropertyMapper.createClaimMapper(EMAIL_VERIFIED,
+                "emailVerified",
+                "email_verified", "boolean",
+                false, EMAIL_VERIFIED_CONSENT_TEXT,
+                true, true);
+        builtins.add(model);
+
+        ProtocolMapperModel fullName = new ProtocolMapperModel();
+        fullName.setName(FULL_NAME);
+        fullName.setProtocolMapper(FullNameMapper.PROVIDER_ID);
+        fullName.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        fullName.setConsentRequired(true);
+        fullName.setConsentText(FULL_NAME_CONSENT_TEXT);
+        Map<String, String> config = new HashMap<String, String>();
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
+        fullName.setConfig(config);
+        builtins.add(fullName);
+        defaultBuiltins.add(fullName);
+
+        ProtocolMapperModel address = AddressMapper.createAddressMapper();
+        builtins.add(address);
+
+        model = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
+                KerberosConstants.GSS_DELEGATION_CREDENTIAL,
+                KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
+                true, "${gssDelegationCredential}",
+                true, false);
+        builtins.add(model);
+    }
+
+    @Override
+    protected void addDefaults(ClientModel client) {
+        for (ProtocolMapperModel model : defaultBuiltins) client.addProtocolMapper(model);
+    }
+
+    @Override
+    public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
+        return new OIDCLoginProtocolService(realm, event, authManager);
+    }
+
+    @Override
+    public String getId() {
+        return "openid-connect";
+    }
+}
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 e0c7170..18c78c4 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
@@ -1,214 +1,214 @@
-package org.keycloak.protocol.oidc;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.jose.jwk.JWK;
-import org.keycloak.jose.jwk.JWKBuilder;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint;
-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.protocol.oidc.endpoints.ValidateTokenEndpoint;
-import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.resources.RealmsResource;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * Resource class for the oauth/openid connect token service
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class OIDCLoginProtocolService {
-
-    protected static final Logger logger = Logger.getLogger(OIDCLoginProtocolService.class);
-
-    private RealmModel realm;
-    private TokenManager tokenManager;
-    private EventBuilder event;
-    private AuthenticationManager authManager;
-
-    @Context
-    private UriInfo uriInfo;
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private HttpHeaders headers;
-
-    public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
-        this.realm = realm;
-        this.tokenManager = new TokenManager();
-        this.event = event;
-        this.authManager = authManager;
-    }
-
-    public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
-        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
-        return tokenServiceBaseUrl(baseUriBuilder);
-    }
-
-    public static UriBuilder tokenServiceBaseUrl(UriBuilder baseUriBuilder) {
-        return baseUriBuilder.path(RealmsResource.class).path("{realm}/protocol/" + OIDCLoginProtocol.LOGIN_PROTOCOL);
-    }
-
-    public static UriBuilder authUrl(UriInfo uriInfo) {
-        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
-        return authUrl(baseUriBuilder);
-    }
-
-    public static UriBuilder authUrl(UriBuilder baseUriBuilder) {
-        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OIDCLoginProtocolService.class, "auth");
-    }
-
-    public static UriBuilder tokenUrl(UriBuilder baseUriBuilder) {
-        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OIDCLoginProtocolService.class, "token");
-    }
-
-    public static UriBuilder validateAccessTokenUrl(UriBuilder baseUriBuilder) {
-        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OIDCLoginProtocolService.class, "validateAccessToken");
-    }
-
-    public static UriBuilder logoutUrl(UriInfo uriInfo) {
-        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
-        return logoutUrl(baseUriBuilder);
-    }
-
-    public static UriBuilder logoutUrl(UriBuilder baseUriBuilder) {
-        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OIDCLoginProtocolService.class, "logout");
-    }
-
-    /**
-     * Authorization endpoint
-     */
-    @Path("auth")
-    public Object auth() {
-        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    /**
-     * Registration endpoint
-     */
-    @Path("registrations")
-    public Object registerPage() {
-        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.register();
-    }
-
-    /**
-     * Token endpoint
-     */
-    @Path("token")
-    public Object token() {
-        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    @Path("login")
-    @Deprecated
-    public Object loginPage() {
-        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM);
-    }
-
-    @Path("login-status-iframe.html")
-    public Object getLoginStatusIframe() {
-        LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    @Path("grants/access")
-    @Deprecated
-    public Object grantAccessToken() {
-        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.legacy(OAuth2Constants.PASSWORD);
-    }
-
-    @Path("refresh")
-    @Deprecated
-    public Object refreshAccessToken() {
-        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN);
-    }
-
-    @Path("access/codes")
-    @Deprecated
-    public Object accessCodeToToken() {
-        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE);
-    }
-
-    @Path("validate")
-    public Object validateAccessToken(@QueryParam("access_token") String tokenString) {
-        ValidateTokenEndpoint endpoint = new ValidateTokenEndpoint(tokenManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-
-    }
-
-    @GET
-    @Path("certs")
-    @Produces(MediaType.APPLICATION_JSON)
-    public JSONWebKeySet certs() {
-        JSONWebKeySet keySet = new JSONWebKeySet();
-        keySet.setKeys(new JWK[]{JWKBuilder.create().rs256(realm.getPublicKey())});
-        return keySet;
-    }
-
-    @Path("userinfo")
-    public Object issueUserInfo() {
-        UserInfoEndpoint endpoint = new UserInfoEndpoint(tokenManager, realm);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    @Path("logout")
-    public Object logout() {
-        LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, authManager, realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    @Path("oauth/oob")
-    @GET
-    public Response installedAppUrnCallback(final @QueryParam("code") String code, final @QueryParam("error") String error, final @QueryParam("error_description") String errorDescription) {
-        LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class);
-        if (code != null) {
-            return forms.setClientSessionCode(code).createCode();
-        } else {
-            return forms.setError(error).createCode();
-        }
-    }
-
-}
+package org.keycloak.protocol.oidc;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.jose.jwk.JWK;
+import org.keycloak.jose.jwk.JWKBuilder;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint;
+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.protocol.oidc.endpoints.ValidateTokenEndpoint;
+import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.resources.RealmsResource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Resource class for the oauth/openid connect token service
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCLoginProtocolService {
+
+    protected static final Logger logger = Logger.getLogger(OIDCLoginProtocolService.class);
+
+    private RealmModel realm;
+    private TokenManager tokenManager;
+    private EventBuilder event;
+    private AuthenticationManager authManager;
+
+    @Context
+    private UriInfo uriInfo;
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private HttpHeaders headers;
+
+    public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
+        this.realm = realm;
+        this.tokenManager = new TokenManager();
+        this.event = event;
+        this.authManager = authManager;
+    }
+
+    public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
+        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
+        return tokenServiceBaseUrl(baseUriBuilder);
+    }
+
+    public static UriBuilder tokenServiceBaseUrl(UriBuilder baseUriBuilder) {
+        return baseUriBuilder.path(RealmsResource.class).path("{realm}/protocol/" + OIDCLoginProtocol.LOGIN_PROTOCOL);
+    }
+
+    public static UriBuilder authUrl(UriInfo uriInfo) {
+        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
+        return authUrl(baseUriBuilder);
+    }
+
+    public static UriBuilder authUrl(UriBuilder baseUriBuilder) {
+        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
+        return uriBuilder.path(OIDCLoginProtocolService.class, "auth");
+    }
+
+    public static UriBuilder tokenUrl(UriBuilder baseUriBuilder) {
+        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
+        return uriBuilder.path(OIDCLoginProtocolService.class, "token");
+    }
+
+    public static UriBuilder validateAccessTokenUrl(UriBuilder baseUriBuilder) {
+        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
+        return uriBuilder.path(OIDCLoginProtocolService.class, "validateAccessToken");
+    }
+
+    public static UriBuilder logoutUrl(UriInfo uriInfo) {
+        UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
+        return logoutUrl(baseUriBuilder);
+    }
+
+    public static UriBuilder logoutUrl(UriBuilder baseUriBuilder) {
+        UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
+        return uriBuilder.path(OIDCLoginProtocolService.class, "logout");
+    }
+
+    /**
+     * Authorization endpoint
+     */
+    @Path("auth")
+    public Object auth() {
+        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    /**
+     * Registration endpoint
+     */
+    @Path("registrations")
+    public Object registerPage() {
+        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.register();
+    }
+
+    /**
+     * Token endpoint
+     */
+    @Path("token")
+    public Object token() {
+        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    @Path("login")
+    @Deprecated
+    public Object loginPage() {
+        AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM);
+    }
+
+    @Path("login-status-iframe.html")
+    public Object getLoginStatusIframe() {
+        LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    @Path("grants/access")
+    @Deprecated
+    public Object grantAccessToken() {
+        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.legacy(OAuth2Constants.PASSWORD);
+    }
+
+    @Path("refresh")
+    @Deprecated
+    public Object refreshAccessToken() {
+        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN);
+    }
+
+    @Path("access/codes")
+    @Deprecated
+    public Object accessCodeToToken() {
+        TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE);
+    }
+
+    @Path("validate")
+    public Object validateAccessToken(@QueryParam("access_token") String tokenString) {
+        ValidateTokenEndpoint endpoint = new ValidateTokenEndpoint(tokenManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+
+    }
+
+    @GET
+    @Path("certs")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JSONWebKeySet certs() {
+        JSONWebKeySet keySet = new JSONWebKeySet();
+        keySet.setKeys(new JWK[]{JWKBuilder.create().rs256(realm.getPublicKey())});
+        return keySet;
+    }
+
+    @Path("userinfo")
+    public Object issueUserInfo() {
+        UserInfoEndpoint endpoint = new UserInfoEndpoint(tokenManager, realm);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    @Path("logout")
+    public Object logout() {
+        LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, authManager, realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    @Path("oauth/oob")
+    @GET
+    public Response installedAppUrnCallback(final @QueryParam("code") String code, final @QueryParam("error") String error, final @QueryParam("error_description") String errorDescription) {
+        LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class);
+        if (code != null) {
+            return forms.setClientSessionCode(code).createCode();
+        } else {
+            return forms.setError(error).createCode();
+        }
+    }
+
+}
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 995175e..86fe75b 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -1,490 +1,490 @@
-package org.keycloak.protocol.oidc;
-
-import org.jboss.logging.Logger;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuthErrorException;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
-import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.IDToken;
-import org.keycloak.representations.RefreshToken;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Stateful object that creates tokens and manages oauth access codes
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class TokenManager {
-    protected static final Logger logger = Logger.getLogger(TokenManager.class);
-
-    public static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
-        if (visited.contains(scope)) return;
-        visited.add(scope);
-        if (role.hasRole(scope)) {
-            requested.add(scope);
-            return;
-        }
-        if (!scope.isComposite()) return;
-
-        for (RoleModel contained : scope.getComposites()) {
-            applyScope(role, contained, visited, requested);
-        }
-    }
-
-    public static class TokenValidation {
-        public final UserModel user;
-        public final UserSessionModel userSession;
-        public final ClientSessionModel clientSession;
-        public final AccessToken newToken;
-
-        public TokenValidation(UserModel user, UserSessionModel userSession, ClientSessionModel clientSession, AccessToken newToken) {
-            this.user = user;
-            this.userSession = userSession;
-            this.clientSession = clientSession;
-            this.newToken = newToken;
-        }
-    }
-
-    public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, AccessToken oldToken, HttpHeaders headers) throws OAuthErrorException {
-        UserModel user = session.users().getUserById(oldToken.getSubject(), realm);
-        if (user == null) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
-        }
-
-        if (!user.isEnabled()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
-        }
-
-        UserSessionModel userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
-        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
-            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
-        }
-        ClientSessionModel clientSession = null;
-        for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) {
-            if (clientSessionModel.getId().equals(oldToken.getClientSession())) {
-                clientSession = clientSessionModel;
-                break;
-            }
-        }
-
-        if (clientSession == null) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Client session not active", "Client session not active");
-        }
-
-        ClientModel client = clientSession.getClient();
-
-        if (!client.getClientId().equals(oldToken.getIssuedFor())) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
-        }
-
-        if (oldToken.getIssuedAt() < client.getNotBefore()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
-        }
-        if (oldToken.getIssuedAt() < realm.getNotBefore()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
-        }
-
-
-        // recreate token.
-        Set<RoleModel> requestedRoles = TokenManager.getAccess(null, clientSession.getClient(), user);
-        AccessToken newToken = createClientAccessToken(session, requestedRoles, realm, client, user, userSession, clientSession);
-        verifyAccess(oldToken, newToken);
-
-        return new TokenValidation(user, userSession, clientSession, newToken);
-
-
-    }
-
-    public AccessTokenResponse refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers) throws OAuthErrorException {
-        RefreshToken refreshToken = verifyRefreshToken(realm, encodedRefreshToken);
-
-        event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
-
-        TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
-        // validate authorizedClient is same as validated client
-        if (!validation.clientSession.getClient().getId().equals(authorizedClient.getId())) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
-        }
-
-        int currentTime = Time.currentTime();
-        validation.userSession.setLastSessionRefresh(currentTime);
-
-        AccessTokenResponse res = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSession)
-                .accessToken(validation.newToken)
-                .generateIDToken()
-                .generateRefreshToken().build();
-        return res;
-    }
-
-    public RefreshToken verifyRefreshToken(RealmModel realm, String encodedRefreshToken) throws OAuthErrorException {
-        JWSInput jws = new JWSInput(encodedRefreshToken);
-        RefreshToken refreshToken = null;
-        try {
-            if (!RSAProvider.verify(jws, realm.getPublicKey())) {
-                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
-            }
-            refreshToken = jws.readJsonContent(RefreshToken.class);
-        } catch (Exception e) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);
-        }
-        if (refreshToken.isExpired()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
-        }
-
-        if (refreshToken.getIssuedAt() < realm.getNotBefore()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
-        }
-        return refreshToken;
-    }
-    public IDToken verifyIDToken(RealmModel realm, String encodedIDToken) throws OAuthErrorException {
-        JWSInput jws = new JWSInput(encodedIDToken);
-        IDToken idToken = null;
-        try {
-            if (!RSAProvider.verify(jws, realm.getPublicKey())) {
-                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
-            }
-            idToken = jws.readJsonContent(IDToken.class);
-        } catch (IOException e) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);
-        }
-        if (idToken.isExpired()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
-        }
-
-        if (idToken.getIssuedAt() < realm.getNotBefore()) {
-            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
-        }
-        return idToken;
-    }
-
-    public AccessToken createClientAccessToken(KeycloakSession session, Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
-        AccessToken token = initToken(realm, client, user, userSession, clientSession);
-        for (RoleModel role : requestedRoles) {
-            addComposites(token, role);
-        }
-        token = transformAccessToken(session, token, realm, client, user, userSession, clientSession);
-        return token;
-    }
-
-    public static void attachClientSession(UserSessionModel session, ClientSessionModel clientSession) {
-        if (clientSession.getUserSession() != null) {
-            return;
-        }
-
-        UserModel user = session.getUser();
-        clientSession.setUserSession(session);
-        Set<String> requestedRoles = new HashSet<String>();
-        // todo scope param protocol independent
-        for (RoleModel r : TokenManager.getAccess(null, clientSession.getClient(), user)) {
-            requestedRoles.add(r.getId());
-        }
-        clientSession.setRoles(requestedRoles);
-
-        Set<String> requestedProtocolMappers = new HashSet<String>();
-        for (ProtocolMapperModel protocolMapper : clientSession.getClient().getProtocolMappers()) {
-            if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
-                requestedProtocolMappers.add(protocolMapper.getId());
-            }
-        }
-        clientSession.setProtocolMappers(requestedProtocolMappers);
-
-        Map<String, String> transferredNotes = clientSession.getUserSessionNotes();
-        for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
-            session.setNote(entry.getKey(), entry.getValue());
-        }
-
-    }
-
-    public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) {
-        UserSessionModel userSession = clientSession.getUserSession();
-        if (userSession == null) {
-            return;
-        }
-
-        clientSession.setUserSession(null);
-        clientSession.setRoles(null);
-        clientSession.setProtocolMappers(null);
-
-        if (userSession.getClientSessions().isEmpty()) {
-            sessions.removeUserSession(realm, userSession);
-        }
-    }
-
-    public static Set<RoleModel> getAccess(String scopeParam, ClientModel client, UserModel user) {
-        // todo scopeParam is ignored until we figure out a scheme that fits with openid connect
-        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
-
-        Set<RoleModel> roleMappings = user.getRoleMappings();
-        if (client.isFullScopeAllowed()) return roleMappings;
-
-        Set<RoleModel> scopeMappings = client.getScopeMappings();
-        if (client instanceof ClientModel) {
-            scopeMappings.addAll(((ClientModel) client).getRoles());
-        }
-
-        for (RoleModel role : roleMappings) {
-            for (RoleModel desiredRole : scopeMappings) {
-                Set<RoleModel> visited = new HashSet<RoleModel>();
-                applyScope(role, desiredRole, visited, requestedRoles);
-            }
-        }
-
-        return requestedRoles;
-    }
-
-    public void verifyAccess(AccessToken token, AccessToken newToken) throws OAuthErrorException {
-        if (token.getRealmAccess() != null) {
-            if (newToken.getRealmAccess() == null) throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm roles");
-
-            for (String roleName : token.getRealmAccess().getRoles()) {
-                if (!newToken.getRealmAccess().getRoles().contains(roleName)) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm role: " + roleName);
-                }
-            }
-        }
-        if (token.getResourceAccess() != null) {
-            for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
-                AccessToken.Access appAccess = newToken.getResourceAccess(entry.getKey());
-                if (appAccess == null && !entry.getValue().getRoles().isEmpty()) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or client no longer has role permissions for client key: " + entry.getKey());
-
-                }
-                for (String roleName : entry.getValue().getRoles()) {
-                    if (!appAccess.getRoles().contains(roleName)) {
-                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for client role " + roleName);
-                    }
-                }
-            }
-        }
-    }
-
-    public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
-        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
-        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);
-
-        }
-        return token;
-    }
-    public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user,
-                                      UserSessionModel userSession, ClientSessionModel clientSession) {
-        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
-        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
-        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);
-
-        }
-    }
-
-
-    protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
-        AccessToken token = new AccessToken();
-        if (clientSession != null) token.clientSession(clientSession.getId());
-        token.id(KeycloakModelUtils.generateId());
-        token.subject(user.getId());
-        token.audience(client.getClientId());
-        token.issuedNow();
-        token.issuedFor(client.getClientId());
-        token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
-        token.setNonce(clientSession.getNote(OIDCLoginProtocol.NONCE_PARAM));
-        if (session != null) {
-            token.setSessionState(session.getId());
-        }
-        if (realm.getAccessTokenLifespan() > 0) {
-            token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
-        }
-        Set<String> allowedOrigins = client.getWebOrigins();
-        if (allowedOrigins != null) {
-            token.setAllowedOrigins(allowedOrigins);
-        }
-        return token;
-    }
-
-    protected void addComposites(AccessToken token, RoleModel role) {
-        AccessToken.Access access = null;
-        if (role.getContainer() instanceof RealmModel) {
-            access = token.getRealmAccess();
-            if (token.getRealmAccess() == null) {
-                access = new AccessToken.Access();
-                token.setRealmAccess(access);
-            } else if (token.getRealmAccess().getRoles() != null && token.getRealmAccess().isUserInRole(role.getName()))
-                return;
-
-        } else {
-            ClientModel app = (ClientModel) role.getContainer();
-            access = token.getResourceAccess(app.getClientId());
-            if (access == null) {
-                access = token.addAccess(app.getClientId());
-                if (app.isSurrogateAuthRequired()) access.verifyCaller(true);
-            } else if (access.isUserInRole(role.getName())) return;
-
-        }
-        access.addRole(role.getName());
-        if (!role.isComposite()) return;
-
-        for (RoleModel composite : role.getComposites()) {
-            addComposites(token, composite);
-        }
-
-    }
-
-    public String encodeToken(RealmModel realm, Object token) {
-        String encodedToken = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(realm.getPrivateKey());
-        return encodedToken;
-    }
-
-    public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        return new AccessTokenResponseBuilder(realm, client, event, session, userSession, clientSession);
-    }
-
-    public class AccessTokenResponseBuilder {
-        RealmModel realm;
-        ClientModel client;
-        EventBuilder event;
-        KeycloakSession session;
-        UserSessionModel userSession;
-        ClientSessionModel clientSession;
-
-        AccessToken accessToken;
-        RefreshToken refreshToken;
-        IDToken idToken;
-
-        public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-            this.realm = realm;
-            this.client = client;
-            this.event = event;
-            this.session = session;
-            this.userSession = userSession;
-            this.clientSession = clientSession;
-        }
-
-        public AccessTokenResponseBuilder accessToken(AccessToken accessToken) {
-            this.accessToken = accessToken;
-            return this;
-        }
-        public AccessTokenResponseBuilder refreshToken(RefreshToken refreshToken) {
-            this.refreshToken = refreshToken;
-            return this;
-        }
-
-        public AccessTokenResponseBuilder generateAccessToken(KeycloakSession session, String scopeParam, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
-            Set<RoleModel> requestedRoles = getAccess(scopeParam, client, user);
-            accessToken = createClientAccessToken(session, requestedRoles, realm, client, user, userSession, clientSession);
-            return this;
-        }
-
-        public AccessTokenResponseBuilder generateRefreshToken() {
-            if (accessToken == null) {
-                throw new IllegalStateException("accessToken not set");
-            }
-            refreshToken = new RefreshToken(accessToken);
-            refreshToken.id(KeycloakModelUtils.generateId());
-            refreshToken.issuedNow();
-            refreshToken.expiration(Time.currentTime() + realm.getSsoSessionIdleTimeout());
-            return this;
-        }
-
-        public AccessTokenResponseBuilder generateIDToken() {
-            if (accessToken == null) {
-                throw new IllegalStateException("accessToken not set");
-            }
-            idToken = new IDToken();
-            idToken.id(KeycloakModelUtils.generateId());
-            idToken.subject(accessToken.getSubject());
-            idToken.audience(client.getClientId());
-            idToken.issuedNow();
-            idToken.issuedFor(accessToken.getIssuedFor());
-            idToken.issuer(accessToken.getIssuer());
-            idToken.setNonce(accessToken.getNonce());
-            idToken.setSessionState(accessToken.getSessionState());
-            if (realm.getAccessTokenLifespan() > 0) {
-                idToken.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
-            }
-            transformIDToken(session, idToken, realm, client, userSession.getUser(), userSession, clientSession);
-            return this;
-        }
-
-
-
-        public AccessTokenResponse build() {
-            if (accessToken != null) {
-                event.detail(Details.TOKEN_ID, accessToken.getId());
-            }
-
-            if (refreshToken != null) {
-                if (event.getEvent().getDetails().containsKey(Details.REFRESH_TOKEN_ID)) {
-                    event.detail(Details.UPDATED_REFRESH_TOKEN_ID, refreshToken.getId());
-                } else {
-                    event.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
-                }
-            }
-
-            AccessTokenResponse res = new AccessTokenResponse();
-            if (idToken != null) {
-                String encodedToken = new JWSBuilder().jsonContent(idToken).rsa256(realm.getPrivateKey());
-                res.setIdToken(encodedToken);
-            }
-            if (accessToken != null) {
-                String encodedToken = new JWSBuilder().jsonContent(accessToken).rsa256(realm.getPrivateKey());
-                res.setToken(encodedToken);
-                res.setTokenType("bearer");
-                res.setSessionState(accessToken.getSessionState());
-                if (accessToken.getExpiration() != 0) {
-                    res.setExpiresIn(accessToken.getExpiration() - Time.currentTime());
-                }
-            }
-            if (refreshToken != null) {
-                String encodedToken = new JWSBuilder().jsonContent(refreshToken).rsa256(realm.getPrivateKey());
-                res.setRefreshToken(encodedToken);
-                if (refreshToken.getExpiration() != 0) {
-                    res.setRefreshExpiresIn(refreshToken.getExpiration() - Time.currentTime());
-                }
-            }
-            int notBefore = realm.getNotBefore();
-            if (client.getNotBefore() > notBefore) notBefore = client.getNotBefore();
-            res.setNotBeforePolicy(notBefore);
-            return res;
-        }
-    }
-
-}
+package org.keycloak.protocol.oidc;
+
+import org.jboss.logging.Logger;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuthErrorException;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.UserSessionProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
+import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.RefreshToken;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Stateful object that creates tokens and manages oauth access codes
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class TokenManager {
+    protected static final Logger logger = Logger.getLogger(TokenManager.class);
+
+    public static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
+        if (visited.contains(scope)) return;
+        visited.add(scope);
+        if (role.hasRole(scope)) {
+            requested.add(scope);
+            return;
+        }
+        if (!scope.isComposite()) return;
+
+        for (RoleModel contained : scope.getComposites()) {
+            applyScope(role, contained, visited, requested);
+        }
+    }
+
+    public static class TokenValidation {
+        public final UserModel user;
+        public final UserSessionModel userSession;
+        public final ClientSessionModel clientSession;
+        public final AccessToken newToken;
+
+        public TokenValidation(UserModel user, UserSessionModel userSession, ClientSessionModel clientSession, AccessToken newToken) {
+            this.user = user;
+            this.userSession = userSession;
+            this.clientSession = clientSession;
+            this.newToken = newToken;
+        }
+    }
+
+    public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, AccessToken oldToken, HttpHeaders headers) throws OAuthErrorException {
+        UserModel user = session.users().getUserById(oldToken.getSubject(), realm);
+        if (user == null) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
+        }
+
+        if (!user.isEnabled()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
+        }
+
+        UserSessionModel userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
+        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
+            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
+        }
+        ClientSessionModel clientSession = null;
+        for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) {
+            if (clientSessionModel.getId().equals(oldToken.getClientSession())) {
+                clientSession = clientSessionModel;
+                break;
+            }
+        }
+
+        if (clientSession == null) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Client session not active", "Client session not active");
+        }
+
+        ClientModel client = clientSession.getClient();
+
+        if (!client.getClientId().equals(oldToken.getIssuedFor())) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
+        }
+
+        if (oldToken.getIssuedAt() < client.getNotBefore()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
+        }
+        if (oldToken.getIssuedAt() < realm.getNotBefore()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
+        }
+
+
+        // recreate token.
+        Set<RoleModel> requestedRoles = TokenManager.getAccess(null, clientSession.getClient(), user);
+        AccessToken newToken = createClientAccessToken(session, requestedRoles, realm, client, user, userSession, clientSession);
+        verifyAccess(oldToken, newToken);
+
+        return new TokenValidation(user, userSession, clientSession, newToken);
+
+
+    }
+
+    public AccessTokenResponse refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers) throws OAuthErrorException {
+        RefreshToken refreshToken = verifyRefreshToken(realm, encodedRefreshToken);
+
+        event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
+
+        TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
+        // validate authorizedClient is same as validated client
+        if (!validation.clientSession.getClient().getId().equals(authorizedClient.getId())) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
+        }
+
+        int currentTime = Time.currentTime();
+        validation.userSession.setLastSessionRefresh(currentTime);
+
+        AccessTokenResponse res = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSession)
+                .accessToken(validation.newToken)
+                .generateIDToken()
+                .generateRefreshToken().build();
+        return res;
+    }
+
+    public RefreshToken verifyRefreshToken(RealmModel realm, String encodedRefreshToken) throws OAuthErrorException {
+        JWSInput jws = new JWSInput(encodedRefreshToken);
+        RefreshToken refreshToken = null;
+        try {
+            if (!RSAProvider.verify(jws, realm.getPublicKey())) {
+                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
+            }
+            refreshToken = jws.readJsonContent(RefreshToken.class);
+        } catch (Exception e) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);
+        }
+        if (refreshToken.isExpired()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
+        }
+
+        if (refreshToken.getIssuedAt() < realm.getNotBefore()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
+        }
+        return refreshToken;
+    }
+    public IDToken verifyIDToken(RealmModel realm, String encodedIDToken) throws OAuthErrorException {
+        JWSInput jws = new JWSInput(encodedIDToken);
+        IDToken idToken = null;
+        try {
+            if (!RSAProvider.verify(jws, realm.getPublicKey())) {
+                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
+            }
+            idToken = jws.readJsonContent(IDToken.class);
+        } catch (IOException e) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);
+        }
+        if (idToken.isExpired()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
+        }
+
+        if (idToken.getIssuedAt() < realm.getNotBefore()) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
+        }
+        return idToken;
+    }
+
+    public AccessToken createClientAccessToken(KeycloakSession session, Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
+        AccessToken token = initToken(realm, client, user, userSession, clientSession);
+        for (RoleModel role : requestedRoles) {
+            addComposites(token, role);
+        }
+        token = transformAccessToken(session, token, realm, client, user, userSession, clientSession);
+        return token;
+    }
+
+    public static void attachClientSession(UserSessionModel session, ClientSessionModel clientSession) {
+        if (clientSession.getUserSession() != null) {
+            return;
+        }
+
+        UserModel user = session.getUser();
+        clientSession.setUserSession(session);
+        Set<String> requestedRoles = new HashSet<String>();
+        // todo scope param protocol independent
+        for (RoleModel r : TokenManager.getAccess(null, clientSession.getClient(), user)) {
+            requestedRoles.add(r.getId());
+        }
+        clientSession.setRoles(requestedRoles);
+
+        Set<String> requestedProtocolMappers = new HashSet<String>();
+        for (ProtocolMapperModel protocolMapper : clientSession.getClient().getProtocolMappers()) {
+            if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
+                requestedProtocolMappers.add(protocolMapper.getId());
+            }
+        }
+        clientSession.setProtocolMappers(requestedProtocolMappers);
+
+        Map<String, String> transferredNotes = clientSession.getUserSessionNotes();
+        for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
+            session.setNote(entry.getKey(), entry.getValue());
+        }
+
+    }
+
+    public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) {
+        UserSessionModel userSession = clientSession.getUserSession();
+        if (userSession == null) {
+            return;
+        }
+
+        clientSession.setUserSession(null);
+        clientSession.setRoles(null);
+        clientSession.setProtocolMappers(null);
+
+        if (userSession.getClientSessions().isEmpty()) {
+            sessions.removeUserSession(realm, userSession);
+        }
+    }
+
+    public static Set<RoleModel> getAccess(String scopeParam, ClientModel client, UserModel user) {
+        // todo scopeParam is ignored until we figure out a scheme that fits with openid connect
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+
+        Set<RoleModel> roleMappings = user.getRoleMappings();
+        if (client.isFullScopeAllowed()) return roleMappings;
+
+        Set<RoleModel> scopeMappings = client.getScopeMappings();
+        if (client instanceof ClientModel) {
+            scopeMappings.addAll(((ClientModel) client).getRoles());
+        }
+
+        for (RoleModel role : roleMappings) {
+            for (RoleModel desiredRole : scopeMappings) {
+                Set<RoleModel> visited = new HashSet<RoleModel>();
+                applyScope(role, desiredRole, visited, requestedRoles);
+            }
+        }
+
+        return requestedRoles;
+    }
+
+    public void verifyAccess(AccessToken token, AccessToken newToken) throws OAuthErrorException {
+        if (token.getRealmAccess() != null) {
+            if (newToken.getRealmAccess() == null) throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm roles");
+
+            for (String roleName : token.getRealmAccess().getRoles()) {
+                if (!newToken.getRealmAccess().getRoles().contains(roleName)) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm role: " + roleName);
+                }
+            }
+        }
+        if (token.getResourceAccess() != null) {
+            for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
+                AccessToken.Access appAccess = newToken.getResourceAccess(entry.getKey());
+                if (appAccess == null && !entry.getValue().getRoles().isEmpty()) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or client no longer has role permissions for client key: " + entry.getKey());
+
+                }
+                for (String roleName : entry.getValue().getRoles()) {
+                    if (!appAccess.getRoles().contains(roleName)) {
+                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for client role " + roleName);
+                    }
+                }
+            }
+        }
+    }
+
+    public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
+        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+        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);
+
+        }
+        return token;
+    }
+    public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user,
+                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
+        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+        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);
+
+        }
+    }
+
+
+    protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
+        AccessToken token = new AccessToken();
+        if (clientSession != null) token.clientSession(clientSession.getId());
+        token.id(KeycloakModelUtils.generateId());
+        token.subject(user.getId());
+        token.audience(client.getClientId());
+        token.issuedNow();
+        token.issuedFor(client.getClientId());
+        token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
+        token.setNonce(clientSession.getNote(OIDCLoginProtocol.NONCE_PARAM));
+        if (session != null) {
+            token.setSessionState(session.getId());
+        }
+        if (realm.getAccessTokenLifespan() > 0) {
+            token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
+        }
+        Set<String> allowedOrigins = client.getWebOrigins();
+        if (allowedOrigins != null) {
+            token.setAllowedOrigins(allowedOrigins);
+        }
+        return token;
+    }
+
+    protected void addComposites(AccessToken token, RoleModel role) {
+        AccessToken.Access access = null;
+        if (role.getContainer() instanceof RealmModel) {
+            access = token.getRealmAccess();
+            if (token.getRealmAccess() == null) {
+                access = new AccessToken.Access();
+                token.setRealmAccess(access);
+            } else if (token.getRealmAccess().getRoles() != null && token.getRealmAccess().isUserInRole(role.getName()))
+                return;
+
+        } else {
+            ClientModel app = (ClientModel) role.getContainer();
+            access = token.getResourceAccess(app.getClientId());
+            if (access == null) {
+                access = token.addAccess(app.getClientId());
+                if (app.isSurrogateAuthRequired()) access.verifyCaller(true);
+            } else if (access.isUserInRole(role.getName())) return;
+
+        }
+        access.addRole(role.getName());
+        if (!role.isComposite()) return;
+
+        for (RoleModel composite : role.getComposites()) {
+            addComposites(token, composite);
+        }
+
+    }
+
+    public String encodeToken(RealmModel realm, Object token) {
+        String encodedToken = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(realm.getPrivateKey());
+        return encodedToken;
+    }
+
+    public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        return new AccessTokenResponseBuilder(realm, client, event, session, userSession, clientSession);
+    }
+
+    public class AccessTokenResponseBuilder {
+        RealmModel realm;
+        ClientModel client;
+        EventBuilder event;
+        KeycloakSession session;
+        UserSessionModel userSession;
+        ClientSessionModel clientSession;
+
+        AccessToken accessToken;
+        RefreshToken refreshToken;
+        IDToken idToken;
+
+        public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+            this.realm = realm;
+            this.client = client;
+            this.event = event;
+            this.session = session;
+            this.userSession = userSession;
+            this.clientSession = clientSession;
+        }
+
+        public AccessTokenResponseBuilder accessToken(AccessToken accessToken) {
+            this.accessToken = accessToken;
+            return this;
+        }
+        public AccessTokenResponseBuilder refreshToken(RefreshToken refreshToken) {
+            this.refreshToken = refreshToken;
+            return this;
+        }
+
+        public AccessTokenResponseBuilder generateAccessToken(KeycloakSession session, String scopeParam, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
+            Set<RoleModel> requestedRoles = getAccess(scopeParam, client, user);
+            accessToken = createClientAccessToken(session, requestedRoles, realm, client, user, userSession, clientSession);
+            return this;
+        }
+
+        public AccessTokenResponseBuilder generateRefreshToken() {
+            if (accessToken == null) {
+                throw new IllegalStateException("accessToken not set");
+            }
+            refreshToken = new RefreshToken(accessToken);
+            refreshToken.id(KeycloakModelUtils.generateId());
+            refreshToken.issuedNow();
+            refreshToken.expiration(Time.currentTime() + realm.getSsoSessionIdleTimeout());
+            return this;
+        }
+
+        public AccessTokenResponseBuilder generateIDToken() {
+            if (accessToken == null) {
+                throw new IllegalStateException("accessToken not set");
+            }
+            idToken = new IDToken();
+            idToken.id(KeycloakModelUtils.generateId());
+            idToken.subject(accessToken.getSubject());
+            idToken.audience(client.getClientId());
+            idToken.issuedNow();
+            idToken.issuedFor(accessToken.getIssuedFor());
+            idToken.issuer(accessToken.getIssuer());
+            idToken.setNonce(accessToken.getNonce());
+            idToken.setSessionState(accessToken.getSessionState());
+            if (realm.getAccessTokenLifespan() > 0) {
+                idToken.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
+            }
+            transformIDToken(session, idToken, realm, client, userSession.getUser(), userSession, clientSession);
+            return this;
+        }
+
+
+
+        public AccessTokenResponse build() {
+            if (accessToken != null) {
+                event.detail(Details.TOKEN_ID, accessToken.getId());
+            }
+
+            if (refreshToken != null) {
+                if (event.getEvent().getDetails().containsKey(Details.REFRESH_TOKEN_ID)) {
+                    event.detail(Details.UPDATED_REFRESH_TOKEN_ID, refreshToken.getId());
+                } else {
+                    event.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
+                }
+            }
+
+            AccessTokenResponse res = new AccessTokenResponse();
+            if (idToken != null) {
+                String encodedToken = new JWSBuilder().jsonContent(idToken).rsa256(realm.getPrivateKey());
+                res.setIdToken(encodedToken);
+            }
+            if (accessToken != null) {
+                String encodedToken = new JWSBuilder().jsonContent(accessToken).rsa256(realm.getPrivateKey());
+                res.setToken(encodedToken);
+                res.setTokenType("bearer");
+                res.setSessionState(accessToken.getSessionState());
+                if (accessToken.getExpiration() != 0) {
+                    res.setExpiresIn(accessToken.getExpiration() - Time.currentTime());
+                }
+            }
+            if (refreshToken != null) {
+                String encodedToken = new JWSBuilder().jsonContent(refreshToken).rsa256(realm.getPrivateKey());
+                res.setRefreshToken(encodedToken);
+                if (refreshToken.getExpiration() != 0) {
+                    res.setRefreshExpiresIn(refreshToken.getExpiration() - Time.currentTime());
+                }
+            }
+            int notBefore = realm.getNotBefore();
+            if (client.getNotBefore() > notBefore) notBefore = client.getNotBefore();
+            res.setNotBeforePolicy(notBefore);
+            return res;
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
index 2016d5d..36851da 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
@@ -1,16 +1,16 @@
-package org.keycloak.protocol;
-
-import org.keycloak.provider.ConfiguredProvider;
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper>,ConfiguredProvider {
-    String getProtocol();
-    String getDisplayCategory();
-    String getDisplayType();
-
-}
+package org.keycloak.protocol;
+
+import org.keycloak.provider.ConfiguredProvider;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper>,ConfiguredProvider {
+    String getProtocol();
+    String getDisplayCategory();
+    String getDisplayType();
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
index fecd27f..829e863 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
@@ -1,62 +1,62 @@
-package org.keycloak.protocol;
-
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.AccessToken;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMapperUtils {
-    public static final String USER_ATTRIBUTE = "user.attribute";
-    public static final String USER_SESSION_NOTE = "user.session.note";
-    public static final String MULTIVALUED = "multivalued";
-    public static final String USER_MODEL_PROPERTY_LABEL = "User Property";
-    public static final String USER_MODEL_PROPERTY_HELP_TEXT = "Name of the property method in the UserModel interface.  For example, a value of 'email' would reference the UserModel.getEmail() method.";
-    public static final String USER_MODEL_ATTRIBUTE_LABEL = "User Attribute";
-    public static final String USER_MODEL_ATTRIBUTE_HELP_TEXT = "Name of stored user attribute which is the name of an attribute within the UserModel.attribute map.";
-    public static final String USER_SESSION_MODEL_NOTE_LABEL = "User Session Note";
-    public static final String USER_SESSION_MODEL_NOTE_HELP_TEXT = "Name of stored user session note within the UserSessionModel.note map.";
-    public static final String MULTIVALUED_LABEL = "Multivalued";
-    public static final String MULTIVALUED_HELP_TEXT = "Indicates if attribute supports multiple values. If true, then the list of all values of this attribute will be set as claim. If false, then just first value will be set as claim";
-
-    public static String getUserModelValue(UserModel user, String propertyName) {
-
-        String methodName = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
-        try {
-            Method method = UserModel.class.getMethod(methodName);
-            Object val = method.invoke(user);
-            if (val != null) return val.toString();
-        } catch (Exception ignore) {
-
-        }
-        methodName = "is" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
-        try {
-            Method method = UserModel.class.getMethod(methodName);
-            Object val = method.invoke(user);
-            if (val != null) return val.toString();
-        } catch (Exception ignore) {
-
-        }
-        return null;
-    }
-
-    public static String[] parseRole(String role) {
-        int scopeIndex = role.lastIndexOf('.');
-        if (scopeIndex > -1) {
-            String appName = role.substring(0, scopeIndex);
-            role = role.substring(scopeIndex + 1);
-            String[] rtn = {appName, role};
-            return rtn;
-        } else {
-            String[] rtn = {null, role};
-            return rtn;
-
-        }
-    }
-}
+package org.keycloak.protocol;
+
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.AccessToken;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMapperUtils {
+    public static final String USER_ATTRIBUTE = "user.attribute";
+    public static final String USER_SESSION_NOTE = "user.session.note";
+    public static final String MULTIVALUED = "multivalued";
+    public static final String USER_MODEL_PROPERTY_LABEL = "User Property";
+    public static final String USER_MODEL_PROPERTY_HELP_TEXT = "Name of the property method in the UserModel interface.  For example, a value of 'email' would reference the UserModel.getEmail() method.";
+    public static final String USER_MODEL_ATTRIBUTE_LABEL = "User Attribute";
+    public static final String USER_MODEL_ATTRIBUTE_HELP_TEXT = "Name of stored user attribute which is the name of an attribute within the UserModel.attribute map.";
+    public static final String USER_SESSION_MODEL_NOTE_LABEL = "User Session Note";
+    public static final String USER_SESSION_MODEL_NOTE_HELP_TEXT = "Name of stored user session note within the UserSessionModel.note map.";
+    public static final String MULTIVALUED_LABEL = "Multivalued";
+    public static final String MULTIVALUED_HELP_TEXT = "Indicates if attribute supports multiple values. If true, then the list of all values of this attribute will be set as claim. If false, then just first value will be set as claim";
+
+    public static String getUserModelValue(UserModel user, String propertyName) {
+
+        String methodName = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
+        try {
+            Method method = UserModel.class.getMethod(methodName);
+            Object val = method.invoke(user);
+            if (val != null) return val.toString();
+        } catch (Exception ignore) {
+
+        }
+        methodName = "is" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
+        try {
+            Method method = UserModel.class.getMethod(methodName);
+            Object val = method.invoke(user);
+            if (val != null) return val.toString();
+        } catch (Exception ignore) {
+
+        }
+        return null;
+    }
+
+    public static String[] parseRole(String role) {
+        int scopeIndex = role.lastIndexOf('.');
+        if (scopeIndex > -1) {
+            String appName = role.substring(0, scopeIndex);
+            role = role.substring(scopeIndex + 1);
+            String[] rtn = {appName, role};
+            return rtn;
+        } else {
+            String[] rtn = {null, role};
+            return rtn;
+
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index c672235..fc06d93 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -1,168 +1,168 @@
-package org.keycloak.services;
-
-import org.jboss.resteasy.spi.HttpRequest;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.models.KeycloakContext;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakTransactionManager;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserFederationManager;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.cache.CacheRealmProvider;
-import org.keycloak.models.cache.CacheUserProvider;
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-
-import javax.ws.rs.core.UriInfo;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class DefaultKeycloakSession implements KeycloakSession {
-
-    private final DefaultKeycloakSessionFactory factory;
-    private final Map<Integer, Provider> providers = new HashMap<>();
-    private final List<Provider> closable = new LinkedList<Provider>();
-    private final DefaultKeycloakTransactionManager transactionManager;
-    private RealmProvider model;
-    private UserProvider userModel;
-    private UserSessionProvider sessionProvider;
-    private UserFederationManager federationManager;
-    private KeycloakContext context;
-
-    public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
-        this.factory = factory;
-        this.transactionManager = new DefaultKeycloakTransactionManager();
-        federationManager = new UserFederationManager(this);
-        context = new DefaultKeycloakContext();
-    }
-
-    @Override
-    public KeycloakContext getContext() {
-        return context;
-    }
-
-    private RealmProvider getRealmProvider() {
-        if (factory.getDefaultProvider(CacheRealmProvider.class) != null) {
-            return getProvider(CacheRealmProvider.class);
-        } else {
-            return getProvider(RealmProvider.class);
-        }
-    }
-
-    private UserProvider getUserProvider() {
-        if (factory.getDefaultProvider(CacheUserProvider.class) != null) {
-            return getProvider(CacheUserProvider.class);
-        } else {
-            return getProvider(UserProvider.class);
-        }
-    }
-
-    @Override
-    public void enlistForClose(Provider provider) {
-        closable.add(provider);
-    }
-
-    @Override
-    public KeycloakTransactionManager getTransaction() {
-        return transactionManager;
-    }
-
-    @Override
-    public KeycloakSessionFactory getKeycloakSessionFactory() {
-        return factory;
-    }
-
-    @Override
-    public UserProvider userStorage() {
-        if (userModel == null) {
-            userModel = getUserProvider();
-        }
-        return userModel;
-
-    }
-
-    public <T extends Provider> T getProvider(Class<T> clazz) {
-        Integer hash = clazz.hashCode();
-        T provider = (T) providers.get(hash);
-        if (provider == null) {
-            ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz);
-            if (providerFactory != null) {
-                provider = providerFactory.create(this);
-                providers.put(hash, provider);
-            }
-        }
-        return provider;
-    }
-
-    public <T extends Provider> T getProvider(Class<T> clazz, String id) {
-        Integer hash = clazz.hashCode() + id.hashCode();
-        T provider = (T) providers.get(hash);
-        if (provider == null) {
-            ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz, id);
-            if (providerFactory != null) {
-                provider = providerFactory.create(this);
-                providers.put(hash, provider);
-            }
-        }
-        return provider;
-    }
-
-    public <T extends Provider> Set<String> listProviderIds(Class<T> clazz) {
-        return factory.getAllProviderIds(clazz);
-    }
-
-    @Override
-    public <T extends Provider> Set<T> getAllProviders(Class<T> clazz) {
-        Set<T> providers = new HashSet<T>();
-        for (String id : listProviderIds(clazz)) {
-            providers.add(getProvider(clazz, id));
-        }
-        return providers;
-    }
-
-    @Override
-    public RealmProvider realms() {
-        if (model == null) {
-            model = getRealmProvider();
-        }
-        return model;
-    }
-
-    @Override
-    public UserFederationManager users() {
-        return federationManager;
-    }
-
-    @Override
-    public UserSessionProvider sessions() {
-        if (sessionProvider == null) {
-            sessionProvider = getProvider(UserSessionProvider.class);
-        }
-        return sessionProvider;
-    }
-
-    public void close() {
-        for (Provider p : providers.values()) {
-            try {
-                p.close();
-            } catch (Exception e) {
-            }
-        }
-        for (Provider p : closable) {
-            try {
-                p.close();
-            } catch (Exception e) {
-            }
-        }
-    }
-
-}
+package org.keycloak.services;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.models.KeycloakContext;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakTransactionManager;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.UserFederationManager;
+import org.keycloak.models.UserProvider;
+import org.keycloak.models.UserSessionProvider;
+import org.keycloak.models.cache.CacheRealmProvider;
+import org.keycloak.models.cache.CacheUserProvider;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+import javax.ws.rs.core.UriInfo;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class DefaultKeycloakSession implements KeycloakSession {
+
+    private final DefaultKeycloakSessionFactory factory;
+    private final Map<Integer, Provider> providers = new HashMap<>();
+    private final List<Provider> closable = new LinkedList<Provider>();
+    private final DefaultKeycloakTransactionManager transactionManager;
+    private RealmProvider model;
+    private UserProvider userModel;
+    private UserSessionProvider sessionProvider;
+    private UserFederationManager federationManager;
+    private KeycloakContext context;
+
+    public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
+        this.factory = factory;
+        this.transactionManager = new DefaultKeycloakTransactionManager();
+        federationManager = new UserFederationManager(this);
+        context = new DefaultKeycloakContext();
+    }
+
+    @Override
+    public KeycloakContext getContext() {
+        return context;
+    }
+
+    private RealmProvider getRealmProvider() {
+        if (factory.getDefaultProvider(CacheRealmProvider.class) != null) {
+            return getProvider(CacheRealmProvider.class);
+        } else {
+            return getProvider(RealmProvider.class);
+        }
+    }
+
+    private UserProvider getUserProvider() {
+        if (factory.getDefaultProvider(CacheUserProvider.class) != null) {
+            return getProvider(CacheUserProvider.class);
+        } else {
+            return getProvider(UserProvider.class);
+        }
+    }
+
+    @Override
+    public void enlistForClose(Provider provider) {
+        closable.add(provider);
+    }
+
+    @Override
+    public KeycloakTransactionManager getTransaction() {
+        return transactionManager;
+    }
+
+    @Override
+    public KeycloakSessionFactory getKeycloakSessionFactory() {
+        return factory;
+    }
+
+    @Override
+    public UserProvider userStorage() {
+        if (userModel == null) {
+            userModel = getUserProvider();
+        }
+        return userModel;
+
+    }
+
+    public <T extends Provider> T getProvider(Class<T> clazz) {
+        Integer hash = clazz.hashCode();
+        T provider = (T) providers.get(hash);
+        if (provider == null) {
+            ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz);
+            if (providerFactory != null) {
+                provider = providerFactory.create(this);
+                providers.put(hash, provider);
+            }
+        }
+        return provider;
+    }
+
+    public <T extends Provider> T getProvider(Class<T> clazz, String id) {
+        Integer hash = clazz.hashCode() + id.hashCode();
+        T provider = (T) providers.get(hash);
+        if (provider == null) {
+            ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz, id);
+            if (providerFactory != null) {
+                provider = providerFactory.create(this);
+                providers.put(hash, provider);
+            }
+        }
+        return provider;
+    }
+
+    public <T extends Provider> Set<String> listProviderIds(Class<T> clazz) {
+        return factory.getAllProviderIds(clazz);
+    }
+
+    @Override
+    public <T extends Provider> Set<T> getAllProviders(Class<T> clazz) {
+        Set<T> providers = new HashSet<T>();
+        for (String id : listProviderIds(clazz)) {
+            providers.add(getProvider(clazz, id));
+        }
+        return providers;
+    }
+
+    @Override
+    public RealmProvider realms() {
+        if (model == null) {
+            model = getRealmProvider();
+        }
+        return model;
+    }
+
+    @Override
+    public UserFederationManager users() {
+        return federationManager;
+    }
+
+    @Override
+    public UserSessionProvider sessions() {
+        if (sessionProvider == null) {
+            sessionProvider = getProvider(UserSessionProvider.class);
+        }
+        return sessionProvider;
+    }
+
+    public void close() {
+        for (Provider p : providers.values()) {
+            try {
+                p.close();
+            } catch (Exception e) {
+            }
+        }
+        for (Provider p : closable) {
+            try {
+                p.close();
+            } catch (Exception e) {
+            }
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index b91858a..e312aa0 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -1,151 +1,151 @@
-package org.keycloak.services;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderEvent;
-import org.keycloak.provider.ProviderEventListener;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.ProviderManager;
-import org.keycloak.provider.Spi;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
-
-    private static final Logger log = Logger.getLogger(DefaultKeycloakSessionFactory.class);
-
-    private Map<Class<? extends Provider>, String> provider = new HashMap<Class<? extends Provider>, String>();
-    private Map<Class<? extends Provider>, Map<String, ProviderFactory>> factoriesMap = new HashMap<Class<? extends Provider>, Map<String, ProviderFactory>>();
-    protected CopyOnWriteArrayList<ProviderEventListener> listeners = new CopyOnWriteArrayList<ProviderEventListener>();
-
-    @Override
-    public void register(ProviderEventListener listener) {
-        listeners.add(listener);
-    }
-
-    @Override
-    public void unregister(ProviderEventListener listener) {
-        listeners.remove(listener);
-    }
-
-    @Override
-    public void publish(ProviderEvent event) {
-        for (ProviderEventListener listener : listeners) {
-            listener.onEvent(event);
-        }
-    }
-
-    public void init() {
-        ProviderManager pm = new ProviderManager(getClass().getClassLoader(), Config.scope().getArray("providers"));
-
-        for (Spi spi : ServiceLoader.load(Spi.class, getClass().getClassLoader())) {
-            Map<String, ProviderFactory> factories = new HashMap<String, ProviderFactory>();
-            factoriesMap.put(spi.getProviderClass(), factories);
-
-            String provider = Config.getProvider(spi.getName());
-            if (provider != null) {
-                this.provider.put(spi.getProviderClass(), provider);
-
-                ProviderFactory factory = pm.load(spi, provider);
-                if (factory == null) {
-                    throw new RuntimeException("Failed to find provider " + provider + " for " + spi.getName());
-                }
-
-                Config.Scope scope = Config.scope(spi.getName(), provider);
-                factory.init(scope);
-
-                if (spi.isInternal() && !isInternal(factory)) {
-                    log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
-                }
-
-                factories.put(factory.getId(), factory);
-
-                log.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
-            } else {
-                for (ProviderFactory factory : pm.load(spi)) {
-                    Config.Scope scope = Config.scope(spi.getName(), factory.getId());
-                    factory.init(scope);
-
-                    if (spi.isInternal() && !isInternal(factory)) {
-                        log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
-                    }
-
-                    factories.put(factory.getId(), factory);
-                }
-
-                if (factories.size() == 1) {
-                    provider = factories.values().iterator().next().getId();
-                    this.provider.put(spi.getProviderClass(), provider);
-
-                    log.debugv("Loaded SPI {0}  (provider = {1})", spi.getName(), provider);
-                } else {
-                    log.debugv("Loaded SPI {0} (providers = {1})", spi.getName(), factories.keySet());
-                }
-            }
-        }
-        for ( Map<String, ProviderFactory> factories : factoriesMap.values()) {
-            for (ProviderFactory factory : factories.values()) {
-                factory.postInit(this);
-            }
-        }
-    }
-
-    public KeycloakSession create() {
-        return new DefaultKeycloakSession(this);
-    }
-
-    <T extends Provider> String getDefaultProvider(Class<T> clazz) {
-        return provider.get(clazz);
-    }
-
-    @Override
-    public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz) {
-         return getProviderFactory(clazz, provider.get(clazz));
-    }
-
-    @Override
-    public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id) {
-         return factoriesMap.get(clazz).get(id);
-    }
-
-    @Override
-    public List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz) {
-        List<ProviderFactory> list = new LinkedList<ProviderFactory>();
-        if (factoriesMap == null) return list;
-        Map<String, ProviderFactory> providerFactoryMap = factoriesMap.get(clazz);
-        if (providerFactoryMap == null) return list;
-        list.addAll(providerFactoryMap.values());
-        return list;
-    }
-
-    <T extends Provider> Set<String> getAllProviderIds(Class<T> clazz) {
-        Set<String> ids = new HashSet<String>();
-        for (ProviderFactory f : factoriesMap.get(clazz).values()) {
-            ids.add(f.getId());
-        }
-        return ids;
-    }
-
-    public void close() {
-        for (Map<String, ProviderFactory> factories : factoriesMap.values()) {
-            for (ProviderFactory factory : factories.values()) {
-                factory.close();
-            }
-        }
-    }
-
-    private boolean isInternal(ProviderFactory<?> factory) {
-        return factory.getClass().getPackage().getName().startsWith("org.keycloak");
-    }
-
-}
+package org.keycloak.services;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderEvent;
+import org.keycloak.provider.ProviderEventListener;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.ProviderManager;
+import org.keycloak.provider.Spi;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
+
+    private static final Logger log = Logger.getLogger(DefaultKeycloakSessionFactory.class);
+
+    private Map<Class<? extends Provider>, String> provider = new HashMap<Class<? extends Provider>, String>();
+    private Map<Class<? extends Provider>, Map<String, ProviderFactory>> factoriesMap = new HashMap<Class<? extends Provider>, Map<String, ProviderFactory>>();
+    protected CopyOnWriteArrayList<ProviderEventListener> listeners = new CopyOnWriteArrayList<ProviderEventListener>();
+
+    @Override
+    public void register(ProviderEventListener listener) {
+        listeners.add(listener);
+    }
+
+    @Override
+    public void unregister(ProviderEventListener listener) {
+        listeners.remove(listener);
+    }
+
+    @Override
+    public void publish(ProviderEvent event) {
+        for (ProviderEventListener listener : listeners) {
+            listener.onEvent(event);
+        }
+    }
+
+    public void init() {
+        ProviderManager pm = new ProviderManager(getClass().getClassLoader(), Config.scope().getArray("providers"));
+
+        for (Spi spi : ServiceLoader.load(Spi.class, getClass().getClassLoader())) {
+            Map<String, ProviderFactory> factories = new HashMap<String, ProviderFactory>();
+            factoriesMap.put(spi.getProviderClass(), factories);
+
+            String provider = Config.getProvider(spi.getName());
+            if (provider != null) {
+                this.provider.put(spi.getProviderClass(), provider);
+
+                ProviderFactory factory = pm.load(spi, provider);
+                if (factory == null) {
+                    throw new RuntimeException("Failed to find provider " + provider + " for " + spi.getName());
+                }
+
+                Config.Scope scope = Config.scope(spi.getName(), provider);
+                factory.init(scope);
+
+                if (spi.isInternal() && !isInternal(factory)) {
+                    log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
+                }
+
+                factories.put(factory.getId(), factory);
+
+                log.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
+            } else {
+                for (ProviderFactory factory : pm.load(spi)) {
+                    Config.Scope scope = Config.scope(spi.getName(), factory.getId());
+                    factory.init(scope);
+
+                    if (spi.isInternal() && !isInternal(factory)) {
+                        log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
+                    }
+
+                    factories.put(factory.getId(), factory);
+                }
+
+                if (factories.size() == 1) {
+                    provider = factories.values().iterator().next().getId();
+                    this.provider.put(spi.getProviderClass(), provider);
+
+                    log.debugv("Loaded SPI {0}  (provider = {1})", spi.getName(), provider);
+                } else {
+                    log.debugv("Loaded SPI {0} (providers = {1})", spi.getName(), factories.keySet());
+                }
+            }
+        }
+        for ( Map<String, ProviderFactory> factories : factoriesMap.values()) {
+            for (ProviderFactory factory : factories.values()) {
+                factory.postInit(this);
+            }
+        }
+    }
+
+    public KeycloakSession create() {
+        return new DefaultKeycloakSession(this);
+    }
+
+    <T extends Provider> String getDefaultProvider(Class<T> clazz) {
+        return provider.get(clazz);
+    }
+
+    @Override
+    public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz) {
+         return getProviderFactory(clazz, provider.get(clazz));
+    }
+
+    @Override
+    public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id) {
+         return factoriesMap.get(clazz).get(id);
+    }
+
+    @Override
+    public List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz) {
+        List<ProviderFactory> list = new LinkedList<ProviderFactory>();
+        if (factoriesMap == null) return list;
+        Map<String, ProviderFactory> providerFactoryMap = factoriesMap.get(clazz);
+        if (providerFactoryMap == null) return list;
+        list.addAll(providerFactoryMap.values());
+        return list;
+    }
+
+    <T extends Provider> Set<String> getAllProviderIds(Class<T> clazz) {
+        Set<String> ids = new HashSet<String>();
+        for (ProviderFactory f : factoriesMap.get(clazz).values()) {
+            ids.add(f.getId());
+        }
+        return ids;
+    }
+
+    public void close() {
+        for (Map<String, ProviderFactory> factories : factoriesMap.values()) {
+            for (ProviderFactory factory : factories.values()) {
+                factory.close();
+            }
+        }
+    }
+
+    private boolean isInternal(ProviderFactory<?> factory) {
+        return factory.getClass().getPackage().getName().startsWith("org.keycloak");
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
index e412c0d..c7c85fb 100755
--- a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
@@ -1,48 +1,48 @@
-package org.keycloak.services.filters;
-
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.ClientConnection;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Deprecated
-public class ClientConnectionFilter implements Filter {
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-    }
-
-    @Override
-    public void doFilter(final ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
-        ResteasyProviderFactory.pushContext(ClientConnection.class, new ClientConnection() {
-            @Override
-            public String getRemoteAddr() {
-                return request.getRemoteAddr();
-            }
-
-            @Override
-            public String getRemoteHost() {
-                return request.getRemoteHost();
-            }
-
-            @Override
-            public int getReportPort() {
-                return request.getRemotePort();
-            }
-        });
-        chain.doFilter(request, response);
-    }
-
-    @Override
-    public void destroy() {
-    }
-}
+package org.keycloak.services.filters;
+
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Deprecated
+public class ClientConnectionFilter implements Filter {
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        ResteasyProviderFactory.pushContext(ClientConnection.class, new ClientConnection() {
+            @Override
+            public String getRemoteAddr() {
+                return request.getRemoteAddr();
+            }
+
+            @Override
+            public String getRemoteHost() {
+                return request.getRemoteHost();
+            }
+
+            @Override
+            public int getReportPort() {
+                return request.getRemotePort();
+            }
+        });
+        chain.doFilter(request, response);
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index cfd482e..ae55eee 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -1,84 +1,84 @@
-package org.keycloak.services.filters;
-
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.ClientConnection;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakTransaction;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakSessionServletFilter implements Filter {
-
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-    }
-
-    @Override
-    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-        final HttpServletRequest request = (HttpServletRequest)servletRequest;
-
-        KeycloakSessionFactory sessionFactory = (KeycloakSessionFactory) servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
-        KeycloakSession session = sessionFactory.create();
-        ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
-        ClientConnection connection = new ClientConnection() {
-            @Override
-            public String getRemoteAddr() {
-                return request.getRemoteAddr();
-            }
-
-            @Override
-            public String getRemoteHost() {
-                return request.getRemoteHost();
-            }
-
-            @Override
-            public int getReportPort() {
-                return request.getRemotePort();
-            }
-        };
-        session.getContext().setConnection(connection);
-        ResteasyProviderFactory.pushContext(ClientConnection.class, connection);
-
-        KeycloakTransaction tx = session.getTransaction();
-        ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
-        tx.begin();
-
-        try {
-            filterChain.doFilter(servletRequest, servletResponse);
-            if (tx.isActive()) {
-                if (tx.getRollbackOnly()) tx.rollback();
-                else tx.commit();
-            }
-        } catch (IOException ex) {
-            if (tx.isActive()) tx.rollback();
-            throw ex;
-        } catch (ServletException ex) {
-            if (tx.isActive()) tx.rollback();
-            throw ex;
-        }
-        catch (RuntimeException ex) {
-            if (tx.isActive()) tx.rollback();
-            throw new RuntimeException("request path: " + request.getRequestURI(), ex);
-        } finally {
-            session.close();
-            ResteasyProviderFactory.clearContextData();
-        }
-
-    }
-
-    @Override
-    public void destroy() {
-    }
-}
+package org.keycloak.services.filters;
+
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakTransaction;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakSessionServletFilter implements Filter {
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        final HttpServletRequest request = (HttpServletRequest)servletRequest;
+
+        KeycloakSessionFactory sessionFactory = (KeycloakSessionFactory) servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
+        KeycloakSession session = sessionFactory.create();
+        ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
+        ClientConnection connection = new ClientConnection() {
+            @Override
+            public String getRemoteAddr() {
+                return request.getRemoteAddr();
+            }
+
+            @Override
+            public String getRemoteHost() {
+                return request.getRemoteHost();
+            }
+
+            @Override
+            public int getReportPort() {
+                return request.getRemotePort();
+            }
+        };
+        session.getContext().setConnection(connection);
+        ResteasyProviderFactory.pushContext(ClientConnection.class, connection);
+
+        KeycloakTransaction tx = session.getTransaction();
+        ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
+        tx.begin();
+
+        try {
+            filterChain.doFilter(servletRequest, servletResponse);
+            if (tx.isActive()) {
+                if (tx.getRollbackOnly()) tx.rollback();
+                else tx.commit();
+            }
+        } catch (IOException ex) {
+            if (tx.isActive()) tx.rollback();
+            throw ex;
+        } catch (ServletException ex) {
+            if (tx.isActive()) tx.rollback();
+            throw ex;
+        }
+        catch (RuntimeException ex) {
+            if (tx.isActive()) tx.rollback();
+            throw new RuntimeException("request path: " + request.getRequestURI(), ex);
+        } finally {
+            session.close();
+            ResteasyProviderFactory.clearContextData();
+        }
+
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/ForbiddenException.java b/services/src/main/java/org/keycloak/services/ForbiddenException.java
index 5e1365d..5c1fa5a 100755
--- a/services/src/main/java/org/keycloak/services/ForbiddenException.java
+++ b/services/src/main/java/org/keycloak/services/ForbiddenException.java
@@ -1,48 +1,48 @@
-package org.keycloak.services;
-
-import org.jboss.resteasy.spi.LoggableFailure;
-
-import javax.ws.rs.core.Response;
-
-/**
- * To provide a typed exception for Forbidden (This doesn't exist in Resteasy 2.3.7)
- */
-public class ForbiddenException extends LoggableFailure
-{
-   public ForbiddenException()
-   {
-      super(403);
-   }
-
-   public ForbiddenException(String s)
-   {
-      super(s, 403);
-   }
-
-   public ForbiddenException(String s, Response response)
-   {
-      super(s, response);
-   }
-
-   public ForbiddenException(String s, Throwable throwable, Response response)
-   {
-      super(s, throwable, response);
-   }
-
-   public ForbiddenException(String s, Throwable throwable)
-   {
-      super(s, throwable, 403);
-   }
-
-   public ForbiddenException(Throwable throwable)
-   {
-      super(throwable, 403);
-   }
-
-   public ForbiddenException(Throwable throwable, Response response)
-   {
-      super(throwable, response);
-   }
-
-
+package org.keycloak.services;
+
+import org.jboss.resteasy.spi.LoggableFailure;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * To provide a typed exception for Forbidden (This doesn't exist in Resteasy 2.3.7)
+ */
+public class ForbiddenException extends LoggableFailure
+{
+   public ForbiddenException()
+   {
+      super(403);
+   }
+
+   public ForbiddenException(String s)
+   {
+      super(s, 403);
+   }
+
+   public ForbiddenException(String s, Response response)
+   {
+      super(s, response);
+   }
+
+   public ForbiddenException(String s, Throwable throwable, Response response)
+   {
+      super(s, throwable, response);
+   }
+
+   public ForbiddenException(String s, Throwable throwable)
+   {
+      super(s, throwable, 403);
+   }
+
+   public ForbiddenException(Throwable throwable)
+   {
+      super(throwable, 403);
+   }
+
+   public ForbiddenException(Throwable throwable, Response response)
+   {
+      super(throwable, response);
+   }
+
+
 }
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/JspRequestParameters.java b/services/src/main/java/org/keycloak/services/JspRequestParameters.java
index 8a221c9..8800318 100755
--- a/services/src/main/java/org/keycloak/services/JspRequestParameters.java
+++ b/services/src/main/java/org/keycloak/services/JspRequestParameters.java
@@ -1,9 +1,9 @@
-package org.keycloak.services;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public interface JspRequestParameters {
-    public static final String KEYCLOAK_SECURITY_FAILURE_MESSAGE = "KEYCLOAK_SECURITY_FAILURE_MESSAGE";
-}
+package org.keycloak.services;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface JspRequestParameters {
+    public static final String KEYCLOAK_SECURITY_FAILURE_MESSAGE = "KEYCLOAK_SECURITY_FAILURE_MESSAGE";
+}
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 7510572..95b4243 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -1,84 +1,84 @@
-package org.keycloak.services.managers;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.representations.idm.CredentialRepresentation;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ApplianceBootstrap {
-
-    private static final Logger logger = Logger.getLogger(ApplianceBootstrap.class);
-
-    public void bootstrap(KeycloakSessionFactory sessionFactory, String contextPath) {
-        KeycloakSession session = sessionFactory.create();
-        session.getTransaction().begin();
-
-        try {
-            bootstrap(session, contextPath);
-            session.getTransaction().commit();
-        } finally {
-            session.close();
-        }
-    }
-
-    public void bootstrap(KeycloakSession session, String contextPath) {
-        String adminRealmName = Config.getAdminRealm();
-        if (session.realms().getRealm(adminRealmName) != null) {
-            return;
-        }
-
-        logger.info("Initializing " + adminRealmName + " realm");
-
-        RealmManager manager = new RealmManager(session);
-        manager.setContextPath(contextPath);
-        RealmModel realm = manager.createRealm(adminRealmName, adminRealmName);
-        realm.setName(adminRealmName);
-        realm.setEnabled(true);
-        realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
-        realm.setSsoSessionIdleTimeout(1800);
-        realm.setAccessTokenLifespan(60);
-        realm.setSsoSessionMaxLifespan(36000);
-        realm.setAccessCodeLifespan(60);
-        realm.setAccessCodeLifespanUserAction(300);
-        realm.setAccessCodeLifespanLogin(1800);
-        realm.setSslRequired(SslRequired.EXTERNAL);
-        realm.setRegistrationAllowed(false);
-        realm.setRegistrationEmailAsUsername(false);
-        KeycloakModelUtils.generateRealmKeys(realm);
-
-        UserModel adminUser = session.users().addUser(realm, "admin");
-        setupAdminUser(session, realm, adminUser, "admin");
-    }
-
-    public static void setupAdminUser(KeycloakSession session, RealmModel realm, UserModel adminUser, String password) {
-        adminUser.setEnabled(true);
-        UserCredentialModel usrCredModel = new UserCredentialModel();
-        usrCredModel.setType(UserCredentialModel.PASSWORD);
-        usrCredModel.setValue(password);
-        session.users().updateCredential(realm, adminUser, usrCredModel);
-        adminUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-
-        RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
-        adminUser.grantRole(adminRole);
-
-        ClientModel accountApp = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-        for (String r : accountApp.getDefaultRoles()) {
-            adminUser.grantRole(accountApp.getRole(r));
-        }
-    }
-
-}
+package org.keycloak.services.managers;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.CredentialRepresentation;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ApplianceBootstrap {
+
+    private static final Logger logger = Logger.getLogger(ApplianceBootstrap.class);
+
+    public void bootstrap(KeycloakSessionFactory sessionFactory, String contextPath) {
+        KeycloakSession session = sessionFactory.create();
+        session.getTransaction().begin();
+
+        try {
+            bootstrap(session, contextPath);
+            session.getTransaction().commit();
+        } finally {
+            session.close();
+        }
+    }
+
+    public void bootstrap(KeycloakSession session, String contextPath) {
+        String adminRealmName = Config.getAdminRealm();
+        if (session.realms().getRealm(adminRealmName) != null) {
+            return;
+        }
+
+        logger.info("Initializing " + adminRealmName + " realm");
+
+        RealmManager manager = new RealmManager(session);
+        manager.setContextPath(contextPath);
+        RealmModel realm = manager.createRealm(adminRealmName, adminRealmName);
+        realm.setName(adminRealmName);
+        realm.setEnabled(true);
+        realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
+        realm.setSsoSessionIdleTimeout(1800);
+        realm.setAccessTokenLifespan(60);
+        realm.setSsoSessionMaxLifespan(36000);
+        realm.setAccessCodeLifespan(60);
+        realm.setAccessCodeLifespanUserAction(300);
+        realm.setAccessCodeLifespanLogin(1800);
+        realm.setSslRequired(SslRequired.EXTERNAL);
+        realm.setRegistrationAllowed(false);
+        realm.setRegistrationEmailAsUsername(false);
+        KeycloakModelUtils.generateRealmKeys(realm);
+
+        UserModel adminUser = session.users().addUser(realm, "admin");
+        setupAdminUser(session, realm, adminUser, "admin");
+    }
+
+    public static void setupAdminUser(KeycloakSession session, RealmModel realm, UserModel adminUser, String password) {
+        adminUser.setEnabled(true);
+        UserCredentialModel usrCredModel = new UserCredentialModel();
+        usrCredModel.setType(UserCredentialModel.PASSWORD);
+        usrCredModel.setValue(password);
+        session.users().updateCredential(realm, adminUser, usrCredModel);
+        adminUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+
+        RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
+        adminUser.grantRole(adminRole);
+
+        ClientModel accountApp = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        for (String r : accountApp.getDefaultRoles()) {
+            adminUser.grantRole(accountApp.getRole(r));
+        }
+    }
+
+}
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 0bb41c1..eacb927 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -1,733 +1,733 @@
-package org.keycloak.services.managers;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.VerificationException;
-import org.keycloak.authentication.RequiredActionContext;
-import org.keycloak.authentication.RequiredActionFactory;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.broker.provider.IdentityProvider;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.RequiredActionProviderModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserModel.RequiredAction;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.resources.IdentityBrokerService;
-import org.keycloak.services.resources.LoginActionsService;
-import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.Urls;
-import org.keycloak.services.util.CookieHelper;
-import org.keycloak.services.validation.Validation;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.NewCookie;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.net.URI;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Stateless object that manages authentication
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AuthenticationManager {
-    protected static Logger logger = Logger.getLogger(AuthenticationManager.class);
-    public static final String FORM_USERNAME = "username";
-    // used for auth login
-    public static final String KEYCLOAK_IDENTITY_COOKIE = "KEYCLOAK_IDENTITY";
-    // used solely to determine is user is logged in
-    public static final String KEYCLOAK_SESSION_COOKIE = "KEYCLOAK_SESSION";
-    public static final String KEYCLOAK_REMEMBER_ME = "KEYCLOAK_REMEMBER_ME";
-    public static final String KEYCLOAK_LOGOUT_PROTOCOL = "KEYCLOAK_LOGOUT_PROTOCOL";
-
-    protected BruteForceProtector protector;
-
-    public AuthenticationManager() {
-    }
-
-    public AuthenticationManager(BruteForceProtector protector) {
-        this.protector = protector;
-    }
-
-    public BruteForceProtector getProtector() {
-        return protector;
-    }
-
-    public static boolean isSessionValid(RealmModel realm, UserSessionModel userSession) {
-        if (userSession == null) {
-            logger.debug("No user session");
-            return false;
-        }
-        int currentTime = Time.currentTime();
-        int max = userSession.getStarted() + realm.getSsoSessionMaxLifespan();
-        return userSession != null && userSession.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout() > currentTime && max > currentTime;
-    }
-
-    public static void expireUserSessionCookie(KeycloakSession session, UserSessionModel userSession, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, ClientConnection connection) {
-        try {
-            // check to see if any identity cookie is set with the same session and expire it if necessary
-            Cookie cookie = headers.getCookies().get(KEYCLOAK_IDENTITY_COOKIE);
-            if (cookie == null) return;
-            String tokenString = cookie.getValue();
-            AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), false);
-            UserSessionModel cookieSession = session.sessions().getUserSession(realm, token.getSessionState());
-            if (cookieSession == null || !cookieSession.getId().equals(userSession.getId())) return;
-            expireIdentityCookie(realm, uriInfo, connection);
-            expireRememberMeCookie(realm, uriInfo, connection);
-        } catch (Exception e) {
-        }
-
-    }
-
-    /**
-     * Do not logout broker
-     *
-     * @param session
-     * @param realm
-     * @param userSession
-     * @param uriInfo
-     * @param connection
-     * @param headers
-     */
-    public static void backchannelLogout(KeycloakSession session, RealmModel realm,
-                                         UserSessionModel userSession, UriInfo uriInfo,
-                                         ClientConnection connection, HttpHeaders headers,
-                                         boolean logoutBroker) {
-        if (userSession == null) return;
-        UserModel user = userSession.getUser();
-        userSession.setState(UserSessionModel.State.LOGGING_OUT);
-
-        logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
-        expireUserSessionCookie(session, userSession, realm, uriInfo, headers, connection);
-
-        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
-            backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
-        }
-        if (logoutBroker) {
-            String brokerId = userSession.getNote(IdentityBrokerService.BROKER_PROVIDER_ID);
-            if (brokerId != null) {
-                IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
-                try {
-                    identityProvider.backchannelLogout(userSession, uriInfo, realm);
-                } catch (Exception e) {
-                }
-            }
-        }
-        userSession.setState(UserSessionModel.State.LOGGED_OUT);
-        session.sessions().removeUserSession(realm, userSession);
-    }
-
-    public static void backchannelLogoutClientSession(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, UserSessionModel userSession, UriInfo uriInfo, HttpHeaders headers) {
-        ClientModel client = clientSession.getClient();
-        if (client instanceof ClientModel && !client.isFrontchannelLogout() && !ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) {
-            String authMethod = clientSession.getAuthMethod();
-            if (authMethod == null) return; // must be a keycloak service like account
-            LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
-            protocol.setRealm(realm)
-                    .setHttpHeaders(headers)
-                    .setUriInfo(uriInfo);
-            protocol.backchannelLogout(userSession, clientSession);
-            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-        }
-
-    }
-
-    // Logout all clientSessions of this user and client
-    public static void backchannelUserFromClient(KeycloakSession session, RealmModel realm, UserModel user, ClientModel client, UriInfo uriInfo, HttpHeaders headers) {
-        String clientId = client.getId();
-
-        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
-        for (UserSessionModel userSession : userSessions) {
-            List<ClientSessionModel> clientSessions = userSession.getClientSessions();
-            for (ClientSessionModel clientSession : clientSessions) {
-                if (clientSession.getClient().getId().equals(clientId)) {
-                    AuthenticationManager.backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
-                    TokenManager.dettachClientSession(session.sessions(), realm, clientSession);
-                }
-            }
-        }
-    }
-
-    public static Response browserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
-        if (userSession == null) return null;
-        UserModel user = userSession.getUser();
-
-        logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
-        if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
-            userSession.setState(UserSessionModel.State.LOGGING_OUT);
-        }
-        List<ClientSessionModel> redirectClients = new LinkedList<ClientSessionModel>();
-        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
-            ClientModel client = clientSession.getClient();
-            if (ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) continue;
-            if (client.isFrontchannelLogout()) {
-                String authMethod = clientSession.getAuthMethod();
-                if (authMethod == null) continue; // must be a keycloak service like account
-                redirectClients.add(clientSession);
-                continue;
-            }
-            if (client instanceof ClientModel && !client.isFrontchannelLogout()) {
-                String authMethod = clientSession.getAuthMethod();
-                if (authMethod == null) continue; // must be a keycloak service like account
-                LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
-                protocol.setRealm(realm)
-                        .setHttpHeaders(headers)
-                        .setUriInfo(uriInfo);
-                try {
-                    logger.debugv("backchannel logout to: {0}", client.getClientId());
-                    protocol.backchannelLogout(userSession, clientSession);
-                    clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-                } catch (Exception e) {
-                    logger.warn("Failed to logout client, continuing", e);
-                }
-            }
-        }
-
-        for (ClientSessionModel nextRedirectClient : redirectClients) {
-            String authMethod = nextRedirectClient.getAuthMethod();
-            LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
-            protocol.setRealm(realm)
-                    .setHttpHeaders(headers)
-                    .setUriInfo(uriInfo);
-            // setting this to logged out cuz I"m not sure protocols can always verify that the client was logged out or not
-            nextRedirectClient.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
-            try {
-                logger.debugv("frontchannel logout to: {0}", nextRedirectClient.getClient().getClientId());
-                Response response = protocol.frontchannelLogout(userSession, nextRedirectClient);
-                if (response != null) {
-                    logger.debug("returning frontchannel logout request to client");
-                    return response;
-                }
-            } catch (Exception e) {
-                logger.warn("Failed to logout client, continuing", e);
-            }
-
-        }
-        String brokerId = userSession.getNote(IdentityBrokerService.BROKER_PROVIDER_ID);
-        if (brokerId != null) {
-            IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
-            Response response = identityProvider.keycloakInitiatedBrowserLogout(userSession, uriInfo, realm);
-            if (response != null) return response;
-        }
-        return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
-    }
-
-    public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
-        expireIdentityCookie(realm, uriInfo, connection);
-        expireRememberMeCookie(realm, uriInfo, connection);
-        userSession.setState(UserSessionModel.State.LOGGED_OUT);
-        String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
-        EventBuilder event = new EventBuilder(realm, session, connection);
-        LoginProtocol protocol = session.getProvider(LoginProtocol.class, method);
-        protocol.setRealm(realm)
-                .setHttpHeaders(headers)
-                .setUriInfo(uriInfo)
-                .setEventBuilder(event);
-        Response response = protocol.finishLogout(userSession);
-        session.sessions().removeUserSession(realm, userSession);
-        return response;
-    }
-
-
-    public static AccessToken createIdentityToken(RealmModel realm, UserModel user, UserSessionModel session, String issuer) {
-        AccessToken token = new AccessToken();
-        token.id(KeycloakModelUtils.generateId());
-        token.issuedNow();
-        token.subject(user.getId());
-        token.issuer(issuer);
-        if (session != null) {
-            token.setSessionState(session.getId());
-        }
-        if (realm.getSsoSessionMaxLifespan() > 0) {
-            token.expiration(Time.currentTime() + realm.getSsoSessionMaxLifespan());
-        }
-        return token;
-    }
-
-    public static void createLoginCookie(RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, ClientConnection connection) {
-        String cookiePath = getIdentityCookiePath(realm, uriInfo);
-        String issuer = Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName());
-        AccessToken identityToken = createIdentityToken(realm, user, session, issuer);
-        String encoded = encodeToken(realm, identityToken);
-        boolean secureOnly = realm.getSslRequired().isRequired(connection);
-        int maxAge = NewCookie.DEFAULT_MAX_AGE;
-        if (session.isRememberMe()) {
-            maxAge = realm.getSsoSessionMaxLifespan();
-        }
-        logger.debugv("Create login cookie - name: {0}, path: {1}, max-age: {2}", KEYCLOAK_IDENTITY_COOKIE, cookiePath, maxAge);
-        CookieHelper.addCookie(KEYCLOAK_IDENTITY_COOKIE, encoded, cookiePath, null, null, maxAge, secureOnly, true);
-        //builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
-
-        String sessionCookieValue = realm.getName() + "/" + user.getId();
-        if (session != null) {
-            sessionCookieValue += "/" + session.getId();
-        }
-        // THIS SHOULD NOT BE A HTTPONLY COOKIE!  It is used for OpenID Connect Iframe Session support!
-        // Max age should be set to the max lifespan of the session as it's used to invalidate old-sessions on re-login
-        CookieHelper.addCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, realm.getSsoSessionMaxLifespan(), secureOnly, false);
-
-    }
-
-    public static void createRememberMeCookie(RealmModel realm, String username, UriInfo uriInfo, ClientConnection connection) {
-        String path = getIdentityCookiePath(realm, uriInfo);
-        boolean secureOnly = realm.getSslRequired().isRequired(connection);
-        // remember me cookie should be persistent (hardcoded to 365 days for now)
-        //NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
-        CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "username:" + username, path, null, null, 31536000, secureOnly, true);
-    }
-
-    public static String getRememberMeUsername(RealmModel realm, HttpHeaders headers) {
-        if (realm.isRememberMe()) {
-            Cookie cookie = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
-            if (cookie != null) {
-                String value = cookie.getValue();
-                String[] s = value.split(":");
-                if (s[0].equals("username") && s.length == 2) {
-                    return s[1];
-                }
-            }
-        }
-        return null;
-    }
-
-    protected static String encodeToken(RealmModel realm, Object token) {
-        String encodedToken = new JWSBuilder()
-                .jsonContent(token)
-                .rsa256(realm.getPrivateKey());
-        return encodedToken;
-    }
-
-    public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
-        logger.debug("Expiring identity cookie");
-        String path = getIdentityCookiePath(realm, uriInfo);
-        expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true, connection);
-        expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false, connection);
-    }
-    public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
-        logger.debug("Expiring remember me cookie");
-        String path = getIdentityCookiePath(realm, uriInfo);
-        String cookieName = KEYCLOAK_REMEMBER_ME;
-        expireCookie(realm, cookieName, path, true, connection);
-    }
-
-    protected static String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
-        return getRealmCookiePath(realm, uriInfo);
-    }
-
-    public static String getRealmCookiePath(RealmModel realm, UriInfo uriInfo) {
-        URI uri = RealmsResource.realmBaseUrl(uriInfo).build(realm.getName());
-        return uri.getRawPath();
-    }
-
-    public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly, ClientConnection connection) {
-        logger.debugv("Expiring cookie: {0} path: {1}", cookieName, path);
-        boolean secureOnly = realm.getSslRequired().isRequired(connection);;
-        CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly);
-    }
-
-    public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm) {
-        return authenticateIdentityCookie(session, realm, true);
-    }
-
-    public static AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, boolean checkActive) {
-        Cookie cookie = session.getContext().getRequestHeaders().getCookies().get(KEYCLOAK_IDENTITY_COOKIE);
-        if (cookie == null || "".equals(cookie.getValue())) {
-            logger.debugv("Could not find cookie: {0}", KEYCLOAK_IDENTITY_COOKIE);
-            return null;
-        }
-
-        String tokenString = cookie.getValue();
-        AuthResult authResult = verifyIdentityToken(session, realm, session.getContext().getUri(), session.getContext().getConnection(), checkActive, tokenString, session.getContext().getRequestHeaders());
-        if (authResult == null) {
-            expireIdentityCookie(realm, session.getContext().getUri(), session.getContext().getConnection());
-            return null;
-        }
-        authResult.getSession().setLastSessionRefresh(Time.currentTime());
-        return authResult;
-    }
-
-
-    public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
-                                                ClientSessionModel clientSession,
-                                                HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection) {
-        Cookie sessionCookie = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
-        if (sessionCookie != null) {
-
-            String[] split = sessionCookie.getValue().split("/");
-            if (split.length >= 3) {
-                String oldSessionId = split[2];
-                if (!oldSessionId.equals(userSession.getId())) {
-                    UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
-                    if (oldSession != null) {
-                        logger.debugv("Removing old user session: session: {0}", oldSessionId);
-                        session.sessions().removeUserSession(realm, oldSession);
-                    }
-                }
-            }
-        }
-        // refresh the cookies!
-        createLoginCookie(realm, userSession.getUser(), userSession, uriInfo, clientConnection);
-        if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
-        if (userSession.isRememberMe()) createRememberMeCookie(realm, userSession.getUser().getUsername(), uriInfo, clientConnection);
-        LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
-        protocol.setRealm(realm)
-                .setHttpHeaders(request.getHttpHeaders())
-                .setUriInfo(uriInfo);
-        return protocol.authenticated(userSession, new ClientSessionCode(realm, clientSession));
-
-    }
-
-    public static Response nextActionAfterAuthentication(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
-                                                  ClientConnection clientConnection,
-                                                  HttpRequest request, UriInfo uriInfo, EventBuilder event) {
-        Response requiredAction = actionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event);
-        if (requiredAction != null) return requiredAction;
-        event.success();
-        RealmModel realm = clientSession.getRealm();
-        return redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, clientConnection);
-
-    }
-
-    public static Response actionRequired(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession,
-                                                         final ClientConnection clientConnection,
-                                                         final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
-        final RealmModel realm = clientSession.getRealm();
-        final UserModel user = userSession.getUser();
-        final ClientModel client = clientSession.getClient();
-
-        RequiredActionContext context = new RequiredActionContext() {
-            @Override
-            public EventBuilder getEvent() {
-                return event;
-            }
-
-            @Override
-            public UserModel getUser() {
-                return user;
-            }
-
-            @Override
-            public RealmModel getRealm() {
-                return realm;
-            }
-
-            @Override
-            public ClientSessionModel getClientSession() {
-                return clientSession;
-            }
-
-            @Override
-            public UserSessionModel getUserSession() {
-                return userSession;
-            }
-
-            @Override
-            public ClientConnection getConnection() {
-                return clientConnection;
-            }
-
-            @Override
-            public UriInfo getUriInfo() {
-                return uriInfo;
-            }
-
-            @Override
-            public KeycloakSession getSession() {
-                return session;
-            }
-
-            @Override
-            public HttpRequest getHttpRequest() {
-                return request;
-            }
-
-            @Override
-            public String generateAccessCode(String action) {
-                ClientSessionCode code = new ClientSessionCode(getRealm(), getClientSession());
-                code.setAction(action);
-                return code.getCode();
-            }
-        };
-
-        // see if any required actions need triggering, i.e. an expired password
-        for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
-            if (!model.isEnabled()) continue;
-            RequiredActionProvider provider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
-            provider.evaluateTriggers(context);
-        }
-
-
-        logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
-
-        event.detail(Details.CODE_ID, clientSession.getId());
-
-        Set<String> requiredActions = user.getRequiredActions();
-        for (String action : requiredActions) {
-            RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(action);
-            RequiredActionProvider actionProvider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
-            Response challenge = actionProvider.invokeRequiredAction(context);
-            if (challenge != null) {
-                return challenge;
-            }
-
-        }
-        if (client.isConsentRequired()) {
-
-            UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
-
-            List<RoleModel> realmRoles = new LinkedList<>();
-            MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<>();
-            ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
-            for (RoleModel r : accessCode.getRequestedRoles()) {
-
-                // Consent already granted by user
-                if (grantedConsent != null && grantedConsent.isRoleGranted(r)) {
-                    continue;
-                }
-
-                if (r.getContainer() instanceof RealmModel) {
-                    realmRoles.add(r);
-                } else {
-                    resourceRoles.add(((ClientModel) r.getContainer()).getClientId(), r);
-                }
-            }
-
-            List<ProtocolMapperModel> protocolMappers = new LinkedList<>();
-            for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) {
-                if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) {
-                    if (grantedConsent == null || !grantedConsent.isProtocolMapperGranted(protocolMapper)) {
-                        protocolMappers.add(protocolMapper);
-                    }
-                }
-            }
-
-            // Skip grant screen if everything was already approved by this user
-            if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
-                accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT.name());
-
-                return session.getProvider(LoginFormsProvider.class)
-                        .setClientSessionCode(accessCode.getCode())
-                        .setAccessRequest(realmRoles, resourceRoles, protocolMappers)
-                        .createOAuthGrant(clientSession);
-            } else {
-                String consentDetail = (grantedConsent != null) ? Details.CONSENT_VALUE_PERSISTED_CONSENT : Details.CONSENT_VALUE_NO_CONSENT_REQUIRED;
-                event.detail(Details.CONSENT, consentDetail);
-            }
-        } else {
-            event.detail(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED);
-        }
-        return null;
-
-    }
-
-
-    protected static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString, HttpHeaders headers) {
-        try {
-            AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), checkActive);
-            if (checkActive) {
-                if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
-                    logger.debug("identity cookie expired");
-                    return null;
-                } else {
-                    logger.debugv("token active - active: {0}, issued-at: {1}, not-before: {2}", token.isActive(), token.getIssuedAt(), realm.getNotBefore());
-                }
-            }
-
-            UserModel user = session.users().getUserById(token.getSubject(), realm);
-            if (user == null || !user.isEnabled() ) {
-                logger.debug("Unknown user in identity token");
-                return null;
-            }
-
-            UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
-            if (!isSessionValid(realm, userSession)) {
-                if (userSession != null) backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
-                logger.debug("User session not active");
-                return null;
-            }
-
-            return new AuthResult(user, userSession, token);
-        } catch (VerificationException e) {
-            logger.debug("Failed to verify identity token", e);
-        }
-        return null;
-    }
-
-    public AuthenticationStatus authenticateForm(KeycloakSession session, ClientConnection clientConnection, RealmModel realm, MultivaluedMap<String, String> formData) {
-        String username = formData.getFirst(FORM_USERNAME);
-        if (username == null) {
-            logger.debug("Username not provided");
-            return AuthenticationStatus.INVALID_USER;
-        }
-
-        if (realm.isBruteForceProtected()) {
-            if (protector.isTemporarilyDisabled(session, realm, username)) {
-                return AuthenticationStatus.ACCOUNT_TEMPORARILY_DISABLED;
-            }
-        }
-
-        AuthenticationStatus status = authenticateInternal(session, realm, formData, username);
-        if (realm.isBruteForceProtected()) {
-            switch (status) {
-                case SUCCESS:
-                    protector.successfulLogin(realm, username, clientConnection);
-                    break;
-                case FAILED:
-                case MISSING_TOTP:
-                case MISSING_PASSWORD:
-                case INVALID_CREDENTIALS:
-                    protector.failedLogin(realm, username, clientConnection);
-                    break;
-                case INVALID_USER:
-                    protector.invalidUser(realm, username, clientConnection);
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        return status;
-    }
-
-    protected AuthenticationStatus authenticateInternal(KeycloakSession session, RealmModel realm, MultivaluedMap<String, String> formData, String username) {
-        UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username);
-
-        if (user == null) {
-            logger.debugv("User {0} not found", username);
-            return AuthenticationStatus.INVALID_USER;
-        }
-
-        Set<String> types = new HashSet<String>();
-
-        for (RequiredCredentialModel credential : realm.getRequiredCredentials()) {
-            types.add(credential.getType());
-        }
-
-        if (types.contains(CredentialRepresentation.PASSWORD)) {
-            List<UserCredentialModel> credentials = new LinkedList<UserCredentialModel>();
-
-            String password = formData.getFirst(CredentialRepresentation.PASSWORD);
-            if (password != null) {
-                credentials.add(UserCredentialModel.password(password));
-            }
-
-            String passwordToken = formData.getFirst(CredentialRepresentation.PASSWORD_TOKEN);
-            if (passwordToken != null) {
-                credentials.add(UserCredentialModel.passwordToken(passwordToken));
-            }
-
-            String totp = formData.getFirst(CredentialRepresentation.TOTP);
-            if (totp != null) {
-                credentials.add(UserCredentialModel.totp(totp));
-            }
-
-            if ((password == null || password.isEmpty()) && (passwordToken == null || passwordToken.isEmpty())) {
-                logger.debug("Password not provided");
-                return AuthenticationStatus.MISSING_PASSWORD;
-            }
-
-            logger.debugv("validating password for user: {0}", username);
-
-            if (!session.users().validCredentials(realm, user, credentials)) {
-                return AuthenticationStatus.INVALID_CREDENTIALS;
-            }
-
-            if (!user.isEnabled()) {
-                return AuthenticationStatus.ACCOUNT_DISABLED;
-            }
-
-            if (user.isTotp() && totp == null) {
-                return AuthenticationStatus.MISSING_TOTP;
-            }
-
-            if (!user.getRequiredActions().isEmpty()) {
-                return AuthenticationStatus.ACTIONS_REQUIRED;
-            } else {
-                return AuthenticationStatus.SUCCESS;
-            }
-        } else if (types.contains(CredentialRepresentation.SECRET)) {
-            String secret = formData.getFirst(CredentialRepresentation.SECRET);
-            if (secret == null) {
-                logger.debug("Secret not provided");
-                return AuthenticationStatus.MISSING_PASSWORD;
-            }
-            if (!session.users().validCredentials(realm, user, UserCredentialModel.secret(secret))) {
-                return AuthenticationStatus.INVALID_CREDENTIALS;
-            }
-            if (!user.isEnabled()) {
-                return AuthenticationStatus.ACCOUNT_DISABLED;
-            }
-            if (!user.getRequiredActions().isEmpty()) {
-                return AuthenticationStatus.ACTIONS_REQUIRED;
-            } else {
-                return AuthenticationStatus.SUCCESS;
-            }
-        } else {
-            logger.warn("Do not know how to authenticate user");
-            return AuthenticationStatus.FAILED;
-        }
-    }
-
-    public enum AuthenticationStatus {
-        SUCCESS, ACCOUNT_TEMPORARILY_DISABLED, ACCOUNT_DISABLED, ACTIONS_REQUIRED, INVALID_USER, INVALID_CREDENTIALS, MISSING_PASSWORD, MISSING_TOTP, FAILED
-    }
-
-    public static class AuthResult {
-        private final UserModel user;
-        private final UserSessionModel session;
-        private final AccessToken token;
-
-        public AuthResult(UserModel user, UserSessionModel session, AccessToken token) {
-            this.user = user;
-            this.session = session;
-            this.token = token;
-        }
-
-        public UserSessionModel getSession() {
-            return session;
-        }
-
-        public UserModel getUser() {
-            return user;
-        }
-
-        public AccessToken getToken() {
-            return token;
-        }
-    }
-
-}
+package org.keycloak.services.managers;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.authentication.RequiredActionContext;
+import org.keycloak.authentication.RequiredActionFactory;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.broker.provider.IdentityProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.resources.IdentityBrokerService;
+import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.services.Urls;
+import org.keycloak.services.util.CookieHelper;
+import org.keycloak.services.validation.Validation;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Stateless object that manages authentication
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AuthenticationManager {
+    protected static Logger logger = Logger.getLogger(AuthenticationManager.class);
+    public static final String FORM_USERNAME = "username";
+    // used for auth login
+    public static final String KEYCLOAK_IDENTITY_COOKIE = "KEYCLOAK_IDENTITY";
+    // used solely to determine is user is logged in
+    public static final String KEYCLOAK_SESSION_COOKIE = "KEYCLOAK_SESSION";
+    public static final String KEYCLOAK_REMEMBER_ME = "KEYCLOAK_REMEMBER_ME";
+    public static final String KEYCLOAK_LOGOUT_PROTOCOL = "KEYCLOAK_LOGOUT_PROTOCOL";
+
+    protected BruteForceProtector protector;
+
+    public AuthenticationManager() {
+    }
+
+    public AuthenticationManager(BruteForceProtector protector) {
+        this.protector = protector;
+    }
+
+    public BruteForceProtector getProtector() {
+        return protector;
+    }
+
+    public static boolean isSessionValid(RealmModel realm, UserSessionModel userSession) {
+        if (userSession == null) {
+            logger.debug("No user session");
+            return false;
+        }
+        int currentTime = Time.currentTime();
+        int max = userSession.getStarted() + realm.getSsoSessionMaxLifespan();
+        return userSession != null && userSession.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout() > currentTime && max > currentTime;
+    }
+
+    public static void expireUserSessionCookie(KeycloakSession session, UserSessionModel userSession, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, ClientConnection connection) {
+        try {
+            // check to see if any identity cookie is set with the same session and expire it if necessary
+            Cookie cookie = headers.getCookies().get(KEYCLOAK_IDENTITY_COOKIE);
+            if (cookie == null) return;
+            String tokenString = cookie.getValue();
+            AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), false);
+            UserSessionModel cookieSession = session.sessions().getUserSession(realm, token.getSessionState());
+            if (cookieSession == null || !cookieSession.getId().equals(userSession.getId())) return;
+            expireIdentityCookie(realm, uriInfo, connection);
+            expireRememberMeCookie(realm, uriInfo, connection);
+        } catch (Exception e) {
+        }
+
+    }
+
+    /**
+     * Do not logout broker
+     *
+     * @param session
+     * @param realm
+     * @param userSession
+     * @param uriInfo
+     * @param connection
+     * @param headers
+     */
+    public static void backchannelLogout(KeycloakSession session, RealmModel realm,
+                                         UserSessionModel userSession, UriInfo uriInfo,
+                                         ClientConnection connection, HttpHeaders headers,
+                                         boolean logoutBroker) {
+        if (userSession == null) return;
+        UserModel user = userSession.getUser();
+        userSession.setState(UserSessionModel.State.LOGGING_OUT);
+
+        logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
+        expireUserSessionCookie(session, userSession, realm, uriInfo, headers, connection);
+
+        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+            backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
+        }
+        if (logoutBroker) {
+            String brokerId = userSession.getNote(IdentityBrokerService.BROKER_PROVIDER_ID);
+            if (brokerId != null) {
+                IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
+                try {
+                    identityProvider.backchannelLogout(userSession, uriInfo, realm);
+                } catch (Exception e) {
+                }
+            }
+        }
+        userSession.setState(UserSessionModel.State.LOGGED_OUT);
+        session.sessions().removeUserSession(realm, userSession);
+    }
+
+    public static void backchannelLogoutClientSession(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, UserSessionModel userSession, UriInfo uriInfo, HttpHeaders headers) {
+        ClientModel client = clientSession.getClient();
+        if (client instanceof ClientModel && !client.isFrontchannelLogout() && !ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) {
+            String authMethod = clientSession.getAuthMethod();
+            if (authMethod == null) return; // must be a keycloak service like account
+            LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
+            protocol.setRealm(realm)
+                    .setHttpHeaders(headers)
+                    .setUriInfo(uriInfo);
+            protocol.backchannelLogout(userSession, clientSession);
+            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+        }
+
+    }
+
+    // Logout all clientSessions of this user and client
+    public static void backchannelUserFromClient(KeycloakSession session, RealmModel realm, UserModel user, ClientModel client, UriInfo uriInfo, HttpHeaders headers) {
+        String clientId = client.getId();
+
+        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
+        for (UserSessionModel userSession : userSessions) {
+            List<ClientSessionModel> clientSessions = userSession.getClientSessions();
+            for (ClientSessionModel clientSession : clientSessions) {
+                if (clientSession.getClient().getId().equals(clientId)) {
+                    AuthenticationManager.backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
+                    TokenManager.dettachClientSession(session.sessions(), realm, clientSession);
+                }
+            }
+        }
+    }
+
+    public static Response browserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
+        if (userSession == null) return null;
+        UserModel user = userSession.getUser();
+
+        logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
+        if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
+            userSession.setState(UserSessionModel.State.LOGGING_OUT);
+        }
+        List<ClientSessionModel> redirectClients = new LinkedList<ClientSessionModel>();
+        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+            ClientModel client = clientSession.getClient();
+            if (ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) continue;
+            if (client.isFrontchannelLogout()) {
+                String authMethod = clientSession.getAuthMethod();
+                if (authMethod == null) continue; // must be a keycloak service like account
+                redirectClients.add(clientSession);
+                continue;
+            }
+            if (client instanceof ClientModel && !client.isFrontchannelLogout()) {
+                String authMethod = clientSession.getAuthMethod();
+                if (authMethod == null) continue; // must be a keycloak service like account
+                LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
+                protocol.setRealm(realm)
+                        .setHttpHeaders(headers)
+                        .setUriInfo(uriInfo);
+                try {
+                    logger.debugv("backchannel logout to: {0}", client.getClientId());
+                    protocol.backchannelLogout(userSession, clientSession);
+                    clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+                } catch (Exception e) {
+                    logger.warn("Failed to logout client, continuing", e);
+                }
+            }
+        }
+
+        for (ClientSessionModel nextRedirectClient : redirectClients) {
+            String authMethod = nextRedirectClient.getAuthMethod();
+            LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
+            protocol.setRealm(realm)
+                    .setHttpHeaders(headers)
+                    .setUriInfo(uriInfo);
+            // setting this to logged out cuz I"m not sure protocols can always verify that the client was logged out or not
+            nextRedirectClient.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+            try {
+                logger.debugv("frontchannel logout to: {0}", nextRedirectClient.getClient().getClientId());
+                Response response = protocol.frontchannelLogout(userSession, nextRedirectClient);
+                if (response != null) {
+                    logger.debug("returning frontchannel logout request to client");
+                    return response;
+                }
+            } catch (Exception e) {
+                logger.warn("Failed to logout client, continuing", e);
+            }
+
+        }
+        String brokerId = userSession.getNote(IdentityBrokerService.BROKER_PROVIDER_ID);
+        if (brokerId != null) {
+            IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
+            Response response = identityProvider.keycloakInitiatedBrowserLogout(userSession, uriInfo, realm);
+            if (response != null) return response;
+        }
+        return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
+    }
+
+    public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
+        expireIdentityCookie(realm, uriInfo, connection);
+        expireRememberMeCookie(realm, uriInfo, connection);
+        userSession.setState(UserSessionModel.State.LOGGED_OUT);
+        String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
+        EventBuilder event = new EventBuilder(realm, session, connection);
+        LoginProtocol protocol = session.getProvider(LoginProtocol.class, method);
+        protocol.setRealm(realm)
+                .setHttpHeaders(headers)
+                .setUriInfo(uriInfo)
+                .setEventBuilder(event);
+        Response response = protocol.finishLogout(userSession);
+        session.sessions().removeUserSession(realm, userSession);
+        return response;
+    }
+
+
+    public static AccessToken createIdentityToken(RealmModel realm, UserModel user, UserSessionModel session, String issuer) {
+        AccessToken token = new AccessToken();
+        token.id(KeycloakModelUtils.generateId());
+        token.issuedNow();
+        token.subject(user.getId());
+        token.issuer(issuer);
+        if (session != null) {
+            token.setSessionState(session.getId());
+        }
+        if (realm.getSsoSessionMaxLifespan() > 0) {
+            token.expiration(Time.currentTime() + realm.getSsoSessionMaxLifespan());
+        }
+        return token;
+    }
+
+    public static void createLoginCookie(RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, ClientConnection connection) {
+        String cookiePath = getIdentityCookiePath(realm, uriInfo);
+        String issuer = Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName());
+        AccessToken identityToken = createIdentityToken(realm, user, session, issuer);
+        String encoded = encodeToken(realm, identityToken);
+        boolean secureOnly = realm.getSslRequired().isRequired(connection);
+        int maxAge = NewCookie.DEFAULT_MAX_AGE;
+        if (session.isRememberMe()) {
+            maxAge = realm.getSsoSessionMaxLifespan();
+        }
+        logger.debugv("Create login cookie - name: {0}, path: {1}, max-age: {2}", KEYCLOAK_IDENTITY_COOKIE, cookiePath, maxAge);
+        CookieHelper.addCookie(KEYCLOAK_IDENTITY_COOKIE, encoded, cookiePath, null, null, maxAge, secureOnly, true);
+        //builder.cookie(new NewCookie(cookieName, encoded, cookiePath, null, null, maxAge, secureOnly));// todo httponly , true);
+
+        String sessionCookieValue = realm.getName() + "/" + user.getId();
+        if (session != null) {
+            sessionCookieValue += "/" + session.getId();
+        }
+        // THIS SHOULD NOT BE A HTTPONLY COOKIE!  It is used for OpenID Connect Iframe Session support!
+        // Max age should be set to the max lifespan of the session as it's used to invalidate old-sessions on re-login
+        CookieHelper.addCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, realm.getSsoSessionMaxLifespan(), secureOnly, false);
+
+    }
+
+    public static void createRememberMeCookie(RealmModel realm, String username, UriInfo uriInfo, ClientConnection connection) {
+        String path = getIdentityCookiePath(realm, uriInfo);
+        boolean secureOnly = realm.getSslRequired().isRequired(connection);
+        // remember me cookie should be persistent (hardcoded to 365 days for now)
+        //NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true);
+        CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "username:" + username, path, null, null, 31536000, secureOnly, true);
+    }
+
+    public static String getRememberMeUsername(RealmModel realm, HttpHeaders headers) {
+        if (realm.isRememberMe()) {
+            Cookie cookie = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
+            if (cookie != null) {
+                String value = cookie.getValue();
+                String[] s = value.split(":");
+                if (s[0].equals("username") && s.length == 2) {
+                    return s[1];
+                }
+            }
+        }
+        return null;
+    }
+
+    protected static String encodeToken(RealmModel realm, Object token) {
+        String encodedToken = new JWSBuilder()
+                .jsonContent(token)
+                .rsa256(realm.getPrivateKey());
+        return encodedToken;
+    }
+
+    public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
+        logger.debug("Expiring identity cookie");
+        String path = getIdentityCookiePath(realm, uriInfo);
+        expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true, connection);
+        expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false, connection);
+    }
+    public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) {
+        logger.debug("Expiring remember me cookie");
+        String path = getIdentityCookiePath(realm, uriInfo);
+        String cookieName = KEYCLOAK_REMEMBER_ME;
+        expireCookie(realm, cookieName, path, true, connection);
+    }
+
+    protected static String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) {
+        return getRealmCookiePath(realm, uriInfo);
+    }
+
+    public static String getRealmCookiePath(RealmModel realm, UriInfo uriInfo) {
+        URI uri = RealmsResource.realmBaseUrl(uriInfo).build(realm.getName());
+        return uri.getRawPath();
+    }
+
+    public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly, ClientConnection connection) {
+        logger.debugv("Expiring cookie: {0} path: {1}", cookieName, path);
+        boolean secureOnly = realm.getSslRequired().isRequired(connection);;
+        CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly);
+    }
+
+    public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm) {
+        return authenticateIdentityCookie(session, realm, true);
+    }
+
+    public static AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, boolean checkActive) {
+        Cookie cookie = session.getContext().getRequestHeaders().getCookies().get(KEYCLOAK_IDENTITY_COOKIE);
+        if (cookie == null || "".equals(cookie.getValue())) {
+            logger.debugv("Could not find cookie: {0}", KEYCLOAK_IDENTITY_COOKIE);
+            return null;
+        }
+
+        String tokenString = cookie.getValue();
+        AuthResult authResult = verifyIdentityToken(session, realm, session.getContext().getUri(), session.getContext().getConnection(), checkActive, tokenString, session.getContext().getRequestHeaders());
+        if (authResult == null) {
+            expireIdentityCookie(realm, session.getContext().getUri(), session.getContext().getConnection());
+            return null;
+        }
+        authResult.getSession().setLastSessionRefresh(Time.currentTime());
+        return authResult;
+    }
+
+
+    public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
+                                                ClientSessionModel clientSession,
+                                                HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection) {
+        Cookie sessionCookie = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
+        if (sessionCookie != null) {
+
+            String[] split = sessionCookie.getValue().split("/");
+            if (split.length >= 3) {
+                String oldSessionId = split[2];
+                if (!oldSessionId.equals(userSession.getId())) {
+                    UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
+                    if (oldSession != null) {
+                        logger.debugv("Removing old user session: session: {0}", oldSessionId);
+                        session.sessions().removeUserSession(realm, oldSession);
+                    }
+                }
+            }
+        }
+        // refresh the cookies!
+        createLoginCookie(realm, userSession.getUser(), userSession, uriInfo, clientConnection);
+        if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
+        if (userSession.isRememberMe()) createRememberMeCookie(realm, userSession.getUser().getUsername(), uriInfo, clientConnection);
+        LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
+        protocol.setRealm(realm)
+                .setHttpHeaders(request.getHttpHeaders())
+                .setUriInfo(uriInfo);
+        return protocol.authenticated(userSession, new ClientSessionCode(realm, clientSession));
+
+    }
+
+    public static Response nextActionAfterAuthentication(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
+                                                  ClientConnection clientConnection,
+                                                  HttpRequest request, UriInfo uriInfo, EventBuilder event) {
+        Response requiredAction = actionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+        if (requiredAction != null) return requiredAction;
+        event.success();
+        RealmModel realm = clientSession.getRealm();
+        return redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, clientConnection);
+
+    }
+
+    public static Response actionRequired(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession,
+                                                         final ClientConnection clientConnection,
+                                                         final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
+        final RealmModel realm = clientSession.getRealm();
+        final UserModel user = userSession.getUser();
+        final ClientModel client = clientSession.getClient();
+
+        RequiredActionContext context = new RequiredActionContext() {
+            @Override
+            public EventBuilder getEvent() {
+                return event;
+            }
+
+            @Override
+            public UserModel getUser() {
+                return user;
+            }
+
+            @Override
+            public RealmModel getRealm() {
+                return realm;
+            }
+
+            @Override
+            public ClientSessionModel getClientSession() {
+                return clientSession;
+            }
+
+            @Override
+            public UserSessionModel getUserSession() {
+                return userSession;
+            }
+
+            @Override
+            public ClientConnection getConnection() {
+                return clientConnection;
+            }
+
+            @Override
+            public UriInfo getUriInfo() {
+                return uriInfo;
+            }
+
+            @Override
+            public KeycloakSession getSession() {
+                return session;
+            }
+
+            @Override
+            public HttpRequest getHttpRequest() {
+                return request;
+            }
+
+            @Override
+            public String generateAccessCode(String action) {
+                ClientSessionCode code = new ClientSessionCode(getRealm(), getClientSession());
+                code.setAction(action);
+                return code.getCode();
+            }
+        };
+
+        // see if any required actions need triggering, i.e. an expired password
+        for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
+            if (!model.isEnabled()) continue;
+            RequiredActionProvider provider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
+            provider.evaluateTriggers(context);
+        }
+
+
+        logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
+
+        event.detail(Details.CODE_ID, clientSession.getId());
+
+        Set<String> requiredActions = user.getRequiredActions();
+        for (String action : requiredActions) {
+            RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(action);
+            RequiredActionProvider actionProvider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
+            Response challenge = actionProvider.invokeRequiredAction(context);
+            if (challenge != null) {
+                return challenge;
+            }
+
+        }
+        if (client.isConsentRequired()) {
+
+            UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
+
+            List<RoleModel> realmRoles = new LinkedList<>();
+            MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<>();
+            ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
+            for (RoleModel r : accessCode.getRequestedRoles()) {
+
+                // Consent already granted by user
+                if (grantedConsent != null && grantedConsent.isRoleGranted(r)) {
+                    continue;
+                }
+
+                if (r.getContainer() instanceof RealmModel) {
+                    realmRoles.add(r);
+                } else {
+                    resourceRoles.add(((ClientModel) r.getContainer()).getClientId(), r);
+                }
+            }
+
+            List<ProtocolMapperModel> protocolMappers = new LinkedList<>();
+            for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) {
+                if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) {
+                    if (grantedConsent == null || !grantedConsent.isProtocolMapperGranted(protocolMapper)) {
+                        protocolMappers.add(protocolMapper);
+                    }
+                }
+            }
+
+            // Skip grant screen if everything was already approved by this user
+            if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
+                accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT.name());
+
+                return session.getProvider(LoginFormsProvider.class)
+                        .setClientSessionCode(accessCode.getCode())
+                        .setAccessRequest(realmRoles, resourceRoles, protocolMappers)
+                        .createOAuthGrant(clientSession);
+            } else {
+                String consentDetail = (grantedConsent != null) ? Details.CONSENT_VALUE_PERSISTED_CONSENT : Details.CONSENT_VALUE_NO_CONSENT_REQUIRED;
+                event.detail(Details.CONSENT, consentDetail);
+            }
+        } else {
+            event.detail(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED);
+        }
+        return null;
+
+    }
+
+
+    protected static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString, HttpHeaders headers) {
+        try {
+            AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), checkActive);
+            if (checkActive) {
+                if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
+                    logger.debug("identity cookie expired");
+                    return null;
+                } else {
+                    logger.debugv("token active - active: {0}, issued-at: {1}, not-before: {2}", token.isActive(), token.getIssuedAt(), realm.getNotBefore());
+                }
+            }
+
+            UserModel user = session.users().getUserById(token.getSubject(), realm);
+            if (user == null || !user.isEnabled() ) {
+                logger.debug("Unknown user in identity token");
+                return null;
+            }
+
+            UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
+            if (!isSessionValid(realm, userSession)) {
+                if (userSession != null) backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
+                logger.debug("User session not active");
+                return null;
+            }
+
+            return new AuthResult(user, userSession, token);
+        } catch (VerificationException e) {
+            logger.debug("Failed to verify identity token", e);
+        }
+        return null;
+    }
+
+    public AuthenticationStatus authenticateForm(KeycloakSession session, ClientConnection clientConnection, RealmModel realm, MultivaluedMap<String, String> formData) {
+        String username = formData.getFirst(FORM_USERNAME);
+        if (username == null) {
+            logger.debug("Username not provided");
+            return AuthenticationStatus.INVALID_USER;
+        }
+
+        if (realm.isBruteForceProtected()) {
+            if (protector.isTemporarilyDisabled(session, realm, username)) {
+                return AuthenticationStatus.ACCOUNT_TEMPORARILY_DISABLED;
+            }
+        }
+
+        AuthenticationStatus status = authenticateInternal(session, realm, formData, username);
+        if (realm.isBruteForceProtected()) {
+            switch (status) {
+                case SUCCESS:
+                    protector.successfulLogin(realm, username, clientConnection);
+                    break;
+                case FAILED:
+                case MISSING_TOTP:
+                case MISSING_PASSWORD:
+                case INVALID_CREDENTIALS:
+                    protector.failedLogin(realm, username, clientConnection);
+                    break;
+                case INVALID_USER:
+                    protector.invalidUser(realm, username, clientConnection);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        return status;
+    }
+
+    protected AuthenticationStatus authenticateInternal(KeycloakSession session, RealmModel realm, MultivaluedMap<String, String> formData, String username) {
+        UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username);
+
+        if (user == null) {
+            logger.debugv("User {0} not found", username);
+            return AuthenticationStatus.INVALID_USER;
+        }
+
+        Set<String> types = new HashSet<String>();
+
+        for (RequiredCredentialModel credential : realm.getRequiredCredentials()) {
+            types.add(credential.getType());
+        }
+
+        if (types.contains(CredentialRepresentation.PASSWORD)) {
+            List<UserCredentialModel> credentials = new LinkedList<UserCredentialModel>();
+
+            String password = formData.getFirst(CredentialRepresentation.PASSWORD);
+            if (password != null) {
+                credentials.add(UserCredentialModel.password(password));
+            }
+
+            String passwordToken = formData.getFirst(CredentialRepresentation.PASSWORD_TOKEN);
+            if (passwordToken != null) {
+                credentials.add(UserCredentialModel.passwordToken(passwordToken));
+            }
+
+            String totp = formData.getFirst(CredentialRepresentation.TOTP);
+            if (totp != null) {
+                credentials.add(UserCredentialModel.totp(totp));
+            }
+
+            if ((password == null || password.isEmpty()) && (passwordToken == null || passwordToken.isEmpty())) {
+                logger.debug("Password not provided");
+                return AuthenticationStatus.MISSING_PASSWORD;
+            }
+
+            logger.debugv("validating password for user: {0}", username);
+
+            if (!session.users().validCredentials(realm, user, credentials)) {
+                return AuthenticationStatus.INVALID_CREDENTIALS;
+            }
+
+            if (!user.isEnabled()) {
+                return AuthenticationStatus.ACCOUNT_DISABLED;
+            }
+
+            if (user.isTotp() && totp == null) {
+                return AuthenticationStatus.MISSING_TOTP;
+            }
+
+            if (!user.getRequiredActions().isEmpty()) {
+                return AuthenticationStatus.ACTIONS_REQUIRED;
+            } else {
+                return AuthenticationStatus.SUCCESS;
+            }
+        } else if (types.contains(CredentialRepresentation.SECRET)) {
+            String secret = formData.getFirst(CredentialRepresentation.SECRET);
+            if (secret == null) {
+                logger.debug("Secret not provided");
+                return AuthenticationStatus.MISSING_PASSWORD;
+            }
+            if (!session.users().validCredentials(realm, user, UserCredentialModel.secret(secret))) {
+                return AuthenticationStatus.INVALID_CREDENTIALS;
+            }
+            if (!user.isEnabled()) {
+                return AuthenticationStatus.ACCOUNT_DISABLED;
+            }
+            if (!user.getRequiredActions().isEmpty()) {
+                return AuthenticationStatus.ACTIONS_REQUIRED;
+            } else {
+                return AuthenticationStatus.SUCCESS;
+            }
+        } else {
+            logger.warn("Do not know how to authenticate user");
+            return AuthenticationStatus.FAILED;
+        }
+    }
+
+    public enum AuthenticationStatus {
+        SUCCESS, ACCOUNT_TEMPORARILY_DISABLED, ACCOUNT_DISABLED, ACTIONS_REQUIRED, INVALID_USER, INVALID_CREDENTIALS, MISSING_PASSWORD, MISSING_TOTP, FAILED
+    }
+
+    public static class AuthResult {
+        private final UserModel user;
+        private final UserSessionModel session;
+        private final AccessToken token;
+
+        public AuthResult(UserModel user, UserSessionModel session, AccessToken token) {
+            this.user = user;
+            this.session = session;
+            this.token = token;
+        }
+
+        public UserSessionModel getSession() {
+            return session;
+        }
+
+        public UserModel getUser() {
+            return user;
+        }
+
+        public AccessToken getToken() {
+            return token;
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
index aa202e7..75e12c2 100755
--- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
@@ -1,263 +1,263 @@
-package org.keycloak.services.managers;
-
-
-import org.jboss.logging.Logger;
-import org.keycloak.ClientConnection;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UsernameLoginFailureModel;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A single thread will log failures.  This is so that we can avoid concurrent writes as we want an accurate failure count
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class BruteForceProtector implements Runnable {
-    protected static Logger logger = Logger.getLogger(BruteForceProtector.class);
-
-    protected volatile boolean run = true;
-    protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
-    protected KeycloakSessionFactory factory;
-    protected CountDownLatch shutdownLatch = new CountDownLatch(1);
-
-    protected volatile long failures;
-    protected volatile long lastFailure;
-    protected volatile long totalTime;
-
-    protected LinkedBlockingQueue<LoginEvent> queue = new LinkedBlockingQueue<LoginEvent>();
-    public static final int TRANSACTION_SIZE = 20;
-
-
-    protected abstract class LoginEvent implements Comparable<LoginEvent> {
-        protected final String realmId;
-        protected final String username;
-        protected final String ip;
-
-        protected LoginEvent(String realmId, String username, String ip) {
-            this.realmId = realmId;
-            this.username = username;
-            this.ip = ip;
-        }
-
-        @Override
-        public int compareTo(LoginEvent o) {
-            return username.compareTo(o.username);
-        }
-    }
-
-    protected class SuccessfulLogin extends LoginEvent {
-        public SuccessfulLogin(String realmId, String userId, String ip) {
-            super(realmId, userId, ip);
-        }
-    }
-
-    protected class ShutdownEvent extends LoginEvent {
-        public ShutdownEvent() {
-            super(null, null, null);
-        }
-    }
-
-    protected class FailedLogin extends LoginEvent {
-        protected final CountDownLatch latch = new CountDownLatch(1);
-
-        public FailedLogin(String realmId, String username, String ip) {
-            super(realmId, username, ip);
-        }
-    }
-
-    public BruteForceProtector(KeycloakSessionFactory factory) {
-        this.factory = factory;
-    }
-
-    public void failure(KeycloakSession session, LoginEvent event) {
-        logger.debug("failure");
-        RealmModel realm = getRealmModel(session, event);
-        logFailure(event);
-        UsernameLoginFailureModel user = getUserModel(session, event);
-        if (user == null) {
-            user = session.sessions().addUserLoginFailure(realm, event.username);
-        }
-        user.setLastIPFailure(event.ip);
-        long currentTime = System.currentTimeMillis();
-        long last = user.getLastFailure();
-        long deltaTime = 0;
-        if (last > 0) {
-            deltaTime = currentTime - last;
-        }
-        user.setLastFailure(currentTime);
-        if (deltaTime > 0) {
-            // if last failure was more than MAX_DELTA clear failures
-            if (deltaTime > (long)realm.getMaxDeltaTimeSeconds() *1000L) {
-                user.clearFailures();
-            }
-        }
-        user.incrementFailures();
-        logger.debugv("new num failures: {0}" , user.getNumFailures());
-
-        int waitSeconds = realm.getWaitIncrementSeconds() * (user.getNumFailures() / realm.getFailureFactor());
-        logger.debugv("waitSeconds: {0}", waitSeconds);
-        logger.debugv("deltaTime: {0}", deltaTime);
-        if (waitSeconds == 0) {
-            if (last > 0 && deltaTime < realm.getQuickLoginCheckMilliSeconds()) {
-                logger.debugv("quick login, set min wait seconds");
-                waitSeconds = realm.getMinimumQuickLoginWaitSeconds();
-            }
-        }
-        if (waitSeconds > 0) {
-            waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
-            int notBefore = (int) (currentTime / 1000) + waitSeconds;
-            logger.debugv("set notBefore: {0}", notBefore);
-            user.setFailedLoginNotBefore(notBefore);
-        }
-    }
-
-    protected UsernameLoginFailureModel getUserModel(KeycloakSession session, LoginEvent event) {
-        RealmModel realm = getRealmModel(session, event);
-        if (realm == null) return null;
-        UsernameLoginFailureModel user = session.sessions().getUserLoginFailure(realm, event.username);
-        if (user == null) return null;
-        return user;
-    }
-
-    protected RealmModel getRealmModel(KeycloakSession session, LoginEvent event) {
-        RealmModel realm = session.realms().getRealm(event.realmId);
-        if (realm == null) return null;
-        return realm;
-    }
-
-    public void start() {
-        new Thread(this, "Brute Force Protector").start();
-    }
-
-    public void shutdown() {
-        run = false;
-        try {
-            queue.offer(new ShutdownEvent());
-            shutdownLatch.await(10, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    public void run() {
-        final ArrayList<LoginEvent> events = new ArrayList<LoginEvent>(TRANSACTION_SIZE + 1);
-        try {
-            while (run) {
-                try {
-                    LoginEvent take = queue.poll(2, TimeUnit.SECONDS);
-                    if (take == null) {
-                        continue;
-                    }
-                    try {
-                        events.add(take);
-                        queue.drainTo(events, TRANSACTION_SIZE);
-                        Collections.sort(events); // we sort to avoid deadlock due to ordered updates.  Maybe I'm overthinking this.
-                        KeycloakSession session = factory.create();
-                        session.getTransaction().begin();
-                        try {
-                            for (LoginEvent event : events) {
-                                if (event instanceof FailedLogin) {
-                                    failure(session, event);
-                                } else if (event instanceof ShutdownEvent) {
-                                    run = false;
-                                }
-                            }
-                            session.getTransaction().commit();
-                        } catch (Exception e) {
-                            session.getTransaction().rollback();
-                            throw e;
-                        } finally {
-                            for (LoginEvent event : events) {
-                                if (event instanceof FailedLogin) {
-                                    ((FailedLogin) event).latch.countDown();
-                                }
-                            }
-                            events.clear();
-                            session.close();
-                        }
-                    } catch (Exception e) {
-                        logger.error("Failed processing type", e);
-                    }
-                } catch (InterruptedException e) {
-                    break;
-                }
-            }
-        } finally {
-            shutdownLatch.countDown();
-        }
-    }
-
-    protected void logSuccess(LoginEvent event) {
-        logger.warn("login success for user " + event.username + " from ip " + event.ip);
-    }
-
-    protected void logFailure(LoginEvent event) {
-        logger.warn("login failure for user " + event.username + " from ip " + event.ip);
-        failures++;
-        long delta = 0;
-        if (lastFailure > 0) {
-            delta = System.currentTimeMillis() - lastFailure;
-            if (delta > (long)maxDeltaTimeSeconds * 1000L) {
-                totalTime = 0;
-
-            } else {
-                totalTime += delta;
-            }
-        }
-    }
-
-    public void successfulLogin(RealmModel realm, String username, ClientConnection clientConnection) {
-        logger.info("successful login user: " + username + " from ip " + clientConnection.getRemoteAddr());
-    }
-
-    public void invalidUser(RealmModel realm, String username, ClientConnection clientConnection) {
-        logger.warn("invalid user: " + username + " from ip " + clientConnection.getRemoteAddr());
-        // todo more?
-    }
-
-    public void failedLogin(RealmModel realm, String username, ClientConnection clientConnection) {
-        try {
-            FailedLogin event = new FailedLogin(realm.getId(), username, clientConnection.getRemoteAddr());
-            queue.offer(event);
-            // wait a minimum of seconds for type to process so that a hacker
-            // cannot flood with failed logins and overwhelm the queue and not have notBefore updated to block next requests
-            // todo failure HTTP responses should be queued via async HTTP
-            event.latch.await(5, TimeUnit.SECONDS);
-
-        } catch (InterruptedException e) {
-        }
-    }
-
-    public boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username) {
-        UsernameLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, username);
-        if (failure == null) {
-            return false;
-        }
-
-        int currTime = (int)(System.currentTimeMillis()/1000);
-        if (currTime < failure.getFailedLoginNotBefore()) {
-            logger.debugv("Current: {0} notBefore: {1}", currTime , failure.getFailedLoginNotBefore());
-            return true;
-        }
-        return false;
-    }
-
-    public long getFailures() {
-        return failures;
-    }
-
-    public long getLastFailure() {
-        return lastFailure;
-    }
-
-
-}
+package org.keycloak.services.managers;
+
+
+import org.jboss.logging.Logger;
+import org.keycloak.ClientConnection;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UsernameLoginFailureModel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A single thread will log failures.  This is so that we can avoid concurrent writes as we want an accurate failure count
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class BruteForceProtector implements Runnable {
+    protected static Logger logger = Logger.getLogger(BruteForceProtector.class);
+
+    protected volatile boolean run = true;
+    protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
+    protected KeycloakSessionFactory factory;
+    protected CountDownLatch shutdownLatch = new CountDownLatch(1);
+
+    protected volatile long failures;
+    protected volatile long lastFailure;
+    protected volatile long totalTime;
+
+    protected LinkedBlockingQueue<LoginEvent> queue = new LinkedBlockingQueue<LoginEvent>();
+    public static final int TRANSACTION_SIZE = 20;
+
+
+    protected abstract class LoginEvent implements Comparable<LoginEvent> {
+        protected final String realmId;
+        protected final String username;
+        protected final String ip;
+
+        protected LoginEvent(String realmId, String username, String ip) {
+            this.realmId = realmId;
+            this.username = username;
+            this.ip = ip;
+        }
+
+        @Override
+        public int compareTo(LoginEvent o) {
+            return username.compareTo(o.username);
+        }
+    }
+
+    protected class SuccessfulLogin extends LoginEvent {
+        public SuccessfulLogin(String realmId, String userId, String ip) {
+            super(realmId, userId, ip);
+        }
+    }
+
+    protected class ShutdownEvent extends LoginEvent {
+        public ShutdownEvent() {
+            super(null, null, null);
+        }
+    }
+
+    protected class FailedLogin extends LoginEvent {
+        protected final CountDownLatch latch = new CountDownLatch(1);
+
+        public FailedLogin(String realmId, String username, String ip) {
+            super(realmId, username, ip);
+        }
+    }
+
+    public BruteForceProtector(KeycloakSessionFactory factory) {
+        this.factory = factory;
+    }
+
+    public void failure(KeycloakSession session, LoginEvent event) {
+        logger.debug("failure");
+        RealmModel realm = getRealmModel(session, event);
+        logFailure(event);
+        UsernameLoginFailureModel user = getUserModel(session, event);
+        if (user == null) {
+            user = session.sessions().addUserLoginFailure(realm, event.username);
+        }
+        user.setLastIPFailure(event.ip);
+        long currentTime = System.currentTimeMillis();
+        long last = user.getLastFailure();
+        long deltaTime = 0;
+        if (last > 0) {
+            deltaTime = currentTime - last;
+        }
+        user.setLastFailure(currentTime);
+        if (deltaTime > 0) {
+            // if last failure was more than MAX_DELTA clear failures
+            if (deltaTime > (long)realm.getMaxDeltaTimeSeconds() *1000L) {
+                user.clearFailures();
+            }
+        }
+        user.incrementFailures();
+        logger.debugv("new num failures: {0}" , user.getNumFailures());
+
+        int waitSeconds = realm.getWaitIncrementSeconds() * (user.getNumFailures() / realm.getFailureFactor());
+        logger.debugv("waitSeconds: {0}", waitSeconds);
+        logger.debugv("deltaTime: {0}", deltaTime);
+        if (waitSeconds == 0) {
+            if (last > 0 && deltaTime < realm.getQuickLoginCheckMilliSeconds()) {
+                logger.debugv("quick login, set min wait seconds");
+                waitSeconds = realm.getMinimumQuickLoginWaitSeconds();
+            }
+        }
+        if (waitSeconds > 0) {
+            waitSeconds = Math.min(realm.getMaxFailureWaitSeconds(), waitSeconds);
+            int notBefore = (int) (currentTime / 1000) + waitSeconds;
+            logger.debugv("set notBefore: {0}", notBefore);
+            user.setFailedLoginNotBefore(notBefore);
+        }
+    }
+
+    protected UsernameLoginFailureModel getUserModel(KeycloakSession session, LoginEvent event) {
+        RealmModel realm = getRealmModel(session, event);
+        if (realm == null) return null;
+        UsernameLoginFailureModel user = session.sessions().getUserLoginFailure(realm, event.username);
+        if (user == null) return null;
+        return user;
+    }
+
+    protected RealmModel getRealmModel(KeycloakSession session, LoginEvent event) {
+        RealmModel realm = session.realms().getRealm(event.realmId);
+        if (realm == null) return null;
+        return realm;
+    }
+
+    public void start() {
+        new Thread(this, "Brute Force Protector").start();
+    }
+
+    public void shutdown() {
+        run = false;
+        try {
+            queue.offer(new ShutdownEvent());
+            shutdownLatch.await(10, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    public void run() {
+        final ArrayList<LoginEvent> events = new ArrayList<LoginEvent>(TRANSACTION_SIZE + 1);
+        try {
+            while (run) {
+                try {
+                    LoginEvent take = queue.poll(2, TimeUnit.SECONDS);
+                    if (take == null) {
+                        continue;
+                    }
+                    try {
+                        events.add(take);
+                        queue.drainTo(events, TRANSACTION_SIZE);
+                        Collections.sort(events); // we sort to avoid deadlock due to ordered updates.  Maybe I'm overthinking this.
+                        KeycloakSession session = factory.create();
+                        session.getTransaction().begin();
+                        try {
+                            for (LoginEvent event : events) {
+                                if (event instanceof FailedLogin) {
+                                    failure(session, event);
+                                } else if (event instanceof ShutdownEvent) {
+                                    run = false;
+                                }
+                            }
+                            session.getTransaction().commit();
+                        } catch (Exception e) {
+                            session.getTransaction().rollback();
+                            throw e;
+                        } finally {
+                            for (LoginEvent event : events) {
+                                if (event instanceof FailedLogin) {
+                                    ((FailedLogin) event).latch.countDown();
+                                }
+                            }
+                            events.clear();
+                            session.close();
+                        }
+                    } catch (Exception e) {
+                        logger.error("Failed processing type", e);
+                    }
+                } catch (InterruptedException e) {
+                    break;
+                }
+            }
+        } finally {
+            shutdownLatch.countDown();
+        }
+    }
+
+    protected void logSuccess(LoginEvent event) {
+        logger.warn("login success for user " + event.username + " from ip " + event.ip);
+    }
+
+    protected void logFailure(LoginEvent event) {
+        logger.warn("login failure for user " + event.username + " from ip " + event.ip);
+        failures++;
+        long delta = 0;
+        if (lastFailure > 0) {
+            delta = System.currentTimeMillis() - lastFailure;
+            if (delta > (long)maxDeltaTimeSeconds * 1000L) {
+                totalTime = 0;
+
+            } else {
+                totalTime += delta;
+            }
+        }
+    }
+
+    public void successfulLogin(RealmModel realm, String username, ClientConnection clientConnection) {
+        logger.info("successful login user: " + username + " from ip " + clientConnection.getRemoteAddr());
+    }
+
+    public void invalidUser(RealmModel realm, String username, ClientConnection clientConnection) {
+        logger.warn("invalid user: " + username + " from ip " + clientConnection.getRemoteAddr());
+        // todo more?
+    }
+
+    public void failedLogin(RealmModel realm, String username, ClientConnection clientConnection) {
+        try {
+            FailedLogin event = new FailedLogin(realm.getId(), username, clientConnection.getRemoteAddr());
+            queue.offer(event);
+            // wait a minimum of seconds for type to process so that a hacker
+            // cannot flood with failed logins and overwhelm the queue and not have notBefore updated to block next requests
+            // todo failure HTTP responses should be queued via async HTTP
+            event.latch.await(5, TimeUnit.SECONDS);
+
+        } catch (InterruptedException e) {
+        }
+    }
+
+    public boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username) {
+        UsernameLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, username);
+        if (failure == null) {
+            return false;
+        }
+
+        int currTime = (int)(System.currentTimeMillis()/1000);
+        if (currTime < failure.getFailedLoginNotBefore()) {
+            logger.debugv("Current: {0} notBefore: {1}", currTime , failure.getFailedLoginNotBefore());
+            return true;
+        }
+        return false;
+    }
+
+    public long getFailures() {
+        return failures;
+    }
+
+    public long getLastFailure() {
+        return lastFailure;
+    }
+
+
+}
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 9e16fe9..40f7a32 100755
--- a/services/src/main/java/org/keycloak/services/managers/ClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
@@ -1,192 +1,192 @@
-package org.keycloak.services.managers;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonPropertyOrder;
-import org.jboss.logging.Logger;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.representations.adapters.config.BaseRealmConfig;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.util.Time;
-
-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 java.util.Set;
-import java.util.TreeSet;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientManager {
-    protected Logger logger = Logger.getLogger(ClientManager.class);
-
-    protected RealmManager realmManager;
-
-    public ClientManager(RealmManager realmManager) {
-        this.realmManager = realmManager;
-    }
-
-    public ClientManager() {
-    }
-
-    public ClientModel createClient(RealmModel realm, String name) {
-        return KeycloakModelUtils.createClient(realm, name);
-    }
-
-    public boolean removeClient(RealmModel realm, ClientModel client) {
-        if (realm.removeClient(client.getId())) {
-            UserSessionProvider sessions = realmManager.getSession().sessions();
-            if (sessions != null) {
-                sessions.onClientRemoved(realm, client);
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public Set<String> validateRegisteredNodes(ClientModel client) {
-        Map<String, Integer> registeredNodes = client.getRegisteredNodes();
-        if (registeredNodes == null || registeredNodes.isEmpty()) {
-            return Collections.emptySet();
-        }
-
-        int currentTime = Time.currentTime();
-
-        Set<String> validatedNodes = new TreeSet<String>();
-        if (client.getNodeReRegistrationTimeout() > 0) {
-            List<String> toRemove = new LinkedList<String>();
-            for (Map.Entry<String, Integer> entry : registeredNodes.entrySet()) {
-                Integer lastReRegistration = entry.getValue();
-                if (lastReRegistration + client.getNodeReRegistrationTimeout() < currentTime) {
-                    toRemove.add(entry.getKey());
-                } else {
-                    validatedNodes.add(entry.getKey());
-                }
-            }
-
-            // Remove time-outed nodes
-            for (String node : toRemove) {
-                client.unregisterNode(node);
-            }
-        } else {
-            // Periodic node reRegistration is disabled, so allow all nodes
-            validatedNodes.addAll(registeredNodes.keySet());
-        }
-
-        return validatedNodes;
-    }
-
-    @JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-required",
-            "resource", "public-client", "credentials",
-            "use-resource-role-mappings"})
-    public static class InstallationAdapterConfig extends BaseRealmConfig {
-        @JsonProperty("resource")
-        protected String resource;
-        @JsonProperty("use-resource-role-mappings")
-        protected Boolean useResourceRoleMappings;
-        @JsonProperty("bearer-only")
-        protected Boolean bearerOnly;
-        @JsonProperty("public-client")
-        protected Boolean publicClient;
-        @JsonProperty("credentials")
-        protected Map<String, String> credentials;
-
-        public Boolean isUseResourceRoleMappings() {
-            return useResourceRoleMappings;
-        }
-
-        public void setUseResourceRoleMappings(Boolean useResourceRoleMappings) {
-            this.useResourceRoleMappings = useResourceRoleMappings;
-        }
-
-        public String getResource() {
-            return resource;
-        }
-
-        public void setResource(String resource) {
-            this.resource = resource;
-        }
-
-        public Map<String, String> getCredentials() {
-            return credentials;
-        }
-
-        public void setCredentials(Map<String, String> credentials) {
-            this.credentials = credentials;
-        }
-
-        public Boolean getPublicClient() {
-            return publicClient;
-        }
-
-        public void setPublicClient(Boolean publicClient) {
-            this.publicClient = publicClient;
-        }
-
-        public Boolean getBearerOnly() {
-            return bearerOnly;
-        }
-
-        public void setBearerOnly(Boolean bearerOnly) {
-            this.bearerOnly = bearerOnly;
-        }
-    }
-
-
-    public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, ClientModel clientModel, URI baseUri) {
-        InstallationAdapterConfig rep = new InstallationAdapterConfig();
-        rep.setAuthServerUrl(baseUri.toString());
-        rep.setRealm(realmModel.getName());
-        rep.setRealmKey(realmModel.getPublicKeyPem());
-        rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase());
-
-        if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) rep.setPublicClient(true);
-        if (clientModel.isBearerOnly()) rep.setBearerOnly(true);
-        if (clientModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true);
-
-        rep.setResource(clientModel.getClientId());
-
-        if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) {
-            Map<String, String> creds = new HashMap<String, String>();
-            String cred = clientModel.getSecret();
-            creds.put(CredentialRepresentation.SECRET, cred);
-            rep.setCredentials(creds);
-        }
-
-        return rep;
-    }
-
-    public String toJBossSubsystemConfig(RealmModel realmModel, ClientModel clientModel, URI baseUri) {
-        StringBuffer buffer = new StringBuffer();
-        buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
-        buffer.append("    <realm>").append(realmModel.getName()).append("</realm>\n");
-        buffer.append("    <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
-        buffer.append("    <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
-        if (clientModel.isBearerOnly()){
-            buffer.append("    <bearer-only>true</bearer-only>\n");
-
-        } else if (clientModel.isPublicClient()) {
-            buffer.append("    <public-client>true</public-client>\n");
-        }
-        buffer.append("    <ssl-required>").append(realmModel.getSslRequired().name()).append("</ssl-required>\n");
-        buffer.append("    <resource>").append(clientModel.getClientId()).append("</resource>\n");
-        String cred = clientModel.getSecret();
-        if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) {
-            buffer.append("    <credential name=\"secret\">").append(cred).append("</credential>\n");
-        }
-        if (clientModel.getRoles().size() > 0) {
-            buffer.append("    <use-resource-role-mappings>true</use-resource-role-mappings>\n");
-        }
-        buffer.append("</secure-deployment>\n");
-        return buffer.toString();
-    }
-
-}
+package org.keycloak.services.managers;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonPropertyOrder;
+import org.jboss.logging.Logger;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.adapters.config.BaseRealmConfig;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.util.Time;
+
+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 java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientManager {
+    protected Logger logger = Logger.getLogger(ClientManager.class);
+
+    protected RealmManager realmManager;
+
+    public ClientManager(RealmManager realmManager) {
+        this.realmManager = realmManager;
+    }
+
+    public ClientManager() {
+    }
+
+    public ClientModel createClient(RealmModel realm, String name) {
+        return KeycloakModelUtils.createClient(realm, name);
+    }
+
+    public boolean removeClient(RealmModel realm, ClientModel client) {
+        if (realm.removeClient(client.getId())) {
+            UserSessionProvider sessions = realmManager.getSession().sessions();
+            if (sessions != null) {
+                sessions.onClientRemoved(realm, client);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public Set<String> validateRegisteredNodes(ClientModel client) {
+        Map<String, Integer> registeredNodes = client.getRegisteredNodes();
+        if (registeredNodes == null || registeredNodes.isEmpty()) {
+            return Collections.emptySet();
+        }
+
+        int currentTime = Time.currentTime();
+
+        Set<String> validatedNodes = new TreeSet<String>();
+        if (client.getNodeReRegistrationTimeout() > 0) {
+            List<String> toRemove = new LinkedList<String>();
+            for (Map.Entry<String, Integer> entry : registeredNodes.entrySet()) {
+                Integer lastReRegistration = entry.getValue();
+                if (lastReRegistration + client.getNodeReRegistrationTimeout() < currentTime) {
+                    toRemove.add(entry.getKey());
+                } else {
+                    validatedNodes.add(entry.getKey());
+                }
+            }
+
+            // Remove time-outed nodes
+            for (String node : toRemove) {
+                client.unregisterNode(node);
+            }
+        } else {
+            // Periodic node reRegistration is disabled, so allow all nodes
+            validatedNodes.addAll(registeredNodes.keySet());
+        }
+
+        return validatedNodes;
+    }
+
+    @JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-required",
+            "resource", "public-client", "credentials",
+            "use-resource-role-mappings"})
+    public static class InstallationAdapterConfig extends BaseRealmConfig {
+        @JsonProperty("resource")
+        protected String resource;
+        @JsonProperty("use-resource-role-mappings")
+        protected Boolean useResourceRoleMappings;
+        @JsonProperty("bearer-only")
+        protected Boolean bearerOnly;
+        @JsonProperty("public-client")
+        protected Boolean publicClient;
+        @JsonProperty("credentials")
+        protected Map<String, String> credentials;
+
+        public Boolean isUseResourceRoleMappings() {
+            return useResourceRoleMappings;
+        }
+
+        public void setUseResourceRoleMappings(Boolean useResourceRoleMappings) {
+            this.useResourceRoleMappings = useResourceRoleMappings;
+        }
+
+        public String getResource() {
+            return resource;
+        }
+
+        public void setResource(String resource) {
+            this.resource = resource;
+        }
+
+        public Map<String, String> getCredentials() {
+            return credentials;
+        }
+
+        public void setCredentials(Map<String, String> credentials) {
+            this.credentials = credentials;
+        }
+
+        public Boolean getPublicClient() {
+            return publicClient;
+        }
+
+        public void setPublicClient(Boolean publicClient) {
+            this.publicClient = publicClient;
+        }
+
+        public Boolean getBearerOnly() {
+            return bearerOnly;
+        }
+
+        public void setBearerOnly(Boolean bearerOnly) {
+            this.bearerOnly = bearerOnly;
+        }
+    }
+
+
+    public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, ClientModel clientModel, URI baseUri) {
+        InstallationAdapterConfig rep = new InstallationAdapterConfig();
+        rep.setAuthServerUrl(baseUri.toString());
+        rep.setRealm(realmModel.getName());
+        rep.setRealmKey(realmModel.getPublicKeyPem());
+        rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase());
+
+        if (clientModel.isPublicClient() && !clientModel.isBearerOnly()) rep.setPublicClient(true);
+        if (clientModel.isBearerOnly()) rep.setBearerOnly(true);
+        if (clientModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true);
+
+        rep.setResource(clientModel.getClientId());
+
+        if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) {
+            Map<String, String> creds = new HashMap<String, String>();
+            String cred = clientModel.getSecret();
+            creds.put(CredentialRepresentation.SECRET, cred);
+            rep.setCredentials(creds);
+        }
+
+        return rep;
+    }
+
+    public String toJBossSubsystemConfig(RealmModel realmModel, ClientModel clientModel, URI baseUri) {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
+        buffer.append("    <realm>").append(realmModel.getName()).append("</realm>\n");
+        buffer.append("    <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
+        buffer.append("    <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
+        if (clientModel.isBearerOnly()){
+            buffer.append("    <bearer-only>true</bearer-only>\n");
+
+        } else if (clientModel.isPublicClient()) {
+            buffer.append("    <public-client>true</public-client>\n");
+        }
+        buffer.append("    <ssl-required>").append(realmModel.getSslRequired().name()).append("</ssl-required>\n");
+        buffer.append("    <resource>").append(clientModel.getClientId()).append("</resource>\n");
+        String cred = clientModel.getSecret();
+        if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) {
+            buffer.append("    <credential name=\"secret\">").append(cred).append("</credential>\n");
+        }
+        if (clientModel.getRoles().size() > 0) {
+            buffer.append("    <use-resource-role-mappings>true</use-resource-role-mappings>\n");
+        }
+        buffer.append("</secure-deployment>\n");
+        return buffer.toString();
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
index b19295b..459aab3 100755
--- a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
@@ -1,174 +1,174 @@
-package org.keycloak.services.managers;
-
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel.RequiredAction;
-import org.keycloak.util.Base64Url;
-import org.keycloak.util.Time;
-
-import javax.crypto.Mac;
-import java.security.Key;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientSessionCode {
-
-    public static final String ACTION_KEY = "action_key";
-
-    private static final byte[] HASH_SEPERATOR = "//".getBytes();
-
-    private final RealmModel realm;
-    private final ClientSessionModel clientSession;
-
-    public ClientSessionCode(RealmModel realm, ClientSessionModel clientSession) {
-        this.realm = realm;
-        this.clientSession = clientSession;
-    }
-
-    public static ClientSessionCode parse(String code, KeycloakSession session) {
-        try {
-            String[] parts = code.split("\\.");
-            String id = parts[1];
-
-            ClientSessionModel clientSession = session.sessions().getClientSession(id);
-            if (clientSession == null) {
-                return null;
-            }
-
-            String hash = createHash(clientSession.getRealm(), clientSession);
-            if (!hash.equals(parts[0])) {
-                return null;
-            }
-
-            return new ClientSessionCode(clientSession.getRealm(), clientSession);
-        } catch (RuntimeException e) {
-            return null;
-        }
-    }
-
-
-    public static ClientSessionCode parse(String code, KeycloakSession session, RealmModel realm) {
-        try {
-            String[] parts = code.split("\\.");
-            String id = parts[1];
-
-            ClientSessionModel clientSession = session.sessions().getClientSession(realm, id);
-            if (clientSession == null) {
-                return null;
-            }
-
-            String hash = createHash(realm, clientSession);
-            if (!hash.equals(parts[0])) {
-                return null;
-            }
-
-            return new ClientSessionCode(realm, clientSession);
-        } catch (RuntimeException e) {
-            return null;
-        }
-    }
-
-    public ClientSessionModel getClientSession() {
-        return clientSession;
-    }
-
-    public boolean isValid(String requestedAction) {
-        if (!isValidAction(requestedAction)) return false;
-        return isActionActive(requestedAction);
-    }
-
-    public boolean isActionActive(String requestedAction) {
-        int timestamp = clientSession.getTimestamp();
-
-        int lifespan;
-        if (requestedAction.equals(ClientSessionModel.Action.CODE_TO_TOKEN.name())) {
-            lifespan = realm.getAccessCodeLifespan();
-
-        } else if (requestedAction.equals(ClientSessionModel.Action.AUTHENTICATE.name())) {
-            lifespan = realm.getAccessCodeLifespanLogin() > 0 ? realm.getAccessCodeLifespanLogin() : realm.getAccessCodeLifespanUserAction();
-        } else {
-            lifespan = realm.getAccessCodeLifespanUserAction();
-        }
-        return timestamp + lifespan > Time.currentTime();
-    }
-
-    public boolean isValidAction(String requestedAction) {
-        String action = clientSession.getAction();
-        if (action == null) {
-            return false;
-        }
-        if (!action.equals(requestedAction)) {
-            return false;
-        }
-        return true;
-    }
-
-
-    public Set<RoleModel> getRequestedRoles() {
-        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
-        for (String roleId : clientSession.getRoles()) {
-            RoleModel role = realm.getRoleById(roleId);
-            if (role != null) {
-                requestedRoles.add(role);
-            }
-        }
-        return requestedRoles;
-    }
-
-    public Set<ProtocolMapperModel> getRequestedProtocolMappers() {
-        Set<ProtocolMapperModel> requestedProtocolMappers = new HashSet<ProtocolMapperModel>();
-        if (clientSession.getProtocolMappers() != null) {
-            for (String protocolMapperId : clientSession.getProtocolMappers()) {
-                ProtocolMapperModel protocolMapper = clientSession.getClient().getProtocolMapperById(protocolMapperId);
-                if (protocolMapper != null) {
-                    requestedProtocolMappers.add(protocolMapper);
-                }
-            }
-        }
-        return requestedProtocolMappers;
-    }
-
-    public void setAction(String action) {
-        clientSession.setAction(action);
-        clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString());
-        clientSession.setTimestamp(Time.currentTime());
-    }
-
-    public String getCode() {
-        return generateCode(realm, clientSession);
-    }
-
-    private static String generateCode(RealmModel realm, ClientSessionModel clientSession) {
-        String hash = createHash(realm, clientSession);
-
-        StringBuilder sb = new StringBuilder();
-        sb.append(hash);
-        sb.append(".");
-        sb.append(clientSession.getId());
-
-        return sb.toString();
-    }
-
-    private static String createHash(RealmModel realm, ClientSessionModel clientSession) {
-        try {
-            Key codeSecretKey = realm.getCodeSecretKey();
-            Mac mac = Mac.getInstance(codeSecretKey.getAlgorithm());
-            mac.init(codeSecretKey);
-            mac.update(clientSession.getId().getBytes());
-            mac.update(HASH_SEPERATOR);
-            mac.update(clientSession.getNote(ACTION_KEY).getBytes());
-            return Base64Url.encode(mac.doFinal());
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
+package org.keycloak.services.managers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.util.Base64Url;
+import org.keycloak.util.Time;
+
+import javax.crypto.Mac;
+import java.security.Key;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientSessionCode {
+
+    public static final String ACTION_KEY = "action_key";
+
+    private static final byte[] HASH_SEPERATOR = "//".getBytes();
+
+    private final RealmModel realm;
+    private final ClientSessionModel clientSession;
+
+    public ClientSessionCode(RealmModel realm, ClientSessionModel clientSession) {
+        this.realm = realm;
+        this.clientSession = clientSession;
+    }
+
+    public static ClientSessionCode parse(String code, KeycloakSession session) {
+        try {
+            String[] parts = code.split("\\.");
+            String id = parts[1];
+
+            ClientSessionModel clientSession = session.sessions().getClientSession(id);
+            if (clientSession == null) {
+                return null;
+            }
+
+            String hash = createHash(clientSession.getRealm(), clientSession);
+            if (!hash.equals(parts[0])) {
+                return null;
+            }
+
+            return new ClientSessionCode(clientSession.getRealm(), clientSession);
+        } catch (RuntimeException e) {
+            return null;
+        }
+    }
+
+
+    public static ClientSessionCode parse(String code, KeycloakSession session, RealmModel realm) {
+        try {
+            String[] parts = code.split("\\.");
+            String id = parts[1];
+
+            ClientSessionModel clientSession = session.sessions().getClientSession(realm, id);
+            if (clientSession == null) {
+                return null;
+            }
+
+            String hash = createHash(realm, clientSession);
+            if (!hash.equals(parts[0])) {
+                return null;
+            }
+
+            return new ClientSessionCode(realm, clientSession);
+        } catch (RuntimeException e) {
+            return null;
+        }
+    }
+
+    public ClientSessionModel getClientSession() {
+        return clientSession;
+    }
+
+    public boolean isValid(String requestedAction) {
+        if (!isValidAction(requestedAction)) return false;
+        return isActionActive(requestedAction);
+    }
+
+    public boolean isActionActive(String requestedAction) {
+        int timestamp = clientSession.getTimestamp();
+
+        int lifespan;
+        if (requestedAction.equals(ClientSessionModel.Action.CODE_TO_TOKEN.name())) {
+            lifespan = realm.getAccessCodeLifespan();
+
+        } else if (requestedAction.equals(ClientSessionModel.Action.AUTHENTICATE.name())) {
+            lifespan = realm.getAccessCodeLifespanLogin() > 0 ? realm.getAccessCodeLifespanLogin() : realm.getAccessCodeLifespanUserAction();
+        } else {
+            lifespan = realm.getAccessCodeLifespanUserAction();
+        }
+        return timestamp + lifespan > Time.currentTime();
+    }
+
+    public boolean isValidAction(String requestedAction) {
+        String action = clientSession.getAction();
+        if (action == null) {
+            return false;
+        }
+        if (!action.equals(requestedAction)) {
+            return false;
+        }
+        return true;
+    }
+
+
+    public Set<RoleModel> getRequestedRoles() {
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+        for (String roleId : clientSession.getRoles()) {
+            RoleModel role = realm.getRoleById(roleId);
+            if (role != null) {
+                requestedRoles.add(role);
+            }
+        }
+        return requestedRoles;
+    }
+
+    public Set<ProtocolMapperModel> getRequestedProtocolMappers() {
+        Set<ProtocolMapperModel> requestedProtocolMappers = new HashSet<ProtocolMapperModel>();
+        if (clientSession.getProtocolMappers() != null) {
+            for (String protocolMapperId : clientSession.getProtocolMappers()) {
+                ProtocolMapperModel protocolMapper = clientSession.getClient().getProtocolMapperById(protocolMapperId);
+                if (protocolMapper != null) {
+                    requestedProtocolMappers.add(protocolMapper);
+                }
+            }
+        }
+        return requestedProtocolMappers;
+    }
+
+    public void setAction(String action) {
+        clientSession.setAction(action);
+        clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString());
+        clientSession.setTimestamp(Time.currentTime());
+    }
+
+    public String getCode() {
+        return generateCode(realm, clientSession);
+    }
+
+    private static String generateCode(RealmModel realm, ClientSessionModel clientSession) {
+        String hash = createHash(realm, clientSession);
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(hash);
+        sb.append(".");
+        sb.append(clientSession.getId());
+
+        return sb.toString();
+    }
+
+    private static String createHash(RealmModel realm, ClientSessionModel clientSession) {
+        try {
+            Key codeSecretKey = realm.getCodeSecretKey();
+            Mac mac = Mac.getInstance(codeSecretKey.getAlgorithm());
+            mac.init(codeSecretKey);
+            mac.update(clientSession.getId().getBytes());
+            mac.update(HASH_SEPERATOR);
+            mac.update(clientSession.getNote(ACTION_KEY).getBytes());
+            return Base64Url.encode(mac.doFinal());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index a0e1235..c011551 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -1,370 +1,370 @@
-package org.keycloak.services.managers;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.exportimport.util.ImportUtils;
-import org.keycloak.models.AccountRoles;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.BrowserSecurityHeaders;
-import org.keycloak.models.Constants;
-import org.keycloak.models.ImpersonationConstants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.models.utils.DefaultRequiredActions;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.ApplicationRepresentation;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
-import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.timer.TimerProvider;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Per request object
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmManager {
-    protected static final Logger logger = Logger.getLogger(RealmManager.class);
-
-    protected KeycloakSession session;
-    protected RealmProvider model;
-    protected String contextPath = "";
-
-    public String getContextPath() {
-        return contextPath;
-    }
-
-    public void setContextPath(String contextPath) {
-        this.contextPath = contextPath;
-    }
-
-    public RealmManager(KeycloakSession session) {
-        this.session = session;
-        this.model = session.realms();
-    }
-
-    public KeycloakSession getSession() {
-        return session;
-    }
-
-    public RealmModel getKeycloakAdminstrationRealm() {
-        return getRealm(Config.getAdminRealm());
-    }
-
-    public RealmModel getRealm(String id) {
-        return model.getRealm(id);
-    }
-
-    public RealmModel getRealmByName(String name) {
-        return model.getRealmByName(name);
-    }
-
-    public RealmModel createRealm(String name) {
-        return createRealm(name, name);
-    }
-
-    public RealmModel createRealm(String id, String name) {
-        if (id == null) id = KeycloakModelUtils.generateId();
-        RealmModel realm = model.createRealm(id, name);
-        realm.setName(name);
-
-        // setup defaults
-        setupRealmDefaults(realm);
-
-        setupMasterAdminManagement(realm);
-        setupRealmAdminManagement(realm);
-        setupAccountManagement(realm);
-        setupBrokerService(realm);
-        setupAdminConsole(realm);
-        setupImpersonationService(realm);
-        setupAuthenticationFlows(realm);
-        setupRequiredActions(realm);
-
-        return realm;
-    }
-
-    protected void setupAuthenticationFlows(RealmModel realm) {
-        if (realm.getAuthenticationFlows().size() == 0) DefaultAuthenticationFlows.addFlows(realm);
-    }
-
-    protected void setupRequiredActions(RealmModel realm) {
-        if (realm.getRequiredActionProviders().size() == 0) DefaultRequiredActions.addActions(realm);
-    }
-
-    protected void setupAdminConsole(RealmModel realm) {
-        ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
-        if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID);
-        adminConsole.setName("${client_" + Constants.ADMIN_CONSOLE_CLIENT_ID + "}");
-        String baseUrl = contextPath + "/admin/" + realm.getName() + "/console";
-        adminConsole.setBaseUrl(baseUrl + "/index.html");
-        adminConsole.setEnabled(true);
-        adminConsole.setPublicClient(true);
-        adminConsole.addRedirectUri(baseUrl + "/*");
-        adminConsole.setFullScopeAllowed(false);
-
-        RoleModel adminRole;
-        if (realm.getName().equals(Config.getAdminRealm())) {
-            adminRole = realm.getRole(AdminRoles.ADMIN);
-        } else {
-            String realmAdminApplicationClientId = getRealmAdminClientId(realm);
-            ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
-            adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
-        }
-        adminConsole.addScopeMapping(adminRole);
-    }
-
-    public String getRealmAdminClientId(RealmModel realm) {
-        return Constants.REALM_MANAGEMENT_CLIENT_ID;
-    }
-
-    public String getRealmAdminClientId(RealmRepresentation realm) {
-        return Constants.REALM_MANAGEMENT_CLIENT_ID;
-    }
-
-
-
-    protected void setupRealmDefaults(RealmModel realm) {
-        realm.setBrowserSecurityHeaders(BrowserSecurityHeaders.defaultHeaders);
-
-        // brute force
-        realm.setBruteForceProtected(false); // default settings off for now todo set it on
-        realm.setMaxFailureWaitSeconds(900);
-        realm.setMinimumQuickLoginWaitSeconds(60);
-        realm.setWaitIncrementSeconds(60);
-        realm.setQuickLoginCheckMilliSeconds(1000);
-        realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours
-        realm.setFailureFactor(30);
-        realm.setSslRequired(SslRequired.EXTERNAL);
-
-        realm.setEventsListeners(Collections.singleton("jboss-logging"));
-    }
-
-    public boolean removeRealm(RealmModel realm) {
-        List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
-
-        boolean removed = model.removeRealm(realm.getId());
-        if (removed) {
-            new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), realm.getMasterAdminClient());
-
-            UserSessionProvider sessions = session.sessions();
-            if (sessions != null) {
-                sessions.onRealmRemoved(realm);
-            }
-
-            // Remove all periodic syncs for configured federation providers
-            UsersSyncManager usersSyncManager = new UsersSyncManager();
-            for (final UserFederationProviderModel fedProvider : federationProviders) {
-                usersSyncManager.removePeriodicSyncForProvider(session.getProvider(TimerProvider.class), fedProvider);
-            }
-        }
-        return removed;
-    }
-
-    public void updateRealmEventsConfig(RealmEventsConfigRepresentation rep, RealmModel realm) {
-        realm.setEventsEnabled(rep.isEventsEnabled());
-        realm.setEventsExpiration(rep.getEventsExpiration() != null ? rep.getEventsExpiration() : 0);
-        if (rep.getEventsListeners() != null) {
-            realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
-        }
-        if(rep.getEnabledEventTypes() != null) {
-            realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
-        }
-        
-        realm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
-        realm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
-    }
-
-    // Should be RealmManager moved to model/api instead of referencing methods this way?
-    private void setupMasterAdminManagement(RealmModel realm) {
-        ImportUtils.setupMasterAdminManagement(model, realm);
-    }
-
-    private void setupRealmAdminManagement(RealmModel realm) {
-        if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm
-
-        ClientManager clientManager = new ClientManager(new RealmManager(session));
-
-        String realmAdminClientId = getRealmAdminClientId(realm);
-        ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId);
-        if (realmAdminClient == null) {
-            realmAdminClient = clientManager.createClient(realm, realmAdminClientId);
-            realmAdminClient.setName("${client_" + realmAdminClientId + "}");
-        }
-        RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN);
-        adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}");
-        realmAdminClient.setBearerOnly(true);
-        realmAdminClient.setFullScopeAllowed(false);
-
-        for (String r : AdminRoles.ALL_REALM_ROLES) {
-            RoleModel role = realmAdminClient.addRole(r);
-            role.setDescription("${role_"+r+"}");
-            adminRole.addCompositeRole(role);
-        }
-    }
-
-
-    private void setupAccountManagement(RealmModel realm) {
-        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-        if (client == null) {
-            client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-            client.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}");
-            client.setEnabled(true);
-            client.setFullScopeAllowed(false);
-            String base = contextPath + "/realms/" + realm.getName() + "/account";
-            String redirectUri = base + "/*";
-            client.addRedirectUri(redirectUri);
-            client.setBaseUrl(base);
-
-            for (String role : AccountRoles.ALL) {
-                client.addDefaultRole(role);
-                client.getRole(role).setDescription("${role_"+role+"}");
-            }
-        }
-    }
-
-    public void setupImpersonationService(RealmModel realm) {
-        ImpersonationConstants.setupImpersonationService(session, realm);
-    }
-
-    public void setupBrokerService(RealmModel realm) {
-        ClientModel client = realm.getClientNameMap().get(Constants.BROKER_SERVICE_CLIENT_ID);
-        if (client == null) {
-            client = new ClientManager(this).createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
-            client.setEnabled(true);
-            client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}");
-            client.setFullScopeAllowed(false);
-
-            for (String role : Constants.BROKER_SERVICE_ROLES) {
-                client.addRole(role).setDescription("${role_"+ role.toLowerCase().replaceAll("_", "-") +"}");
-            }
-        }
-    }
-
-    public RealmModel importRealm(RealmRepresentation rep) {
-        String id = rep.getId();
-        if (id == null) {
-            id = KeycloakModelUtils.generateId();
-        }
-        RealmModel realm = model.createRealm(id, rep.getRealm());
-        realm.setName(rep.getRealm());
-
-        // setup defaults
-
-        setupRealmDefaults(realm);
-        setupMasterAdminManagement(realm);
-        if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm);
-        if (!hasAccountManagementClient(rep)) setupAccountManagement(realm);
-
-        boolean postponeImpersonationSetup = false;
-        if (!hasImpersonationServiceClient(rep)) {
-            if (hasRealmAdminManagementClient(rep)) {
-                postponeImpersonationSetup = true;
-            } else {
-                setupImpersonationService(realm);
-            }
-        }
-
-        if (!hasBrokerClient(rep)) setupBrokerService(realm);
-        if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm);
-
-        RepresentationToModel.importRealm(session, rep, realm);
-
-        // Could happen when migrating from older version and I have exported JSON file, which contains "realm-management" client but not "impersonation" client
-        // I need to postpone impersonation because it needs "realm-management" client and it's roles set
-        if (postponeImpersonationSetup) {
-            setupImpersonationService(realm);
-        }
-
-        setupAuthenticationFlows(realm);
-        setupRequiredActions(realm);
-
-        // Refresh periodic sync tasks for configured federationProviders
-        List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
-        UsersSyncManager usersSyncManager = new UsersSyncManager();
-        for (final UserFederationProviderModel fedProvider : federationProviders) {
-            usersSyncManager.refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), fedProvider, realm.getId());
-        }
-        return realm;
-    }
-
-    private boolean hasRealmAdminManagementClient(RealmRepresentation rep) {
-        String realmAdminClientId = getRealmAdminClientId(rep);
-        return hasClient(rep, realmAdminClientId);
-    }
-
-    private boolean hasAccountManagementClient(RealmRepresentation rep) {
-        return hasClient(rep, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-    }
-    private boolean hasImpersonationServiceClient(RealmRepresentation rep) {
-        return hasClient(rep, Constants.IMPERSONATION_SERVICE_CLIENT_ID);
-    }
-    private boolean hasBrokerClient(RealmRepresentation rep) {
-        return hasClient(rep, Constants.BROKER_SERVICE_CLIENT_ID);
-    }
-
-    private boolean hasAdminConsoleClient(RealmRepresentation rep) {
-        return hasClient(rep, Constants.ADMIN_CONSOLE_CLIENT_ID);
-    }
-
-    private boolean hasClient(RealmRepresentation rep, String clientId) {
-        if (rep.getClients() != null) {
-            for (ClientRepresentation clientRep : rep.getClients()) {
-                if (clientRep.getClientId().equals(clientId)) {
-                    return true;
-                }
-            }
-        }
-
-        // TODO: Just for compatibility with old versions. Should be removed later...
-        if (rep.getApplications() != null) {
-            for (ApplicationRepresentation clientRep : rep.getApplications()) {
-                if (clientRep.getName().equals(clientId)) {
-                    return true;
-                }
-            }
-        }
-        if (rep.getOauthClients() != null) {
-            for (OAuthClientRepresentation clientRep : rep.getOauthClients()) {
-                if (clientRep.getName().equals(clientId)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Query users based on a search string:
-     * <p/>
-     * "Bill Burke" first and last name
-     * "bburke@redhat.com" email
-     * "Burke" lastname or username
-     *
-     * @param searchString
-     * @param realmModel
-     * @return
-     */
-    public List<UserModel> searchUsers(String searchString, RealmModel realmModel) {
-        if (searchString == null) {
-            return Collections.emptyList();
-        }
-        return session.users().searchForUser(searchString.trim(), realmModel);
-    }
-
-}
+package org.keycloak.services.managers;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.exportimport.util.ImportUtils;
+import org.keycloak.models.AccountRoles;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.BrowserSecurityHeaders;
+import org.keycloak.models.Constants;
+import org.keycloak.models.ImpersonationConstants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionProvider;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.models.utils.DefaultRequiredActions;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.timer.TimerProvider;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Per request object
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmManager {
+    protected static final Logger logger = Logger.getLogger(RealmManager.class);
+
+    protected KeycloakSession session;
+    protected RealmProvider model;
+    protected String contextPath = "";
+
+    public String getContextPath() {
+        return contextPath;
+    }
+
+    public void setContextPath(String contextPath) {
+        this.contextPath = contextPath;
+    }
+
+    public RealmManager(KeycloakSession session) {
+        this.session = session;
+        this.model = session.realms();
+    }
+
+    public KeycloakSession getSession() {
+        return session;
+    }
+
+    public RealmModel getKeycloakAdminstrationRealm() {
+        return getRealm(Config.getAdminRealm());
+    }
+
+    public RealmModel getRealm(String id) {
+        return model.getRealm(id);
+    }
+
+    public RealmModel getRealmByName(String name) {
+        return model.getRealmByName(name);
+    }
+
+    public RealmModel createRealm(String name) {
+        return createRealm(name, name);
+    }
+
+    public RealmModel createRealm(String id, String name) {
+        if (id == null) id = KeycloakModelUtils.generateId();
+        RealmModel realm = model.createRealm(id, name);
+        realm.setName(name);
+
+        // setup defaults
+        setupRealmDefaults(realm);
+
+        setupMasterAdminManagement(realm);
+        setupRealmAdminManagement(realm);
+        setupAccountManagement(realm);
+        setupBrokerService(realm);
+        setupAdminConsole(realm);
+        setupImpersonationService(realm);
+        setupAuthenticationFlows(realm);
+        setupRequiredActions(realm);
+
+        return realm;
+    }
+
+    protected void setupAuthenticationFlows(RealmModel realm) {
+        if (realm.getAuthenticationFlows().size() == 0) DefaultAuthenticationFlows.addFlows(realm);
+    }
+
+    protected void setupRequiredActions(RealmModel realm) {
+        if (realm.getRequiredActionProviders().size() == 0) DefaultRequiredActions.addActions(realm);
+    }
+
+    protected void setupAdminConsole(RealmModel realm) {
+        ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
+        if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID);
+        adminConsole.setName("${client_" + Constants.ADMIN_CONSOLE_CLIENT_ID + "}");
+        String baseUrl = contextPath + "/admin/" + realm.getName() + "/console";
+        adminConsole.setBaseUrl(baseUrl + "/index.html");
+        adminConsole.setEnabled(true);
+        adminConsole.setPublicClient(true);
+        adminConsole.addRedirectUri(baseUrl + "/*");
+        adminConsole.setFullScopeAllowed(false);
+
+        RoleModel adminRole;
+        if (realm.getName().equals(Config.getAdminRealm())) {
+            adminRole = realm.getRole(AdminRoles.ADMIN);
+        } else {
+            String realmAdminApplicationClientId = getRealmAdminClientId(realm);
+            ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
+            adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
+        }
+        adminConsole.addScopeMapping(adminRole);
+    }
+
+    public String getRealmAdminClientId(RealmModel realm) {
+        return Constants.REALM_MANAGEMENT_CLIENT_ID;
+    }
+
+    public String getRealmAdminClientId(RealmRepresentation realm) {
+        return Constants.REALM_MANAGEMENT_CLIENT_ID;
+    }
+
+
+
+    protected void setupRealmDefaults(RealmModel realm) {
+        realm.setBrowserSecurityHeaders(BrowserSecurityHeaders.defaultHeaders);
+
+        // brute force
+        realm.setBruteForceProtected(false); // default settings off for now todo set it on
+        realm.setMaxFailureWaitSeconds(900);
+        realm.setMinimumQuickLoginWaitSeconds(60);
+        realm.setWaitIncrementSeconds(60);
+        realm.setQuickLoginCheckMilliSeconds(1000);
+        realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours
+        realm.setFailureFactor(30);
+        realm.setSslRequired(SslRequired.EXTERNAL);
+
+        realm.setEventsListeners(Collections.singleton("jboss-logging"));
+    }
+
+    public boolean removeRealm(RealmModel realm) {
+        List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
+
+        boolean removed = model.removeRealm(realm.getId());
+        if (removed) {
+            new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), realm.getMasterAdminClient());
+
+            UserSessionProvider sessions = session.sessions();
+            if (sessions != null) {
+                sessions.onRealmRemoved(realm);
+            }
+
+            // Remove all periodic syncs for configured federation providers
+            UsersSyncManager usersSyncManager = new UsersSyncManager();
+            for (final UserFederationProviderModel fedProvider : federationProviders) {
+                usersSyncManager.removePeriodicSyncForProvider(session.getProvider(TimerProvider.class), fedProvider);
+            }
+        }
+        return removed;
+    }
+
+    public void updateRealmEventsConfig(RealmEventsConfigRepresentation rep, RealmModel realm) {
+        realm.setEventsEnabled(rep.isEventsEnabled());
+        realm.setEventsExpiration(rep.getEventsExpiration() != null ? rep.getEventsExpiration() : 0);
+        if (rep.getEventsListeners() != null) {
+            realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
+        }
+        if(rep.getEnabledEventTypes() != null) {
+            realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
+        }
+        
+        realm.setAdminEventsEnabled(rep.isAdminEventsEnabled());
+        realm.setAdminEventsDetailsEnabled(rep.isAdminEventsDetailsEnabled());
+    }
+
+    // Should be RealmManager moved to model/api instead of referencing methods this way?
+    private void setupMasterAdminManagement(RealmModel realm) {
+        ImportUtils.setupMasterAdminManagement(model, realm);
+    }
+
+    private void setupRealmAdminManagement(RealmModel realm) {
+        if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm
+
+        ClientManager clientManager = new ClientManager(new RealmManager(session));
+
+        String realmAdminClientId = getRealmAdminClientId(realm);
+        ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId);
+        if (realmAdminClient == null) {
+            realmAdminClient = clientManager.createClient(realm, realmAdminClientId);
+            realmAdminClient.setName("${client_" + realmAdminClientId + "}");
+        }
+        RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN);
+        adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}");
+        realmAdminClient.setBearerOnly(true);
+        realmAdminClient.setFullScopeAllowed(false);
+
+        for (String r : AdminRoles.ALL_REALM_ROLES) {
+            RoleModel role = realmAdminClient.addRole(r);
+            role.setDescription("${role_"+r+"}");
+            adminRole.addCompositeRole(role);
+        }
+    }
+
+
+    private void setupAccountManagement(RealmModel realm) {
+        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        if (client == null) {
+            client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+            client.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}");
+            client.setEnabled(true);
+            client.setFullScopeAllowed(false);
+            String base = contextPath + "/realms/" + realm.getName() + "/account";
+            String redirectUri = base + "/*";
+            client.addRedirectUri(redirectUri);
+            client.setBaseUrl(base);
+
+            for (String role : AccountRoles.ALL) {
+                client.addDefaultRole(role);
+                client.getRole(role).setDescription("${role_"+role+"}");
+            }
+        }
+    }
+
+    public void setupImpersonationService(RealmModel realm) {
+        ImpersonationConstants.setupImpersonationService(session, realm);
+    }
+
+    public void setupBrokerService(RealmModel realm) {
+        ClientModel client = realm.getClientNameMap().get(Constants.BROKER_SERVICE_CLIENT_ID);
+        if (client == null) {
+            client = new ClientManager(this).createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
+            client.setEnabled(true);
+            client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}");
+            client.setFullScopeAllowed(false);
+
+            for (String role : Constants.BROKER_SERVICE_ROLES) {
+                client.addRole(role).setDescription("${role_"+ role.toLowerCase().replaceAll("_", "-") +"}");
+            }
+        }
+    }
+
+    public RealmModel importRealm(RealmRepresentation rep) {
+        String id = rep.getId();
+        if (id == null) {
+            id = KeycloakModelUtils.generateId();
+        }
+        RealmModel realm = model.createRealm(id, rep.getRealm());
+        realm.setName(rep.getRealm());
+
+        // setup defaults
+
+        setupRealmDefaults(realm);
+        setupMasterAdminManagement(realm);
+        if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm);
+        if (!hasAccountManagementClient(rep)) setupAccountManagement(realm);
+
+        boolean postponeImpersonationSetup = false;
+        if (!hasImpersonationServiceClient(rep)) {
+            if (hasRealmAdminManagementClient(rep)) {
+                postponeImpersonationSetup = true;
+            } else {
+                setupImpersonationService(realm);
+            }
+        }
+
+        if (!hasBrokerClient(rep)) setupBrokerService(realm);
+        if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm);
+
+        RepresentationToModel.importRealm(session, rep, realm);
+
+        // Could happen when migrating from older version and I have exported JSON file, which contains "realm-management" client but not "impersonation" client
+        // I need to postpone impersonation because it needs "realm-management" client and it's roles set
+        if (postponeImpersonationSetup) {
+            setupImpersonationService(realm);
+        }
+
+        setupAuthenticationFlows(realm);
+        setupRequiredActions(realm);
+
+        // Refresh periodic sync tasks for configured federationProviders
+        List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
+        UsersSyncManager usersSyncManager = new UsersSyncManager();
+        for (final UserFederationProviderModel fedProvider : federationProviders) {
+            usersSyncManager.refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), fedProvider, realm.getId());
+        }
+        return realm;
+    }
+
+    private boolean hasRealmAdminManagementClient(RealmRepresentation rep) {
+        String realmAdminClientId = getRealmAdminClientId(rep);
+        return hasClient(rep, realmAdminClientId);
+    }
+
+    private boolean hasAccountManagementClient(RealmRepresentation rep) {
+        return hasClient(rep, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+    }
+    private boolean hasImpersonationServiceClient(RealmRepresentation rep) {
+        return hasClient(rep, Constants.IMPERSONATION_SERVICE_CLIENT_ID);
+    }
+    private boolean hasBrokerClient(RealmRepresentation rep) {
+        return hasClient(rep, Constants.BROKER_SERVICE_CLIENT_ID);
+    }
+
+    private boolean hasAdminConsoleClient(RealmRepresentation rep) {
+        return hasClient(rep, Constants.ADMIN_CONSOLE_CLIENT_ID);
+    }
+
+    private boolean hasClient(RealmRepresentation rep, String clientId) {
+        if (rep.getClients() != null) {
+            for (ClientRepresentation clientRep : rep.getClients()) {
+                if (clientRep.getClientId().equals(clientId)) {
+                    return true;
+                }
+            }
+        }
+
+        // TODO: Just for compatibility with old versions. Should be removed later...
+        if (rep.getApplications() != null) {
+            for (ApplicationRepresentation clientRep : rep.getApplications()) {
+                if (clientRep.getName().equals(clientId)) {
+                    return true;
+                }
+            }
+        }
+        if (rep.getOauthClients() != null) {
+            for (OAuthClientRepresentation clientRep : rep.getOauthClients()) {
+                if (clientRep.getName().equals(clientId)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Query users based on a search string:
+     * <p/>
+     * "Bill Burke" first and last name
+     * "bburke@redhat.com" email
+     * "Burke" lastname or username
+     *
+     * @param searchString
+     * @param realmModel
+     * @return
+     */
+    public List<UserModel> searchUsers(String searchString, RealmModel realmModel) {
+        if (searchString == null) {
+            return Collections.emptyList();
+        }
+        return session.users().searchForUser(searchString.trim(), realmModel);
+    }
+
+}
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 dc0b6a4..8a94b6e 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -1,335 +1,335 @@
-package org.keycloak.services.managers;
-
-import org.jboss.logging.Logger;
-import org.keycloak.TokenIdGenerator;
-import org.keycloak.connections.httpclient.HttpClientProvider;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.representations.adapters.action.GlobalRequestResult;
-import org.keycloak.representations.adapters.action.LogoutAction;
-import org.keycloak.representations.adapters.action.PushNotBeforeAction;
-import org.keycloak.representations.adapters.action.TestAvailabilityAction;
-import org.keycloak.services.util.ResolveRelative;
-import org.keycloak.util.KeycloakUriBuilder;
-import org.keycloak.util.MultivaluedHashMap;
-import org.keycloak.util.StringPropertyReplacer;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.UriBuilder;
-import java.io.IOException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ResourceAdminManager {
-    protected static Logger logger = Logger.getLogger(ResourceAdminManager.class);
-    private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}";
-
-    private KeycloakSession session;
-
-    public ResourceAdminManager(KeycloakSession session) {
-        this.session = session;
-    }
-
-    public static String resolveUri(URI requestUri, String uri) {
-        String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, uri);
-        return StringPropertyReplacer.replaceProperties(absoluteURI);
-
-   }
-
-    public static String getManagementUrl(URI requestUri, ClientModel client) {
-        String mgmtUrl = client.getManagementUrl();
-        if (mgmtUrl == null || mgmtUrl.equals("")) {
-            return null;
-        }
-
-        // this is to support relative admin urls when keycloak and clients are deployed on the same machine
-        String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl);
-
-        // this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
-        return StringPropertyReplacer.replaceProperties(absoluteURI);
-    }
-
-    // For non-cluster setup, return just single configured managementUrls
-    // For cluster setup, return the management Urls corresponding to all registered cluster nodes
-    private List<String> getAllManagementUrls(URI requestUri, ClientModel client) {
-        String baseMgmtUrl = getManagementUrl(requestUri, client);
-        if (baseMgmtUrl == null) {
-            return Collections.emptyList();
-        }
-
-        Set<String> registeredNodesHosts = new ClientManager().validateRegisteredNodes(client);
-
-        // No-cluster setup
-        if (registeredNodesHosts.isEmpty()) {
-            return Arrays.asList(baseMgmtUrl);
-        }
-
-        List<String> result = new LinkedList<String>();
-        KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(baseMgmtUrl);
-        for (String nodeHost : registeredNodesHosts) {
-            String currentNodeUri = uriBuilder.clone().host(nodeHost).build().toString();
-            result.add(currentNodeUri);
-        }
-
-        return result;
-    }
-
-    public void logoutUser(URI requestUri, RealmModel realm, UserModel user, KeycloakSession keycloakSession) {
-        List<UserSessionModel> userSessions = keycloakSession.sessions().getUserSessions(realm, user);
-        logoutUserSessions(requestUri, realm, userSessions);
-    }
-
-    protected void logoutUserSessions(URI requestUri, RealmModel realm, List<UserSessionModel> userSessions) {
-        // Map from "app" to clientSessions for this app
-        MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
-        for (UserSessionModel userSession : userSessions) {
-            putClientSessions(clientSessions, userSession);
-        }
-
-        logger.debugv("logging out {0} resources ", clientSessions.size());
-        //logger.infov("logging out resources: {0}", clientSessions);
-
-        for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
-            logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue());
-        }
-    }
-
-    private void putClientSessions(MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
-        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
-            ClientModel client = clientSession.getClient();
-            clientSessions.add(client, clientSession);
-        }
-    }
-
-    public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user) {
-        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
-        List<ClientSessionModel> ourAppClientSessions = null;
-        if (userSessions != null) {
-            MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
-            for (UserSessionModel userSession : userSessions) {
-                putClientSessions(clientSessions, userSession);
-            }
-            ourAppClientSessions = clientSessions.get(resource);
-        }
-
-        logoutClientSessions(requestUri, realm, resource, ourAppClientSessions);
-    }
-
-    public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession) {
-        return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession));
-    }
-
-    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions) {
-        String managementUrl = getManagementUrl(requestUri, resource);
-        if (managementUrl != null) {
-
-            // Key is host, value is list of http sessions for this host
-            MultivaluedHashMap<String, String> adapterSessionIds = null;
-            List<String> userSessions = new LinkedList<>();
-            if (clientSessions != null && clientSessions.size() > 0) {
-                adapterSessionIds = new MultivaluedHashMap<String, String>();
-                for (ClientSessionModel clientSession : clientSessions) {
-                    String adapterSessionId = clientSession.getNote(AdapterConstants.CLIENT_SESSION_STATE);
-                    if (adapterSessionId != null) {
-                        String host = clientSession.getNote(AdapterConstants.CLIENT_SESSION_HOST);
-                        adapterSessionIds.add(host, adapterSessionId);
-                    }
-                    if (clientSession.getUserSession() != null) userSessions.add(clientSession.getUserSession().getId());
-                }
-            }
-
-            if (adapterSessionIds == null || adapterSessionIds.isEmpty()) {
-                logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getClientId());
-                return false;
-            }
-
-            if (managementUrl.contains(CLIENT_SESSION_HOST_PROPERTY)) {
-                boolean allPassed = true;
-                // Send logout separately to each host (needed for single-sign-out in cluster for non-distributable apps - KEYCLOAK-748)
-                for (Map.Entry<String, List<String>> entry : adapterSessionIds.entrySet()) {
-                    String host = entry.getKey();
-                    List<String> sessionIds = entry.getValue();
-                    String currentHostMgmtUrl = managementUrl.replace(CLIENT_SESSION_HOST_PROPERTY, host);
-                    allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, 0, currentHostMgmtUrl) && allPassed;
-                }
-
-                return allPassed;
-            } else {
-                // Send single logout request
-                List<String> allSessionIds = new ArrayList<String>();
-                for (List<String> currentIds : adapterSessionIds.values()) {
-                    allSessionIds.addAll(currentIds);
-                }
-
-                return sendLogoutRequest(realm, resource, allSessionIds, userSessions, 0, managementUrl);
-            }
-        } else {
-            logger.debugv("Can't logout {0}: no management url", resource.getClientId());
-            return false;
-        }
-    }
-
-    // Methods for logout all
-
-    public GlobalRequestResult logoutAll(URI requestUri, RealmModel realm) {
-        realm.setNotBefore(Time.currentTime());
-        List<ClientModel> resources = realm.getClients();
-        logger.debugv("logging out {0} resources ", resources.size());
-
-        GlobalRequestResult finalResult = new GlobalRequestResult();
-        for (ClientModel resource : resources) {
-            GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, realm.getNotBefore());
-            finalResult.addAll(currentResult);
-        }
-        return finalResult;
-    }
-
-    public GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource) {
-        resource.setNotBefore(Time.currentTime());
-        return logoutClient(requestUri, realm, resource, resource.getNotBefore());
-    }
-
-
-    protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
-        List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
-        if (mgmtUrls.isEmpty()) {
-            logger.debug("No management URL or no registered cluster nodes for the client " + resource.getClientId());
-            return new GlobalRequestResult();
-        }
-
-        if (logger.isDebugEnabled()) logger.debug("Send logoutClient for URLs: " + mgmtUrls);
-
-        // Propagate this to all hosts
-        GlobalRequestResult result = new GlobalRequestResult();
-        for (String mgmtUrl : mgmtUrls) {
-            if (sendLogoutRequest(realm, resource, null, null, notBefore, mgmtUrl)) {
-                result.addSuccessRequest(mgmtUrl);
-            } else {
-                result.addFailedRequest(mgmtUrl);
-            }
-        }
-        return result;
-    }
-
-    protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List<String> adapterSessionIds, List<String> userSessions, int notBefore, String managementUrl) {
-        LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), adapterSessionIds, notBefore, userSessions);
-        String token = new TokenManager().encodeToken(realm, adminAction);
-        if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getClientId(), managementUrl);
-        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build();
-        try {
-            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
-            boolean success = status == 204 || status == 200;
-            logger.debugf("logout success for %s: %s", managementUrl, success);
-            return success;
-        } catch (IOException e) {
-            logger.warn("Logout for client '" + resource.getClientId() + "' failed", e);
-            return false;
-        }
-    }
-
-    public GlobalRequestResult pushRealmRevocationPolicy(URI requestUri, RealmModel realm) {
-        GlobalRequestResult finalResult = new GlobalRequestResult();
-        for (ClientModel client : realm.getClients()) {
-            GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore());
-            finalResult.addAll(currentResult);
-        }
-        return finalResult;
-    }
-
-    public GlobalRequestResult pushClientRevocationPolicy(URI requestUri, RealmModel realm, ClientModel client) {
-        return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore());
-    }
-
-
-    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
-        List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
-        if (mgmtUrls.isEmpty()) {
-            logger.debugf("No management URL or no registered cluster nodes for the client %s", resource.getClientId());
-            return new GlobalRequestResult();
-        }
-
-        if (logger.isDebugEnabled()) logger.debug("Sending push revocation to URLS: " + mgmtUrls);
-
-        // Propagate this to all hosts
-        GlobalRequestResult result = new GlobalRequestResult();
-        for (String mgmtUrl : mgmtUrls) {
-            if (sendPushRevocationPolicyRequest(realm, resource, notBefore, mgmtUrl)) {
-                result.addSuccessRequest(mgmtUrl);
-            } else {
-                result.addFailedRequest(mgmtUrl);
-            }
-        }
-        return result;
-    }
-
-    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, String managementUrl) {
-        PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), notBefore);
-        String token = new TokenManager().encodeToken(realm, adminAction);
-        logger.infov("pushRevocation resource: {0} url: {1}", resource.getClientId(), managementUrl);
-        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build();
-        try {
-            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
-            boolean success = status == 204 || status == 200;
-            logger.debugf("pushRevocation success for %s: %s", managementUrl, success);
-            return success;
-        } catch (IOException e) {
-            logger.warn("Failed to send revocation request", e);
-            return false;
-        }
-    }
-
-    public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ClientModel client) {
-        List<String> mgmtUrls = getAllManagementUrls(requestUri, client);
-        if (mgmtUrls.isEmpty()) {
-            logger.debug("No management URL or no registered cluster nodes for the application " + client.getClientId());
-            return new GlobalRequestResult();
-        }
-
-
-        if (logger.isDebugEnabled()) logger.debug("Sending test nodes availability: " + mgmtUrls);
-
-        // Propagate this to all hosts
-        GlobalRequestResult result = new GlobalRequestResult();
-        for (String mgmtUrl : mgmtUrls) {
-            if (sendTestNodeAvailabilityRequest(realm, client, mgmtUrl)) {
-                result.addSuccessRequest(mgmtUrl);
-            } else {
-                result.addFailedRequest(mgmtUrl);
-            }
-        }
-        return result;
-    }
-
-    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, String managementUrl) {
-        TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, client.getClientId());
-        String token = new TokenManager().encodeToken(realm, adminAction);
-        logger.debugv("testNodes availability resource: {0} url: {1}", client.getClientId(), managementUrl);
-        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build();
-        try {
-            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
-            boolean success = status == 204 || status == 200;
-            logger.debugf("testAvailability success for %s: %s", managementUrl, success);
-            return success;
-        } catch (IOException e) {
-            logger.warn("Availability test failed for uri '" + managementUrl + "'", e);
-            return false;
-        }
-   }
-
-}
+package org.keycloak.services.managers;
+
+import org.jboss.logging.Logger;
+import org.keycloak.TokenIdGenerator;
+import org.keycloak.connections.httpclient.HttpClientProvider;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.representations.adapters.action.GlobalRequestResult;
+import org.keycloak.representations.adapters.action.LogoutAction;
+import org.keycloak.representations.adapters.action.PushNotBeforeAction;
+import org.keycloak.representations.adapters.action.TestAvailabilityAction;
+import org.keycloak.services.util.ResolveRelative;
+import org.keycloak.util.KeycloakUriBuilder;
+import org.keycloak.util.MultivaluedHashMap;
+import org.keycloak.util.StringPropertyReplacer;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ResourceAdminManager {
+    protected static Logger logger = Logger.getLogger(ResourceAdminManager.class);
+    private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}";
+
+    private KeycloakSession session;
+
+    public ResourceAdminManager(KeycloakSession session) {
+        this.session = session;
+    }
+
+    public static String resolveUri(URI requestUri, String uri) {
+        String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, uri);
+        return StringPropertyReplacer.replaceProperties(absoluteURI);
+
+   }
+
+    public static String getManagementUrl(URI requestUri, ClientModel client) {
+        String mgmtUrl = client.getManagementUrl();
+        if (mgmtUrl == null || mgmtUrl.equals("")) {
+            return null;
+        }
+
+        // this is to support relative admin urls when keycloak and clients are deployed on the same machine
+        String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl);
+
+        // this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
+        return StringPropertyReplacer.replaceProperties(absoluteURI);
+    }
+
+    // For non-cluster setup, return just single configured managementUrls
+    // For cluster setup, return the management Urls corresponding to all registered cluster nodes
+    private List<String> getAllManagementUrls(URI requestUri, ClientModel client) {
+        String baseMgmtUrl = getManagementUrl(requestUri, client);
+        if (baseMgmtUrl == null) {
+            return Collections.emptyList();
+        }
+
+        Set<String> registeredNodesHosts = new ClientManager().validateRegisteredNodes(client);
+
+        // No-cluster setup
+        if (registeredNodesHosts.isEmpty()) {
+            return Arrays.asList(baseMgmtUrl);
+        }
+
+        List<String> result = new LinkedList<String>();
+        KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(baseMgmtUrl);
+        for (String nodeHost : registeredNodesHosts) {
+            String currentNodeUri = uriBuilder.clone().host(nodeHost).build().toString();
+            result.add(currentNodeUri);
+        }
+
+        return result;
+    }
+
+    public void logoutUser(URI requestUri, RealmModel realm, UserModel user, KeycloakSession keycloakSession) {
+        List<UserSessionModel> userSessions = keycloakSession.sessions().getUserSessions(realm, user);
+        logoutUserSessions(requestUri, realm, userSessions);
+    }
+
+    protected void logoutUserSessions(URI requestUri, RealmModel realm, List<UserSessionModel> userSessions) {
+        // Map from "app" to clientSessions for this app
+        MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
+        for (UserSessionModel userSession : userSessions) {
+            putClientSessions(clientSessions, userSession);
+        }
+
+        logger.debugv("logging out {0} resources ", clientSessions.size());
+        //logger.infov("logging out resources: {0}", clientSessions);
+
+        for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
+            logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue());
+        }
+    }
+
+    private void putClientSessions(MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
+        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+            ClientModel client = clientSession.getClient();
+            clientSessions.add(client, clientSession);
+        }
+    }
+
+    public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user) {
+        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
+        List<ClientSessionModel> ourAppClientSessions = null;
+        if (userSessions != null) {
+            MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
+            for (UserSessionModel userSession : userSessions) {
+                putClientSessions(clientSessions, userSession);
+            }
+            ourAppClientSessions = clientSessions.get(resource);
+        }
+
+        logoutClientSessions(requestUri, realm, resource, ourAppClientSessions);
+    }
+
+    public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession) {
+        return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession));
+    }
+
+    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions) {
+        String managementUrl = getManagementUrl(requestUri, resource);
+        if (managementUrl != null) {
+
+            // Key is host, value is list of http sessions for this host
+            MultivaluedHashMap<String, String> adapterSessionIds = null;
+            List<String> userSessions = new LinkedList<>();
+            if (clientSessions != null && clientSessions.size() > 0) {
+                adapterSessionIds = new MultivaluedHashMap<String, String>();
+                for (ClientSessionModel clientSession : clientSessions) {
+                    String adapterSessionId = clientSession.getNote(AdapterConstants.CLIENT_SESSION_STATE);
+                    if (adapterSessionId != null) {
+                        String host = clientSession.getNote(AdapterConstants.CLIENT_SESSION_HOST);
+                        adapterSessionIds.add(host, adapterSessionId);
+                    }
+                    if (clientSession.getUserSession() != null) userSessions.add(clientSession.getUserSession().getId());
+                }
+            }
+
+            if (adapterSessionIds == null || adapterSessionIds.isEmpty()) {
+                logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getClientId());
+                return false;
+            }
+
+            if (managementUrl.contains(CLIENT_SESSION_HOST_PROPERTY)) {
+                boolean allPassed = true;
+                // Send logout separately to each host (needed for single-sign-out in cluster for non-distributable apps - KEYCLOAK-748)
+                for (Map.Entry<String, List<String>> entry : adapterSessionIds.entrySet()) {
+                    String host = entry.getKey();
+                    List<String> sessionIds = entry.getValue();
+                    String currentHostMgmtUrl = managementUrl.replace(CLIENT_SESSION_HOST_PROPERTY, host);
+                    allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, 0, currentHostMgmtUrl) && allPassed;
+                }
+
+                return allPassed;
+            } else {
+                // Send single logout request
+                List<String> allSessionIds = new ArrayList<String>();
+                for (List<String> currentIds : adapterSessionIds.values()) {
+                    allSessionIds.addAll(currentIds);
+                }
+
+                return sendLogoutRequest(realm, resource, allSessionIds, userSessions, 0, managementUrl);
+            }
+        } else {
+            logger.debugv("Can't logout {0}: no management url", resource.getClientId());
+            return false;
+        }
+    }
+
+    // Methods for logout all
+
+    public GlobalRequestResult logoutAll(URI requestUri, RealmModel realm) {
+        realm.setNotBefore(Time.currentTime());
+        List<ClientModel> resources = realm.getClients();
+        logger.debugv("logging out {0} resources ", resources.size());
+
+        GlobalRequestResult finalResult = new GlobalRequestResult();
+        for (ClientModel resource : resources) {
+            GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, realm.getNotBefore());
+            finalResult.addAll(currentResult);
+        }
+        return finalResult;
+    }
+
+    public GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource) {
+        resource.setNotBefore(Time.currentTime());
+        return logoutClient(requestUri, realm, resource, resource.getNotBefore());
+    }
+
+
+    protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
+        List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
+        if (mgmtUrls.isEmpty()) {
+            logger.debug("No management URL or no registered cluster nodes for the client " + resource.getClientId());
+            return new GlobalRequestResult();
+        }
+
+        if (logger.isDebugEnabled()) logger.debug("Send logoutClient for URLs: " + mgmtUrls);
+
+        // Propagate this to all hosts
+        GlobalRequestResult result = new GlobalRequestResult();
+        for (String mgmtUrl : mgmtUrls) {
+            if (sendLogoutRequest(realm, resource, null, null, notBefore, mgmtUrl)) {
+                result.addSuccessRequest(mgmtUrl);
+            } else {
+                result.addFailedRequest(mgmtUrl);
+            }
+        }
+        return result;
+    }
+
+    protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List<String> adapterSessionIds, List<String> userSessions, int notBefore, String managementUrl) {
+        LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), adapterSessionIds, notBefore, userSessions);
+        String token = new TokenManager().encodeToken(realm, adminAction);
+        if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getClientId(), managementUrl);
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build();
+        try {
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
+            logger.debugf("logout success for %s: %s", managementUrl, success);
+            return success;
+        } catch (IOException e) {
+            logger.warn("Logout for client '" + resource.getClientId() + "' failed", e);
+            return false;
+        }
+    }
+
+    public GlobalRequestResult pushRealmRevocationPolicy(URI requestUri, RealmModel realm) {
+        GlobalRequestResult finalResult = new GlobalRequestResult();
+        for (ClientModel client : realm.getClients()) {
+            GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore());
+            finalResult.addAll(currentResult);
+        }
+        return finalResult;
+    }
+
+    public GlobalRequestResult pushClientRevocationPolicy(URI requestUri, RealmModel realm, ClientModel client) {
+        return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore());
+    }
+
+
+    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore) {
+        List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
+        if (mgmtUrls.isEmpty()) {
+            logger.debugf("No management URL or no registered cluster nodes for the client %s", resource.getClientId());
+            return new GlobalRequestResult();
+        }
+
+        if (logger.isDebugEnabled()) logger.debug("Sending push revocation to URLS: " + mgmtUrls);
+
+        // Propagate this to all hosts
+        GlobalRequestResult result = new GlobalRequestResult();
+        for (String mgmtUrl : mgmtUrls) {
+            if (sendPushRevocationPolicyRequest(realm, resource, notBefore, mgmtUrl)) {
+                result.addSuccessRequest(mgmtUrl);
+            } else {
+                result.addFailedRequest(mgmtUrl);
+            }
+        }
+        return result;
+    }
+
+    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, String managementUrl) {
+        PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), notBefore);
+        String token = new TokenManager().encodeToken(realm, adminAction);
+        logger.infov("pushRevocation resource: {0} url: {1}", resource.getClientId(), managementUrl);
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build();
+        try {
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
+            logger.debugf("pushRevocation success for %s: %s", managementUrl, success);
+            return success;
+        } catch (IOException e) {
+            logger.warn("Failed to send revocation request", e);
+            return false;
+        }
+    }
+
+    public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ClientModel client) {
+        List<String> mgmtUrls = getAllManagementUrls(requestUri, client);
+        if (mgmtUrls.isEmpty()) {
+            logger.debug("No management URL or no registered cluster nodes for the application " + client.getClientId());
+            return new GlobalRequestResult();
+        }
+
+
+        if (logger.isDebugEnabled()) logger.debug("Sending test nodes availability: " + mgmtUrls);
+
+        // Propagate this to all hosts
+        GlobalRequestResult result = new GlobalRequestResult();
+        for (String mgmtUrl : mgmtUrls) {
+            if (sendTestNodeAvailabilityRequest(realm, client, mgmtUrl)) {
+                result.addSuccessRequest(mgmtUrl);
+            } else {
+                result.addFailedRequest(mgmtUrl);
+            }
+        }
+        return result;
+    }
+
+    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, String managementUrl) {
+        TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, client.getClientId());
+        String token = new TokenManager().encodeToken(realm, adminAction);
+        logger.debugv("testNodes availability resource: {0} url: {1}", client.getClientId(), managementUrl);
+        URI target = UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build();
+        try {
+            int status = session.getProvider(HttpClientProvider.class).postText(target.toString(), token);
+            boolean success = status == 204 || status == 200;
+            logger.debugf("testAvailability success for %s: %s", managementUrl, success);
+            return success;
+        } catch (IOException e) {
+            logger.warn("Availability test failed for uri '" + managementUrl + "'", e);
+            return false;
+        }
+   }
+
+}
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 6c7b5a0..2d1472b 100755
--- a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
@@ -1,246 +1,246 @@
-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;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.Urls;
-import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.managers.Auth;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.util.CookieHelper;
-import org.keycloak.util.UriUtils;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.NewCookie;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.net.URI;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Helper class for securing local services.  Provides login basics as well as CSRF check basics
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractSecuredLocalService {
-    private static final Logger logger = Logger.getLogger(AbstractSecuredLocalService.class);
-    protected final ClientModel client;
-    protected RealmModel realm;
-
-    @Context
-    protected UriInfo uriInfo;
-    @Context
-    protected HttpHeaders headers;
-    @Context
-    protected ClientConnection clientConnection;
-    protected String stateChecker;
-    @Context
-    protected KeycloakSession session;
-    @Context
-    protected HttpRequest request;
-    protected Auth auth;
-
-    public AbstractSecuredLocalService(RealmModel realm, ClientModel client) {
-        this.realm = realm;
-        this.client = client;
-    }
-
-    @Path("login-redirect")
-    @GET
-    public Response loginRedirect(@QueryParam("code") String code,
-                                  @QueryParam("state") String state,
-                                  @QueryParam("error") String error,
-                                  @QueryParam("path") String path,
-                                  @QueryParam("referrer") String referrer,
-                                  @Context HttpHeaders headers) {
-        try {
-            if (error != null) {
-                logger.debug("error from oauth");
-                throw new ForbiddenException("error");
-            }
-            if (path != null && !getValidPaths().contains(path)) {
-                throw new BadRequestException("Invalid path");
-            }
-            if (!realm.isEnabled()) {
-                logger.debug("realm not enabled");
-                throw new ForbiddenException();
-            }
-            if (!client.isEnabled()) {
-                logger.debug("account management app not enabled");
-                throw new ForbiddenException();
-            }
-            if (code == null) {
-                logger.debug("code not specified");
-                throw new BadRequestException("code not specified");
-            }
-            if (state == null) {
-                logger.debug("state not specified");
-                throw new BadRequestException("state not specified");
-            }
-
-            URI uri = getBaseRedirectUri();
-            URI redirectUri = path != null ? uri.resolve(path) : uri;
-            if (referrer != null) {
-                redirectUri = redirectUri.resolve("?referrer=" + referrer);
-            }
-
-            return Response.status(302).location(redirectUri).build();
-        } finally {
-        }
-    }
-
-    protected void updateCsrfChecks() {
-        Cookie cookie = headers.getCookies().get(AccountService.KEYCLOAK_STATE_CHECKER);
-        if (cookie != null) {
-            stateChecker = cookie.getValue();
-        } else {
-            stateChecker = UUID.randomUUID().toString();
-            String cookiePath = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
-            boolean secureOnly = realm.getSslRequired().isRequired(clientConnection);
-            CookieHelper.addCookie(AccountService.KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, -1, secureOnly, true);
-        }
-    }
-
-    protected abstract Set<String> getValidPaths();
-
-    /**
-     * Check to see if form post has sessionId hidden field and match it against the session id.
-     *
-     * @param formData
-     */
-    protected void csrfCheck(final MultivaluedMap<String, String> formData) {
-        if (!auth.isCookieAuthenticated()) return;
-        String stateChecker = formData.getFirst("stateChecker");
-        if (!this.stateChecker.equals(stateChecker)) {
-            throw new ForbiddenException();
-        }
-
-    }
-
-    /**
-     * Check to see if form post has sessionId hidden field and match it against the session id.
-     *
-     */
-    protected void csrfCheck(String stateChecker) {
-        if (!auth.isCookieAuthenticated()) return;
-        if (auth.getSession() == null) return;
-        if (!this.stateChecker.equals(stateChecker)) {
-            throw new ForbiddenException();
-        }
-
-    }
-
-    protected abstract URI getBaseRedirectUri();
-
-    protected Response login(String path) {
-        OAuthRedirect oauth = new OAuthRedirect();
-        String authUrl = OIDCLoginProtocolService.authUrl(uriInfo).build(realm.getName()).toString();
-        oauth.setAuthUrl(authUrl);
-
-        oauth.setClientId(client.getClientId());
-
-        UriBuilder uriBuilder = UriBuilder.fromUri(getBaseRedirectUri()).path("login-redirect");
-
-        if (path != null) {
-            uriBuilder.queryParam("path", path);
-        }
-
-        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
-        if (referrer != null) {
-            uriBuilder.queryParam("referrer", referrer);
-        }
-
-        String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
-        if (referrerUri != null) {
-            uriBuilder.queryParam("referrer_uri", referrerUri);
-        }
-
-        URI accountUri = uriBuilder.build(realm.getName());
-
-        oauth.setStateCookiePath(accountUri.getRawPath());
-        return oauth.redirect(uriInfo, accountUri.toString());
-    }
-
-    protected Response authenticateBrowser() {
-        AppAuthManager authManager = new AppAuthManager();
-        AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm);
-        if (authResult != null) {
-            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
-        } else {
-            return login(null);
-        }
-        // don't allow cors requests
-        // This is to prevent CSRF attacks.
-        String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());
-        String origin = headers.getRequestHeaders().getFirst("Origin");
-        if (origin != null && !requestOrigin.equals(origin)) {
-            throw new ForbiddenException();
-        }
-
-        if (!request.getHttpMethod().equals("GET")) {
-            String referrer = headers.getRequestHeaders().getFirst("Referer");
-            if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
-                throw new ForbiddenException();
-            }
-        }
-        updateCsrfChecks();
-        return null;
-    }
-
-    static class OAuthRedirect extends AbstractOAuthClient {
-
-        /**
-         * closes client
-         */
-        public void stop() {
-        }
-
-        public Response redirect(UriInfo uriInfo, String redirectUri) {
-            String state = getStateCode();
-
-            UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
-                    .queryParam(OAuth2Constants.CLIENT_ID, clientId)
-                    .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
-                    .queryParam(OAuth2Constants.STATE, state)
-                    .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
-            if (scope != null) {
-                uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
-            }
-
-            URI url = uriBuilder.build();
-
-            // todo httpOnly!
-            NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure);
-            logger.debug("NewCookie: " + cookie.toString());
-            logger.debug("Oauth Redirect to: " + url);
-            return Response.status(302)
-                    .location(url)
-                    .cookie(cookie).build();
-        }
-
-        private String getStateCookiePath(UriInfo uriInfo) {
-            if (stateCookiePath != null) return stateCookiePath;
-            return uriInfo.getBaseUri().getRawPath();
-        }
-
-    }
-
-
-}
+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;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.Auth;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.util.CookieHelper;
+import org.keycloak.util.UriUtils;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Helper class for securing local services.  Provides login basics as well as CSRF check basics
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractSecuredLocalService {
+    private static final Logger logger = Logger.getLogger(AbstractSecuredLocalService.class);
+    protected final ClientModel client;
+    protected RealmModel realm;
+
+    @Context
+    protected UriInfo uriInfo;
+    @Context
+    protected HttpHeaders headers;
+    @Context
+    protected ClientConnection clientConnection;
+    protected String stateChecker;
+    @Context
+    protected KeycloakSession session;
+    @Context
+    protected HttpRequest request;
+    protected Auth auth;
+
+    public AbstractSecuredLocalService(RealmModel realm, ClientModel client) {
+        this.realm = realm;
+        this.client = client;
+    }
+
+    @Path("login-redirect")
+    @GET
+    public Response loginRedirect(@QueryParam("code") String code,
+                                  @QueryParam("state") String state,
+                                  @QueryParam("error") String error,
+                                  @QueryParam("path") String path,
+                                  @QueryParam("referrer") String referrer,
+                                  @Context HttpHeaders headers) {
+        try {
+            if (error != null) {
+                logger.debug("error from oauth");
+                throw new ForbiddenException("error");
+            }
+            if (path != null && !getValidPaths().contains(path)) {
+                throw new BadRequestException("Invalid path");
+            }
+            if (!realm.isEnabled()) {
+                logger.debug("realm not enabled");
+                throw new ForbiddenException();
+            }
+            if (!client.isEnabled()) {
+                logger.debug("account management app not enabled");
+                throw new ForbiddenException();
+            }
+            if (code == null) {
+                logger.debug("code not specified");
+                throw new BadRequestException("code not specified");
+            }
+            if (state == null) {
+                logger.debug("state not specified");
+                throw new BadRequestException("state not specified");
+            }
+
+            URI uri = getBaseRedirectUri();
+            URI redirectUri = path != null ? uri.resolve(path) : uri;
+            if (referrer != null) {
+                redirectUri = redirectUri.resolve("?referrer=" + referrer);
+            }
+
+            return Response.status(302).location(redirectUri).build();
+        } finally {
+        }
+    }
+
+    protected void updateCsrfChecks() {
+        Cookie cookie = headers.getCookies().get(AccountService.KEYCLOAK_STATE_CHECKER);
+        if (cookie != null) {
+            stateChecker = cookie.getValue();
+        } else {
+            stateChecker = UUID.randomUUID().toString();
+            String cookiePath = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
+            boolean secureOnly = realm.getSslRequired().isRequired(clientConnection);
+            CookieHelper.addCookie(AccountService.KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, -1, secureOnly, true);
+        }
+    }
+
+    protected abstract Set<String> getValidPaths();
+
+    /**
+     * Check to see if form post has sessionId hidden field and match it against the session id.
+     *
+     * @param formData
+     */
+    protected void csrfCheck(final MultivaluedMap<String, String> formData) {
+        if (!auth.isCookieAuthenticated()) return;
+        String stateChecker = formData.getFirst("stateChecker");
+        if (!this.stateChecker.equals(stateChecker)) {
+            throw new ForbiddenException();
+        }
+
+    }
+
+    /**
+     * Check to see if form post has sessionId hidden field and match it against the session id.
+     *
+     */
+    protected void csrfCheck(String stateChecker) {
+        if (!auth.isCookieAuthenticated()) return;
+        if (auth.getSession() == null) return;
+        if (!this.stateChecker.equals(stateChecker)) {
+            throw new ForbiddenException();
+        }
+
+    }
+
+    protected abstract URI getBaseRedirectUri();
+
+    protected Response login(String path) {
+        OAuthRedirect oauth = new OAuthRedirect();
+        String authUrl = OIDCLoginProtocolService.authUrl(uriInfo).build(realm.getName()).toString();
+        oauth.setAuthUrl(authUrl);
+
+        oauth.setClientId(client.getClientId());
+
+        UriBuilder uriBuilder = UriBuilder.fromUri(getBaseRedirectUri()).path("login-redirect");
+
+        if (path != null) {
+            uriBuilder.queryParam("path", path);
+        }
+
+        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
+        if (referrer != null) {
+            uriBuilder.queryParam("referrer", referrer);
+        }
+
+        String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
+        if (referrerUri != null) {
+            uriBuilder.queryParam("referrer_uri", referrerUri);
+        }
+
+        URI accountUri = uriBuilder.build(realm.getName());
+
+        oauth.setStateCookiePath(accountUri.getRawPath());
+        return oauth.redirect(uriInfo, accountUri.toString());
+    }
+
+    protected Response authenticateBrowser() {
+        AppAuthManager authManager = new AppAuthManager();
+        AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm);
+        if (authResult != null) {
+            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
+        } else {
+            return login(null);
+        }
+        // don't allow cors requests
+        // This is to prevent CSRF attacks.
+        String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());
+        String origin = headers.getRequestHeaders().getFirst("Origin");
+        if (origin != null && !requestOrigin.equals(origin)) {
+            throw new ForbiddenException();
+        }
+
+        if (!request.getHttpMethod().equals("GET")) {
+            String referrer = headers.getRequestHeaders().getFirst("Referer");
+            if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
+                throw new ForbiddenException();
+            }
+        }
+        updateCsrfChecks();
+        return null;
+    }
+
+    static class OAuthRedirect extends AbstractOAuthClient {
+
+        /**
+         * closes client
+         */
+        public void stop() {
+        }
+
+        public Response redirect(UriInfo uriInfo, String redirectUri) {
+            String state = getStateCode();
+
+            UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
+                    .queryParam(OAuth2Constants.CLIENT_ID, clientId)
+                    .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
+                    .queryParam(OAuth2Constants.STATE, state)
+                    .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
+            if (scope != null) {
+                uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
+            }
+
+            URI url = uriBuilder.build();
+
+            // todo httpOnly!
+            NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure);
+            logger.debug("NewCookie: " + cookie.toString());
+            logger.debug("Oauth Redirect to: " + url);
+            return Response.status(302)
+                    .location(url)
+                    .cookie(cookie).build();
+        }
+
+        private String getStateCookiePath(UriInfo uriInfo) {
+            if (stateCookiePath != null) return stateCookiePath;
+            return uriInfo.getBaseUri().getRawPath();
+        }
+
+    }
+
+
+}
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 05f8c81..bd702d2 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -1,841 +1,841 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-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;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.account.AccountPages;
-import org.keycloak.account.AccountProvider;
-import org.keycloak.events.Details;
-import org.keycloak.events.Event;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventStoreProvider;
-import org.keycloak.events.EventType;
-import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.AccountRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.ModelReadOnlyException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.TimeBasedOTP;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.protocol.oidc.utils.RedirectUtils;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.Urls;
-import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.managers.Auth;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.messages.Messages;
-import org.keycloak.services.util.CookieHelper;
-import org.keycloak.services.util.ResolveRelative;
-import org.keycloak.services.validation.Validation;
-import org.keycloak.util.UriUtils;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.NewCookie;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.core.Variant;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class AccountService extends AbstractSecuredLocalService {
-
-    private static final Logger logger = Logger.getLogger(AccountService.class);
-
-    private static Set<String> VALID_PATHS = new HashSet<String>();
-    static {
-        for (Method m : AccountService.class.getMethods()) {
-            Path p = m.getAnnotation(Path.class);
-            if (p != null) {
-                VALID_PATHS.add(p.value());
-            }
-        }
-    }
-
-    private static final EventType[] LOG_EVENTS = {EventType.LOGIN, EventType.LOGOUT, EventType.REGISTER, EventType.REMOVE_FEDERATED_IDENTITY, EventType.REMOVE_TOTP, EventType.SEND_RESET_PASSWORD,
-            EventType.SEND_VERIFY_EMAIL, EventType.FEDERATED_IDENTITY_LINK, EventType.UPDATE_EMAIL, EventType.UPDATE_PASSWORD, EventType.UPDATE_PROFILE, EventType.UPDATE_TOTP, EventType.VERIFY_EMAIL};
-
-    private static final Set<String> LOG_DETAILS = new HashSet<String>();
-    static {
-        LOG_DETAILS.add(Details.UPDATED_EMAIL);
-        LOG_DETAILS.add(Details.EMAIL);
-        LOG_DETAILS.add(Details.PREVIOUS_EMAIL);
-        LOG_DETAILS.add(Details.USERNAME);
-        LOG_DETAILS.add(Details.REMEMBER_ME);
-        LOG_DETAILS.add(Details.REGISTER_METHOD);
-        LOG_DETAILS.add(Details.AUTH_METHOD);
-    }
-
-    public static final String KEYCLOAK_STATE_CHECKER = "KEYCLOAK_STATE_CHECKER";
-
-    private final AppAuthManager authManager;
-    private EventBuilder event;
-    private AccountProvider account;
-    private EventStoreProvider eventStore;
-
-    public AccountService(RealmModel realm, ClientModel client, EventBuilder event) {
-        super(realm, client);
-        this.event = event;
-        this.authManager = new AppAuthManager();
-    }
-
-    public void init() {
-        eventStore = session.getProvider(EventStoreProvider.class);
-
-        account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo).setHttpHeaders(headers);
-
-        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
-        if (authResult != null) {
-            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false);
-        } else {
-            authResult = authManager.authenticateIdentityCookie(session, realm);
-            if (authResult != null) {
-                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
-                updateCsrfChecks();
-                account.setStateChecker(stateChecker);
-            }
-        }
-
-        String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());
-
-        // don't allow cors requests unless they were authenticated by an access token
-        // This is to prevent CSRF attacks.
-        if (auth != null && auth.isCookieAuthenticated()) {
-            String origin = headers.getRequestHeaders().getFirst("Origin");
-            if (origin != null && !requestOrigin.equals(origin)) {
-                throw new ForbiddenException();
-            }
-
-            if (!request.getHttpMethod().equals("GET")) {
-                String referrer = headers.getRequestHeaders().getFirst("Referer");
-                if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
-                    throw new ForbiddenException();
-                }
-            }
-        }
-
-        if (authResult != null) {
-            UserSessionModel userSession = authResult.getSession();
-            if (userSession != null) {
-                boolean associated = false;
-                for (ClientSessionModel c : userSession.getClientSessions()) {
-                    if (c.getClient().equals(client)) {
-                        auth.setClientSession(c);
-                        associated = true;
-                        break;
-                    }
-                }
-                if (!associated) {
-                    ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
-                    clientSession.setUserSession(userSession);
-                    auth.setClientSession(clientSession);
-                }
-            }
-
-            account.setUser(auth.getUser());
-
-        }
-
-        boolean eventsEnabled = eventStore != null && realm.isEventsEnabled();
-
-        // todo find out from federation if password is updatable
-        account.setFeatures(realm.isIdentityFederationEnabled(), eventsEnabled, true);
-    }
-
-    public static UriBuilder accountServiceBaseUrl(UriInfo uriInfo) {
-        UriBuilder base = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
-        return base;
-    }
-
-    public static UriBuilder accountServiceApplicationPage(UriInfo uriInfo) {
-        return accountServiceBaseUrl(uriInfo).path(AccountService.class, "applicationsPage");
-    }
-
-    public static UriBuilder accountServiceBaseUrl(UriBuilder base) {
-        return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
-    }
-
-    protected Set<String> getValidPaths() {
-        return AccountService.VALID_PATHS;
-    }
-
-    private Response forwardToPage(String path, AccountPages page) {
-        if (auth != null) {
-            try {
-                require(AccountRoles.MANAGE_ACCOUNT);
-            } catch (ForbiddenException e) {
-                return session.getProvider(LoginFormsProvider.class).setError(Messages.NO_ACCESS).createErrorPage();
-            }
-
-            setReferrerOnPage();
-
-            return account.createResponse(page);
-        } else {
-            return login(path);
-        }
-    }
-
-    protected void setReferrerOnPage() {
-        String[] referrer = getReferrer();
-        if (referrer != null) {
-            account.setReferrer(referrer);
-        }
-    }
-
-    /**
-     * CORS preflight
-     *
-     * @return
-     */
-    @Path("/")
-    @OPTIONS
-    public Response accountPreflight() {
-        return Cors.add(request, Response.ok()).auth().preflight().build();
-    }
-
-    /**
-     * Get account information.
-     *
-     * @return
-     */
-    @Path("/")
-    @GET
-    public Response accountPage() {
-        List<MediaType> types = headers.getAcceptableMediaTypes();
-        if (types.contains(MediaType.WILDCARD_TYPE) || (types.contains(MediaType.TEXT_HTML_TYPE))) {
-            return forwardToPage(null, AccountPages.ACCOUNT);
-        } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
-            requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
-
-            UserRepresentation rep = ModelToRepresentation.toRepresentation(auth.getUser());
-            if (rep.getAttributes() != null) {
-                Iterator<String> itr = rep.getAttributes().keySet().iterator();
-                while (itr.hasNext()) {
-                    if (itr.next().startsWith("keycloak.")) {
-                        itr.remove();
-                    }
-                }
-            }
-
-            return Cors.add(request, Response.ok(rep)).auth().allowedOrigins(auth.getToken()).build();
-        } else {
-            return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
-        }
-    }
-
-    public static UriBuilder totpUrl(UriBuilder base) {
-        return RealmsResource.accountUrl(base).path(AccountService.class, "totpPage");
-    }
-    @Path("totp")
-    @GET
-    public Response totpPage() {
-        return forwardToPage("totp", AccountPages.TOTP);
-    }
-
-    public static UriBuilder passwordUrl(UriBuilder base) {
-        return RealmsResource.accountUrl(base).path(AccountService.class, "passwordPage");
-    }
-    @Path("password")
-    @GET
-    public Response passwordPage() {
-        if (auth != null) {
-            account.setPasswordSet(isPasswordSet(auth.getUser()));
-        }
-
-        return forwardToPage("password", AccountPages.PASSWORD);
-    }
-
-    @Path("identity")
-    @GET
-    public Response federatedIdentityPage() {
-        return forwardToPage("identity", AccountPages.FEDERATED_IDENTITY);
-    }
-
-    @Path("log")
-    @GET
-    public Response logPage() {
-        if (auth != null) {
-            List<Event> events = eventStore.createQuery().type(LOG_EVENTS).user(auth.getUser().getId()).maxResults(30).getResultList();
-            for (Event e : events) {
-                if (e.getDetails() != null) {
-                    Iterator<Map.Entry<String, String>> itr = e.getDetails().entrySet().iterator();
-                    while (itr.hasNext()) {
-                        if (!LOG_DETAILS.contains(itr.next().getKey())) {
-                            itr.remove();
-                        }
-                    }
-                }
-            }
-            account.setEvents(events);
-        }
-        return forwardToPage("log", AccountPages.LOG);
-    }
-
-    @Path("sessions")
-    @GET
-    public Response sessionsPage() {
-        if (auth != null) {
-            account.setSessions(session.sessions().getUserSessions(realm, auth.getUser()));
-        }
-        return forwardToPage("sessions", AccountPages.SESSIONS);
-    }
-
-    @Path("applications")
-    @GET
-    public Response applicationsPage() {
-        return forwardToPage("applications", AccountPages.APPLICATIONS);
-    }
-
-    /**
-     * Update account information.
-     *
-     * Form params:
-     *
-     * firstName
-     * lastName
-     * email
-     *
-     * @param formData
-     * @return
-     */
-    @Path("/")
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
-        if (auth == null) {
-            return login(null);
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-
-        String action = formData.getFirst("submitAction");
-        if (action != null && action.equals("Cancel")) {
-            setReferrerOnPage();
-            return account.createResponse(AccountPages.ACCOUNT);
-        }
-
-        csrfCheck(formData);
-
-        UserModel user = auth.getUser();
-
-        List<FormMessage> errors = Validation.validateUpdateProfileForm(realm, formData);
-        if (errors != null && !errors.isEmpty()) {
-            setReferrerOnPage();
-            return account.setErrors(errors).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
-        }
-
-        try {
-            if (realm.isEditUsernameAllowed()) {
-                String username = formData.getFirst("username");
-
-                UserModel existing = session.users().getUserByUsername(username, realm);
-                if (existing != null && !existing.getId().equals(user.getId())) {
-                    throw new ModelDuplicateException(Messages.USERNAME_EXISTS);
-                }
-
-                user.setUsername(username);
-            }
-            user.setFirstName(formData.getFirst("firstName"));
-            user.setLastName(formData.getFirst("lastName"));
-
-            String email = formData.getFirst("email");
-            String oldEmail = user.getEmail();
-            boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null;
-            if (emailChanged) {
-                UserModel existing = session.users().getUserByEmail(email, realm);
-                if (existing != null && !existing.getId().equals(user.getId())) {
-                    throw new ModelDuplicateException(Messages.EMAIL_EXISTS);
-                }
-            }
-
-            user.setEmail(email);
-
-            AttributeFormDataProcessor.process(formData, realm, user);
-
-            event.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()).success();
-
-            if (emailChanged) {
-                user.setEmailVerified(false);
-                event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
-            }
-            setReferrerOnPage();
-            return account.setSuccess(Messages.ACCOUNT_UPDATED).createResponse(AccountPages.ACCOUNT);
-        } catch (ModelReadOnlyException roe) {
-            setReferrerOnPage();
-            return account.setError(Messages.READ_ONLY_USER).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
-        } catch (ModelDuplicateException mde) {
-            setReferrerOnPage();
-            return account.setError(mde.getMessage()).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
-        }
-    }
-
-    @Path("totp-remove")
-    @GET
-    public Response processTotpRemove(@QueryParam("stateChecker") String stateChecker) {
-        if (auth == null) {
-            return login("totp");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-
-        csrfCheck(stateChecker);
-
-        UserModel user = auth.getUser();
-        user.setTotp(false);
-
-        event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
-
-        setReferrerOnPage();
-        return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.TOTP);
-    }
-
-
-    @Path("sessions-logout")
-    @GET
-    public Response processSessionsLogout(@QueryParam("stateChecker") String stateChecker) {
-        if (auth == null) {
-            return login("sessions");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-        csrfCheck(stateChecker);
-
-        UserModel user = auth.getUser();
-        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
-        for (UserSessionModel userSession : userSessions) {
-            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
-        }
-
-        UriBuilder builder = Urls.accountBase(uriInfo.getBaseUri()).path(AccountService.class, "sessionsPage");
-        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
-        if (referrer != null) {
-            builder.queryParam("referrer", referrer);
-
-        }
-        URI location = builder.build(realm.getName());
-        return Response.seeOther(location).build();
-    }
-
-    @Path("revoke-grant")
-    @POST
-    public Response processRevokeGrant(final MultivaluedMap<String, String> formData) {
-        if (auth == null) {
-            return login("applications");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-        csrfCheck(formData);
-
-        String clientId = formData.getFirst("clientId");
-        if (clientId == null) {
-            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
-        }
-        ClientModel client = realm.getClientById(clientId);
-        if (client == null) {
-            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
-        }
-
-        // Revoke grant in UserModel
-        UserModel user = auth.getUser();
-        user.revokeConsentForClient(client.getId());
-
-        // Logout clientSessions for this user and client
-        AuthenticationManager.backchannelUserFromClient(session, realm, user, client, uriInfo, headers);
-
-        event.event(EventType.REVOKE_GRANT).client(auth.getClient()).user(auth.getUser()).detail(Details.REVOKED_CLIENT, client.getClientId()).success();
-        setReferrerOnPage();
-
-        UriBuilder builder = Urls.accountBase(uriInfo.getBaseUri()).path(AccountService.class, "applicationsPage");
-        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
-        if (referrer != null) {
-            builder.queryParam("referrer", referrer);
-
-        }
-        URI location = builder.build(realm.getName());
-        return Response.seeOther(location).build();
-    }
-
-    /**
-     * Update the TOTP for this account.
-     *
-     * form parameters:
-     *
-     * totp - otp generated by authenticator
-     * totpSecret - totp secret to register
-     *
-     * @param formData
-     * @return
-     */
-    @Path("totp")
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
-        if (auth == null) {
-            return login("totp");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-
-        String action = formData.getFirst("submitAction");
-        if (action != null && action.equals("Cancel")) {
-            setReferrerOnPage();
-            return account.createResponse(AccountPages.TOTP);
-        }
-
-        csrfCheck(formData);
-
-        UserModel user = auth.getUser();
-
-        String totp = formData.getFirst("totp");
-        String totpSecret = formData.getFirst("totpSecret");
-
-        if (Validation.isBlank(totp)) {
-            setReferrerOnPage();
-            return account.setError(Messages.MISSING_TOTP).createResponse(AccountPages.TOTP);
-        } else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
-            setReferrerOnPage();
-            return account.setError(Messages.INVALID_TOTP).createResponse(AccountPages.TOTP);
-        }
-
-        UserCredentialModel credentials = new UserCredentialModel();
-        credentials.setType(CredentialRepresentation.TOTP);
-        credentials.setValue(totpSecret);
-        session.users().updateCredential(realm, user, credentials);
-
-        user.setTotp(true);
-
-        event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
-
-        setReferrerOnPage();
-        return account.setSuccess(Messages.SUCCESS_TOTP).createResponse(AccountPages.TOTP);
-    }
-
-    /**
-     * Update account password
-     *
-     * Form params:
-     *
-     * password - old password
-     * password-new
-     * pasword-confirm
-     *
-     * @param formData
-     * @return
-     */
-    @Path("password")
-    @POST
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
-        if (auth == null) {
-            return login("password");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-
-        String action = formData.getFirst("submitAction");
-        if (action != null && action.equals("Cancel")) {
-            setReferrerOnPage();
-            return account.createResponse(AccountPages.PASSWORD);
-        }
-
-        csrfCheck(formData);
-        UserModel user = auth.getUser();
-
-        boolean requireCurrent = isPasswordSet(user);
-        account.setPasswordSet(requireCurrent);
-
-        String password = formData.getFirst("password");
-        String passwordNew = formData.getFirst("password-new");
-        String passwordConfirm = formData.getFirst("password-confirm");
-
-        if (requireCurrent) {
-            if (Validation.isBlank(password)) {
-                setReferrerOnPage();
-                return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
-            }
-
-            UserCredentialModel cred = UserCredentialModel.password(password);
-            if (!session.users().validCredentials(realm, user, cred)) {
-                setReferrerOnPage();
-                return account.setError(Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
-            }
-        }
-
-        if (Validation.isEmpty(passwordNew)) {
-            setReferrerOnPage();
-            return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
-        }
-
-        if (!passwordNew.equals(passwordConfirm)) {
-            setReferrerOnPage();
-            return account.setError(Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD);
-        }
-
-        try {
-            session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew));
-        } catch (ModelReadOnlyException mre) {
-            setReferrerOnPage();
-            return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
-        }catch (ModelException me) {
-            logger.error("Failed to update password", me);
-            setReferrerOnPage();
-            return account.setError(me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
-        }catch (Exception ape) {
-            logger.error("Failed to update password", ape);
-            setReferrerOnPage();
-            return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
-        }
-
-        List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
-        for (UserSessionModel s : sessions) {
-            if (!s.getId().equals(auth.getSession().getId())) {
-                AuthenticationManager.backchannelLogout(session, realm, s, uriInfo, clientConnection, headers, true);
-            }
-        }
-
-        event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
-
-        setReferrerOnPage();
-        return account.setPasswordSet(true).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createResponse(AccountPages.PASSWORD);
-    }
-
-    @Path("federated-identity-update")
-    @GET
-    public Response processFederatedIdentityUpdate(@QueryParam("action") String action,
-                                                   @QueryParam("provider_id") String providerId,
-                                                   @QueryParam("stateChecker") String stateChecker) {
-        if (auth == null) {
-            return login("identity");
-        }
-
-        require(AccountRoles.MANAGE_ACCOUNT);
-        csrfCheck(stateChecker);
-        UserModel user = auth.getUser();
-
-        if (Validation.isEmpty(providerId)) {
-            setReferrerOnPage();
-            return account.setError(Messages.MISSING_IDENTITY_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
-        }
-        AccountSocialAction accountSocialAction = AccountSocialAction.getAction(action);
-        if (accountSocialAction == null) {
-            setReferrerOnPage();
-            return account.setError(Messages.INVALID_FEDERATED_IDENTITY_ACTION).createResponse(AccountPages.FEDERATED_IDENTITY);
-        }
-
-        boolean hasProvider = false;
-
-        for (IdentityProviderModel model : realm.getIdentityProviders()) {
-            if (model.getAlias().equals(providerId)) {
-                hasProvider = true;
-            }
-        }
-
-        if (!hasProvider) {
-            setReferrerOnPage();
-            return account.setError(Messages.IDENTITY_PROVIDER_NOT_FOUND).createResponse(AccountPages.FEDERATED_IDENTITY);
-        }
-
-        if (!user.isEnabled()) {
-            setReferrerOnPage();
-            return account.setError(Messages.ACCOUNT_DISABLED).createResponse(AccountPages.FEDERATED_IDENTITY);
-        }
-
-        switch (accountSocialAction) {
-            case ADD:
-                String redirectUri = UriBuilder.fromUri(Urls.accountFederatedIdentityPage(uriInfo.getBaseUri(), realm.getName())).build().toString();
-
-                try {
-                    ClientSessionModel clientSession = auth.getClientSession();
-                    ClientSessionCode clientSessionCode = new ClientSessionCode(realm, clientSession);
-                    clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-                    clientSession.setRedirectUri(redirectUri);
-                    clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
-
-                    return Response.temporaryRedirect(
-                            Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, realm.getName(), clientSessionCode.getCode()))
-                            .build();
-                } catch (Exception spe) {
-                    setReferrerOnPage();
-                    return account.setError(Messages.IDENTITY_PROVIDER_REDIRECT_ERROR).createResponse(AccountPages.FEDERATED_IDENTITY);
-                }
-            case REMOVE:
-                FederatedIdentityModel link = session.users().getFederatedIdentity(user, providerId, realm);
-                if (link != null) {
-
-                    // Removing last social provider is not possible if you don't have other possibility to authenticate
-                    if (session.users().getFederatedIdentities(user, realm).size() > 1 || user.getFederationLink() != null || isPasswordSet(user)) {
-                        session.users().removeFederatedIdentity(realm, user, providerId);
-
-                        logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());
-
-                        event.event(EventType.REMOVE_FEDERATED_IDENTITY).client(auth.getClient()).user(auth.getUser())
-                                .detail(Details.USERNAME, link.getUserId() + "@" + link.getIdentityProvider())
-                                .success();
-
-                        setReferrerOnPage();
-                        return account.setSuccess(Messages.IDENTITY_PROVIDER_REMOVED).createResponse(AccountPages.FEDERATED_IDENTITY);
-                    } else {
-                        setReferrerOnPage();
-                        return account.setError(Messages.FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
-                    }
-                } else {
-                    setReferrerOnPage();
-                    return account.setError(Messages.FEDERATED_IDENTITY_NOT_ACTIVE).createResponse(AccountPages.FEDERATED_IDENTITY);
-                }
-            default:
-                throw new IllegalArgumentException();
-        }
-    }
-
-    public static UriBuilder loginRedirectUrl(UriBuilder base) {
-        return RealmsResource.accountUrl(base).path(AccountService.class, "loginRedirect");
-    }
-
-    @Override
-    protected URI getBaseRedirectUri() {
-        return Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName());
-    }
-
-    public static boolean isPasswordSet(UserModel user) {
-        boolean passwordSet = false;
-
-        if (user.getFederationLink() != null) {
-            passwordSet = true;
-        }
-
-        for (UserCredentialValueModel c : user.getCredentialsDirectly()) {
-            if (c.getType().equals(CredentialRepresentation.PASSWORD)) {
-                passwordSet = true;
-            }
-        }
-        return passwordSet;
-    }
-
-    private String[] getReferrer() {
-        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
-        if (referrer == null) {
-            return null;
-        }
-
-        String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
-
-        ClientModel referrerClient = realm.getClientByClientId(referrer);
-        if (referrerClient != null) {
-            if (referrerUri != null) {
-                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
-            } else {
-                referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), referrerClient.getBaseUrl());
-            }
-
-            if (referrerUri != null) {
-                return new String[]{referrer, referrerUri};
-            }
-        } else if (referrerUri != null) {
-            referrerClient = realm.getClientByClientId(referrer);
-            if (client != null) {
-                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
-
-                if (referrerUri != null) {
-                    return new String[]{referrer, referrerUri};
-                }
-            }
-        }
-
-        return null;
-    }
-
-    public void require(String role) {
-        if (auth == null) {
-            throw new ForbiddenException();
-        }
-
-        if (!auth.hasClientRole(client, role)) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public void requireOneOf(String... roles) {
-        if (auth == null) {
-            throw new ForbiddenException();
-        }
-
-        if (!auth.hasOneOfAppRole(client, roles)) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public enum AccountSocialAction {
-        ADD,
-        REMOVE;
-
-        public static AccountSocialAction getAction(String action) {
-            if ("add".equalsIgnoreCase(action)) {
-                return ADD;
-            } else if ("remove".equalsIgnoreCase(action)) {
-                return REMOVE;
-            } else {
-                return null;
-            }
-        }
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+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;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.account.AccountPages;
+import org.keycloak.account.AccountProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
+import org.keycloak.models.AccountRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.ModelReadOnlyException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.TimeBasedOTP;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.protocol.oidc.utils.RedirectUtils;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.Auth;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.util.CookieHelper;
+import org.keycloak.services.util.ResolveRelative;
+import org.keycloak.services.validation.Validation;
+import org.keycloak.util.UriUtils;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Variant;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AccountService extends AbstractSecuredLocalService {
+
+    private static final Logger logger = Logger.getLogger(AccountService.class);
+
+    private static Set<String> VALID_PATHS = new HashSet<String>();
+    static {
+        for (Method m : AccountService.class.getMethods()) {
+            Path p = m.getAnnotation(Path.class);
+            if (p != null) {
+                VALID_PATHS.add(p.value());
+            }
+        }
+    }
+
+    private static final EventType[] LOG_EVENTS = {EventType.LOGIN, EventType.LOGOUT, EventType.REGISTER, EventType.REMOVE_FEDERATED_IDENTITY, EventType.REMOVE_TOTP, EventType.SEND_RESET_PASSWORD,
+            EventType.SEND_VERIFY_EMAIL, EventType.FEDERATED_IDENTITY_LINK, EventType.UPDATE_EMAIL, EventType.UPDATE_PASSWORD, EventType.UPDATE_PROFILE, EventType.UPDATE_TOTP, EventType.VERIFY_EMAIL};
+
+    private static final Set<String> LOG_DETAILS = new HashSet<String>();
+    static {
+        LOG_DETAILS.add(Details.UPDATED_EMAIL);
+        LOG_DETAILS.add(Details.EMAIL);
+        LOG_DETAILS.add(Details.PREVIOUS_EMAIL);
+        LOG_DETAILS.add(Details.USERNAME);
+        LOG_DETAILS.add(Details.REMEMBER_ME);
+        LOG_DETAILS.add(Details.REGISTER_METHOD);
+        LOG_DETAILS.add(Details.AUTH_METHOD);
+    }
+
+    public static final String KEYCLOAK_STATE_CHECKER = "KEYCLOAK_STATE_CHECKER";
+
+    private final AppAuthManager authManager;
+    private EventBuilder event;
+    private AccountProvider account;
+    private EventStoreProvider eventStore;
+
+    public AccountService(RealmModel realm, ClientModel client, EventBuilder event) {
+        super(realm, client);
+        this.event = event;
+        this.authManager = new AppAuthManager();
+    }
+
+    public void init() {
+        eventStore = session.getProvider(EventStoreProvider.class);
+
+        account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo).setHttpHeaders(headers);
+
+        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
+        if (authResult != null) {
+            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false);
+        } else {
+            authResult = authManager.authenticateIdentityCookie(session, realm);
+            if (authResult != null) {
+                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
+                updateCsrfChecks();
+                account.setStateChecker(stateChecker);
+            }
+        }
+
+        String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());
+
+        // don't allow cors requests unless they were authenticated by an access token
+        // This is to prevent CSRF attacks.
+        if (auth != null && auth.isCookieAuthenticated()) {
+            String origin = headers.getRequestHeaders().getFirst("Origin");
+            if (origin != null && !requestOrigin.equals(origin)) {
+                throw new ForbiddenException();
+            }
+
+            if (!request.getHttpMethod().equals("GET")) {
+                String referrer = headers.getRequestHeaders().getFirst("Referer");
+                if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
+                    throw new ForbiddenException();
+                }
+            }
+        }
+
+        if (authResult != null) {
+            UserSessionModel userSession = authResult.getSession();
+            if (userSession != null) {
+                boolean associated = false;
+                for (ClientSessionModel c : userSession.getClientSessions()) {
+                    if (c.getClient().equals(client)) {
+                        auth.setClientSession(c);
+                        associated = true;
+                        break;
+                    }
+                }
+                if (!associated) {
+                    ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+                    clientSession.setUserSession(userSession);
+                    auth.setClientSession(clientSession);
+                }
+            }
+
+            account.setUser(auth.getUser());
+
+        }
+
+        boolean eventsEnabled = eventStore != null && realm.isEventsEnabled();
+
+        // todo find out from federation if password is updatable
+        account.setFeatures(realm.isIdentityFederationEnabled(), eventsEnabled, true);
+    }
+
+    public static UriBuilder accountServiceBaseUrl(UriInfo uriInfo) {
+        UriBuilder base = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
+        return base;
+    }
+
+    public static UriBuilder accountServiceApplicationPage(UriInfo uriInfo) {
+        return accountServiceBaseUrl(uriInfo).path(AccountService.class, "applicationsPage");
+    }
+
+    public static UriBuilder accountServiceBaseUrl(UriBuilder base) {
+        return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
+    }
+
+    protected Set<String> getValidPaths() {
+        return AccountService.VALID_PATHS;
+    }
+
+    private Response forwardToPage(String path, AccountPages page) {
+        if (auth != null) {
+            try {
+                require(AccountRoles.MANAGE_ACCOUNT);
+            } catch (ForbiddenException e) {
+                return session.getProvider(LoginFormsProvider.class).setError(Messages.NO_ACCESS).createErrorPage();
+            }
+
+            setReferrerOnPage();
+
+            return account.createResponse(page);
+        } else {
+            return login(path);
+        }
+    }
+
+    protected void setReferrerOnPage() {
+        String[] referrer = getReferrer();
+        if (referrer != null) {
+            account.setReferrer(referrer);
+        }
+    }
+
+    /**
+     * CORS preflight
+     *
+     * @return
+     */
+    @Path("/")
+    @OPTIONS
+    public Response accountPreflight() {
+        return Cors.add(request, Response.ok()).auth().preflight().build();
+    }
+
+    /**
+     * Get account information.
+     *
+     * @return
+     */
+    @Path("/")
+    @GET
+    public Response accountPage() {
+        List<MediaType> types = headers.getAcceptableMediaTypes();
+        if (types.contains(MediaType.WILDCARD_TYPE) || (types.contains(MediaType.TEXT_HTML_TYPE))) {
+            return forwardToPage(null, AccountPages.ACCOUNT);
+        } else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
+            requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
+
+            UserRepresentation rep = ModelToRepresentation.toRepresentation(auth.getUser());
+            if (rep.getAttributes() != null) {
+                Iterator<String> itr = rep.getAttributes().keySet().iterator();
+                while (itr.hasNext()) {
+                    if (itr.next().startsWith("keycloak.")) {
+                        itr.remove();
+                    }
+                }
+            }
+
+            return Cors.add(request, Response.ok(rep)).auth().allowedOrigins(auth.getToken()).build();
+        } else {
+            return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
+        }
+    }
+
+    public static UriBuilder totpUrl(UriBuilder base) {
+        return RealmsResource.accountUrl(base).path(AccountService.class, "totpPage");
+    }
+    @Path("totp")
+    @GET
+    public Response totpPage() {
+        return forwardToPage("totp", AccountPages.TOTP);
+    }
+
+    public static UriBuilder passwordUrl(UriBuilder base) {
+        return RealmsResource.accountUrl(base).path(AccountService.class, "passwordPage");
+    }
+    @Path("password")
+    @GET
+    public Response passwordPage() {
+        if (auth != null) {
+            account.setPasswordSet(isPasswordSet(auth.getUser()));
+        }
+
+        return forwardToPage("password", AccountPages.PASSWORD);
+    }
+
+    @Path("identity")
+    @GET
+    public Response federatedIdentityPage() {
+        return forwardToPage("identity", AccountPages.FEDERATED_IDENTITY);
+    }
+
+    @Path("log")
+    @GET
+    public Response logPage() {
+        if (auth != null) {
+            List<Event> events = eventStore.createQuery().type(LOG_EVENTS).user(auth.getUser().getId()).maxResults(30).getResultList();
+            for (Event e : events) {
+                if (e.getDetails() != null) {
+                    Iterator<Map.Entry<String, String>> itr = e.getDetails().entrySet().iterator();
+                    while (itr.hasNext()) {
+                        if (!LOG_DETAILS.contains(itr.next().getKey())) {
+                            itr.remove();
+                        }
+                    }
+                }
+            }
+            account.setEvents(events);
+        }
+        return forwardToPage("log", AccountPages.LOG);
+    }
+
+    @Path("sessions")
+    @GET
+    public Response sessionsPage() {
+        if (auth != null) {
+            account.setSessions(session.sessions().getUserSessions(realm, auth.getUser()));
+        }
+        return forwardToPage("sessions", AccountPages.SESSIONS);
+    }
+
+    @Path("applications")
+    @GET
+    public Response applicationsPage() {
+        return forwardToPage("applications", AccountPages.APPLICATIONS);
+    }
+
+    /**
+     * Update account information.
+     *
+     * Form params:
+     *
+     * firstName
+     * lastName
+     * email
+     *
+     * @param formData
+     * @return
+     */
+    @Path("/")
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
+        if (auth == null) {
+            return login(null);
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+
+        String action = formData.getFirst("submitAction");
+        if (action != null && action.equals("Cancel")) {
+            setReferrerOnPage();
+            return account.createResponse(AccountPages.ACCOUNT);
+        }
+
+        csrfCheck(formData);
+
+        UserModel user = auth.getUser();
+
+        List<FormMessage> errors = Validation.validateUpdateProfileForm(realm, formData);
+        if (errors != null && !errors.isEmpty()) {
+            setReferrerOnPage();
+            return account.setErrors(errors).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
+        }
+
+        try {
+            if (realm.isEditUsernameAllowed()) {
+                String username = formData.getFirst("username");
+
+                UserModel existing = session.users().getUserByUsername(username, realm);
+                if (existing != null && !existing.getId().equals(user.getId())) {
+                    throw new ModelDuplicateException(Messages.USERNAME_EXISTS);
+                }
+
+                user.setUsername(username);
+            }
+            user.setFirstName(formData.getFirst("firstName"));
+            user.setLastName(formData.getFirst("lastName"));
+
+            String email = formData.getFirst("email");
+            String oldEmail = user.getEmail();
+            boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null;
+            if (emailChanged) {
+                UserModel existing = session.users().getUserByEmail(email, realm);
+                if (existing != null && !existing.getId().equals(user.getId())) {
+                    throw new ModelDuplicateException(Messages.EMAIL_EXISTS);
+                }
+            }
+
+            user.setEmail(email);
+
+            AttributeFormDataProcessor.process(formData, realm, user);
+
+            event.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()).success();
+
+            if (emailChanged) {
+                user.setEmailVerified(false);
+                event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
+            }
+            setReferrerOnPage();
+            return account.setSuccess(Messages.ACCOUNT_UPDATED).createResponse(AccountPages.ACCOUNT);
+        } catch (ModelReadOnlyException roe) {
+            setReferrerOnPage();
+            return account.setError(Messages.READ_ONLY_USER).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
+        } catch (ModelDuplicateException mde) {
+            setReferrerOnPage();
+            return account.setError(mde.getMessage()).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
+        }
+    }
+
+    @Path("totp-remove")
+    @GET
+    public Response processTotpRemove(@QueryParam("stateChecker") String stateChecker) {
+        if (auth == null) {
+            return login("totp");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+
+        csrfCheck(stateChecker);
+
+        UserModel user = auth.getUser();
+        user.setTotp(false);
+
+        event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
+
+        setReferrerOnPage();
+        return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.TOTP);
+    }
+
+
+    @Path("sessions-logout")
+    @GET
+    public Response processSessionsLogout(@QueryParam("stateChecker") String stateChecker) {
+        if (auth == null) {
+            return login("sessions");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+        csrfCheck(stateChecker);
+
+        UserModel user = auth.getUser();
+        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
+        for (UserSessionModel userSession : userSessions) {
+            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
+        }
+
+        UriBuilder builder = Urls.accountBase(uriInfo.getBaseUri()).path(AccountService.class, "sessionsPage");
+        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
+        if (referrer != null) {
+            builder.queryParam("referrer", referrer);
+
+        }
+        URI location = builder.build(realm.getName());
+        return Response.seeOther(location).build();
+    }
+
+    @Path("revoke-grant")
+    @POST
+    public Response processRevokeGrant(final MultivaluedMap<String, String> formData) {
+        if (auth == null) {
+            return login("applications");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+        csrfCheck(formData);
+
+        String clientId = formData.getFirst("clientId");
+        if (clientId == null) {
+            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
+        }
+        ClientModel client = realm.getClientById(clientId);
+        if (client == null) {
+            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
+        }
+
+        // Revoke grant in UserModel
+        UserModel user = auth.getUser();
+        user.revokeConsentForClient(client.getId());
+
+        // Logout clientSessions for this user and client
+        AuthenticationManager.backchannelUserFromClient(session, realm, user, client, uriInfo, headers);
+
+        event.event(EventType.REVOKE_GRANT).client(auth.getClient()).user(auth.getUser()).detail(Details.REVOKED_CLIENT, client.getClientId()).success();
+        setReferrerOnPage();
+
+        UriBuilder builder = Urls.accountBase(uriInfo.getBaseUri()).path(AccountService.class, "applicationsPage");
+        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
+        if (referrer != null) {
+            builder.queryParam("referrer", referrer);
+
+        }
+        URI location = builder.build(realm.getName());
+        return Response.seeOther(location).build();
+    }
+
+    /**
+     * Update the TOTP for this account.
+     *
+     * form parameters:
+     *
+     * totp - otp generated by authenticator
+     * totpSecret - totp secret to register
+     *
+     * @param formData
+     * @return
+     */
+    @Path("totp")
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
+        if (auth == null) {
+            return login("totp");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+
+        String action = formData.getFirst("submitAction");
+        if (action != null && action.equals("Cancel")) {
+            setReferrerOnPage();
+            return account.createResponse(AccountPages.TOTP);
+        }
+
+        csrfCheck(formData);
+
+        UserModel user = auth.getUser();
+
+        String totp = formData.getFirst("totp");
+        String totpSecret = formData.getFirst("totpSecret");
+
+        if (Validation.isBlank(totp)) {
+            setReferrerOnPage();
+            return account.setError(Messages.MISSING_TOTP).createResponse(AccountPages.TOTP);
+        } else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
+            setReferrerOnPage();
+            return account.setError(Messages.INVALID_TOTP).createResponse(AccountPages.TOTP);
+        }
+
+        UserCredentialModel credentials = new UserCredentialModel();
+        credentials.setType(CredentialRepresentation.TOTP);
+        credentials.setValue(totpSecret);
+        session.users().updateCredential(realm, user, credentials);
+
+        user.setTotp(true);
+
+        event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
+
+        setReferrerOnPage();
+        return account.setSuccess(Messages.SUCCESS_TOTP).createResponse(AccountPages.TOTP);
+    }
+
+    /**
+     * Update account password
+     *
+     * Form params:
+     *
+     * password - old password
+     * password-new
+     * pasword-confirm
+     *
+     * @param formData
+     * @return
+     */
+    @Path("password")
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
+        if (auth == null) {
+            return login("password");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+
+        String action = formData.getFirst("submitAction");
+        if (action != null && action.equals("Cancel")) {
+            setReferrerOnPage();
+            return account.createResponse(AccountPages.PASSWORD);
+        }
+
+        csrfCheck(formData);
+        UserModel user = auth.getUser();
+
+        boolean requireCurrent = isPasswordSet(user);
+        account.setPasswordSet(requireCurrent);
+
+        String password = formData.getFirst("password");
+        String passwordNew = formData.getFirst("password-new");
+        String passwordConfirm = formData.getFirst("password-confirm");
+
+        if (requireCurrent) {
+            if (Validation.isBlank(password)) {
+                setReferrerOnPage();
+                return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
+            }
+
+            UserCredentialModel cred = UserCredentialModel.password(password);
+            if (!session.users().validCredentials(realm, user, cred)) {
+                setReferrerOnPage();
+                return account.setError(Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
+            }
+        }
+
+        if (Validation.isEmpty(passwordNew)) {
+            setReferrerOnPage();
+            return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
+        }
+
+        if (!passwordNew.equals(passwordConfirm)) {
+            setReferrerOnPage();
+            return account.setError(Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD);
+        }
+
+        try {
+            session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew));
+        } catch (ModelReadOnlyException mre) {
+            setReferrerOnPage();
+            return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
+        }catch (ModelException me) {
+            logger.error("Failed to update password", me);
+            setReferrerOnPage();
+            return account.setError(me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
+        }catch (Exception ape) {
+            logger.error("Failed to update password", ape);
+            setReferrerOnPage();
+            return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
+        }
+
+        List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
+        for (UserSessionModel s : sessions) {
+            if (!s.getId().equals(auth.getSession().getId())) {
+                AuthenticationManager.backchannelLogout(session, realm, s, uriInfo, clientConnection, headers, true);
+            }
+        }
+
+        event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
+
+        setReferrerOnPage();
+        return account.setPasswordSet(true).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createResponse(AccountPages.PASSWORD);
+    }
+
+    @Path("federated-identity-update")
+    @GET
+    public Response processFederatedIdentityUpdate(@QueryParam("action") String action,
+                                                   @QueryParam("provider_id") String providerId,
+                                                   @QueryParam("stateChecker") String stateChecker) {
+        if (auth == null) {
+            return login("identity");
+        }
+
+        require(AccountRoles.MANAGE_ACCOUNT);
+        csrfCheck(stateChecker);
+        UserModel user = auth.getUser();
+
+        if (Validation.isEmpty(providerId)) {
+            setReferrerOnPage();
+            return account.setError(Messages.MISSING_IDENTITY_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
+        }
+        AccountSocialAction accountSocialAction = AccountSocialAction.getAction(action);
+        if (accountSocialAction == null) {
+            setReferrerOnPage();
+            return account.setError(Messages.INVALID_FEDERATED_IDENTITY_ACTION).createResponse(AccountPages.FEDERATED_IDENTITY);
+        }
+
+        boolean hasProvider = false;
+
+        for (IdentityProviderModel model : realm.getIdentityProviders()) {
+            if (model.getAlias().equals(providerId)) {
+                hasProvider = true;
+            }
+        }
+
+        if (!hasProvider) {
+            setReferrerOnPage();
+            return account.setError(Messages.IDENTITY_PROVIDER_NOT_FOUND).createResponse(AccountPages.FEDERATED_IDENTITY);
+        }
+
+        if (!user.isEnabled()) {
+            setReferrerOnPage();
+            return account.setError(Messages.ACCOUNT_DISABLED).createResponse(AccountPages.FEDERATED_IDENTITY);
+        }
+
+        switch (accountSocialAction) {
+            case ADD:
+                String redirectUri = UriBuilder.fromUri(Urls.accountFederatedIdentityPage(uriInfo.getBaseUri(), realm.getName())).build().toString();
+
+                try {
+                    ClientSessionModel clientSession = auth.getClientSession();
+                    ClientSessionCode clientSessionCode = new ClientSessionCode(realm, clientSession);
+                    clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+                    clientSession.setRedirectUri(redirectUri);
+                    clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
+
+                    return Response.temporaryRedirect(
+                            Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, realm.getName(), clientSessionCode.getCode()))
+                            .build();
+                } catch (Exception spe) {
+                    setReferrerOnPage();
+                    return account.setError(Messages.IDENTITY_PROVIDER_REDIRECT_ERROR).createResponse(AccountPages.FEDERATED_IDENTITY);
+                }
+            case REMOVE:
+                FederatedIdentityModel link = session.users().getFederatedIdentity(user, providerId, realm);
+                if (link != null) {
+
+                    // Removing last social provider is not possible if you don't have other possibility to authenticate
+                    if (session.users().getFederatedIdentities(user, realm).size() > 1 || user.getFederationLink() != null || isPasswordSet(user)) {
+                        session.users().removeFederatedIdentity(realm, user, providerId);
+
+                        logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());
+
+                        event.event(EventType.REMOVE_FEDERATED_IDENTITY).client(auth.getClient()).user(auth.getUser())
+                                .detail(Details.USERNAME, link.getUserId() + "@" + link.getIdentityProvider())
+                                .success();
+
+                        setReferrerOnPage();
+                        return account.setSuccess(Messages.IDENTITY_PROVIDER_REMOVED).createResponse(AccountPages.FEDERATED_IDENTITY);
+                    } else {
+                        setReferrerOnPage();
+                        return account.setError(Messages.FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER).createResponse(AccountPages.FEDERATED_IDENTITY);
+                    }
+                } else {
+                    setReferrerOnPage();
+                    return account.setError(Messages.FEDERATED_IDENTITY_NOT_ACTIVE).createResponse(AccountPages.FEDERATED_IDENTITY);
+                }
+            default:
+                throw new IllegalArgumentException();
+        }
+    }
+
+    public static UriBuilder loginRedirectUrl(UriBuilder base) {
+        return RealmsResource.accountUrl(base).path(AccountService.class, "loginRedirect");
+    }
+
+    @Override
+    protected URI getBaseRedirectUri() {
+        return Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName());
+    }
+
+    public static boolean isPasswordSet(UserModel user) {
+        boolean passwordSet = false;
+
+        if (user.getFederationLink() != null) {
+            passwordSet = true;
+        }
+
+        for (UserCredentialValueModel c : user.getCredentialsDirectly()) {
+            if (c.getType().equals(CredentialRepresentation.PASSWORD)) {
+                passwordSet = true;
+            }
+        }
+        return passwordSet;
+    }
+
+    private String[] getReferrer() {
+        String referrer = uriInfo.getQueryParameters().getFirst("referrer");
+        if (referrer == null) {
+            return null;
+        }
+
+        String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
+
+        ClientModel referrerClient = realm.getClientByClientId(referrer);
+        if (referrerClient != null) {
+            if (referrerUri != null) {
+                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
+            } else {
+                referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), referrerClient.getBaseUrl());
+            }
+
+            if (referrerUri != null) {
+                return new String[]{referrer, referrerUri};
+            }
+        } else if (referrerUri != null) {
+            referrerClient = realm.getClientByClientId(referrer);
+            if (client != null) {
+                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
+
+                if (referrerUri != null) {
+                    return new String[]{referrer, referrerUri};
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void require(String role) {
+        if (auth == null) {
+            throw new ForbiddenException();
+        }
+
+        if (!auth.hasClientRole(client, role)) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public void requireOneOf(String... roles) {
+        if (auth == null) {
+            throw new ForbiddenException();
+        }
+
+        if (!auth.hasOneOfAppRole(client, roles)) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public enum AccountSocialAction {
+        ADD,
+        REMOVE;
+
+        public static AccountSocialAction getAction(String action) {
+            if ("add".equalsIgnoreCase(action)) {
+                return ADD;
+            } else if ("remove".equalsIgnoreCase(action)) {
+                return REMOVE;
+            } else {
+                return null;
+            }
+        }
+    }
+}
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 6b2db7b..e3bde40 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -1,305 +1,305 @@
-package org.keycloak.services.resources.admin;
-
-import org.codehaus.jackson.annotate.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;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.ClientConnection;
-import org.keycloak.Version;
-import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
-import org.keycloak.freemarker.FreeMarkerException;
-import org.keycloak.freemarker.FreeMarkerUtil;
-import org.keycloak.freemarker.Theme;
-import org.keycloak.freemarker.ThemeProvider;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.managers.ClientManager;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.Urls;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.Providers;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AdminConsole {
-    protected static final Logger logger = Logger.getLogger(AdminConsole.class);
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected ClientConnection clientConnection;
-
-    @Context
-    protected HttpRequest request;
-
-    @Context
-    protected HttpResponse response;
-
-    @Context
-    protected KeycloakSession session;
-
-    @Context
-    protected Providers providers;
-
-    @Context
-    protected KeycloakApplication keycloak;
-
-    protected AppAuthManager authManager;
-    protected RealmModel realm;
-
-    public AdminConsole(RealmModel realm) {
-        this.realm = realm;
-        this.authManager = new AppAuthManager();
-    }
-
-    public static class WhoAmI {
-        protected String userId;
-        protected String realm;
-        protected String displayName;
-
-        @JsonProperty("createRealm")
-        protected boolean createRealm;
-        @JsonProperty("realm_access")
-        protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
-
-        public WhoAmI() {
-        }
-
-        public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
-            this.userId = userId;
-            this.realm = realm;
-            this.displayName = displayName;
-            this.createRealm = createRealm;
-            this.realmAccess = realmAccess;
-        }
-
-        public String getUserId() {
-            return userId;
-        }
-
-        public void setUserId(String userId) {
-            this.userId = userId;
-        }
-
-        public String getRealm() {
-            return realm;
-        }
-
-        public void setRealm(String realm) {
-            this.realm = realm;
-        }
-
-        public String getDisplayName() {
-            return displayName;
-        }
-
-        public void setDisplayName(String displayName) {
-            this.displayName = displayName;
-        }
-
-        public boolean isCreateRealm() {
-            return createRealm;
-        }
-
-        public void setCreateRealm(boolean createRealm) {
-            this.createRealm = createRealm;
-        }
-
-        public Map<String, Set<String>> getRealmAccess() {
-            return realmAccess;
-        }
-
-        public void setRealmAccess(Map<String, Set<String>> realmAccess) {
-            this.realmAccess = realmAccess;
-        }
-    }
-
-    /**
-     * Adapter configuration for the admin console for this realm
-     *
-     * @return
-     */
-    @Path("config")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public ClientManager.InstallationAdapterConfig config() {
-        ClientModel consoleApp = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
-        if (consoleApp == null) {
-            throw new NotFoundException("Could not find admin console client");
-        }
-        return new ClientManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
-
-    }
-
-    /**
-     * Permission information
-     *
-     * @param headers
-     * @return
-     */
-    @Path("whoami")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public Response whoAmI(final @Context HttpHeaders headers) {
-        RealmManager realmManager = new RealmManager(session);
-        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
-        if (authResult == null) {
-            return Response.status(401).build();
-        }
-        UserModel user= authResult.getUser();
-        String displayName;
-        if ((user.getFirstName() != null && !user.getFirstName().trim().equals("")) || (user.getLastName() != null && !user.getLastName().trim().equals(""))) {
-            displayName = user.getFirstName();
-            if (user.getLastName() != null) {
-                displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
-            }
-        } else {
-            displayName = user.getUsername();
-        }
-
-        RealmModel masterRealm = getAdminstrationRealm(realmManager);
-        Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
-        if (masterRealm == null)
-            throw new NotFoundException("No realm found");
-        boolean createRealm = false;
-        if (realm.equals(masterRealm)) {
-            logger.debug("setting up realm access for a master realm user");
-            createRealm = user.hasRole(masterRealm.getRole(AdminRoles.CREATE_REALM));
-            addMasterRealmAccess(realm, user, realmAccess);
-        } else {
-            logger.debug("setting up realm access for a realm user");
-            addRealmAccess(realm, user, realmAccess);
-        }
-
-        return Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess)).build();
-    }
-
-    private void addRealmAccess(RealmModel realm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
-        RealmManager realmManager = new RealmManager(session);
-        ClientModel realmAdminApp = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm));
-        Set<RoleModel> roles = realmAdminApp.getRoles();
-        for (RoleModel role : roles) {
-            if (!user.hasRole(role)) continue;
-            if (!realmAdminAccess.containsKey(realm.getName())) {
-                realmAdminAccess.put(realm.getName(), new HashSet<String>());
-            }
-            realmAdminAccess.get(realm.getName()).add(role.getName());
-        }
-
-    }
-
-    private void addMasterRealmAccess(RealmModel masterRealm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
-        List<RealmModel> realms = session.realms().getRealms();
-        for (RealmModel realm : realms) {
-            ClientModel realmAdminApp = realm.getMasterAdminClient();
-            Set<RoleModel> roles = realmAdminApp.getRoles();
-            for (RoleModel role : roles) {
-                if (!user.hasRole(role)) continue;
-                if (!realmAdminAccess.containsKey(realm.getName())) {
-                    realmAdminAccess.put(realm.getName(), new HashSet<String>());
-                }
-                realmAdminAccess.get(realm.getName()).add(role.getName());
-            }
-        }
-    }
-
-    /**
-     * Logout from the admin console
-     *
-     * @return
-     */
-    @Path("logout")
-    @GET
-    @NoCache
-    public Response logout() {
-        URI redirect = AdminRoot.adminConsoleUrl(uriInfo).build(realm.getName());
-
-        return Response.status(302).location(
-                OIDCLoginProtocolService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
-        ).build();
-    }
-
-    protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
-        return realmManager.getKeycloakAdminstrationRealm();
-    }
-
-    /**
-     * Main page of this realm's admin console
-     *
-     * @return
-     * @throws URISyntaxException
-     */
-    @GET
-    @NoCache
-    public Response getMainPage() throws URISyntaxException, IOException, FreeMarkerException {
-        if (!uriInfo.getRequestUri().getPath().endsWith("/")) {
-            return Response.status(302).location(uriInfo.getRequestUriBuilder().path("/").build()).build();
-        } else {
-            String adminTheme = realm.getAdminTheme();
-            if (adminTheme == null) {
-                adminTheme = "keycloak";
-            }
-
-            Map<String, Object> map = new HashMap<>();
-
-            URI baseUri = uriInfo.getBaseUri();
-
-            String authUrl = baseUri.toString();
-            authUrl = authUrl.substring(0, authUrl.length() - 1);
-
-            map.put("authUrl", authUrl);
-            map.put("resourceUrl", Urls.themeRoot(baseUri) + "/admin/" + adminTheme);
-            map.put("resourceVersion", Version.RESOURCES_VERSION);
-
-            ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
-            Theme theme = themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
-
-            map.put("properties", theme.getProperties());
-
-            FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil();
-            String result = freeMarkerUtil.processTemplate(map, "index.ftl", theme);
-            Response.ResponseBuilder builder = Response.status(Response.Status.OK).type(MediaType.TEXT_HTML).entity(result);
-            BrowserSecurityHeaderSetup.headers(builder, realm);
-            return builder.build();
-        }
-    }
-
-    @GET
-    @Path("{indexhtml: index.html}") // this expression is a hack to get around jaxdoclet generation bug.  Doesn't like index.html
-    public Response getIndexHtmlRedirect() {
-        return Response.status(302).location(uriInfo.getRequestUriBuilder().path("../").build()).build();
-    }
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.codehaus.jackson.annotate.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;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.ClientConnection;
+import org.keycloak.Version;
+import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
+import org.keycloak.freemarker.FreeMarkerException;
+import org.keycloak.freemarker.FreeMarkerUtil;
+import org.keycloak.freemarker.Theme;
+import org.keycloak.freemarker.ThemeProvider;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.ClientManager;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.Urls;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AdminConsole {
+    protected static final Logger logger = Logger.getLogger(AdminConsole.class);
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected ClientConnection clientConnection;
+
+    @Context
+    protected HttpRequest request;
+
+    @Context
+    protected HttpResponse response;
+
+    @Context
+    protected KeycloakSession session;
+
+    @Context
+    protected Providers providers;
+
+    @Context
+    protected KeycloakApplication keycloak;
+
+    protected AppAuthManager authManager;
+    protected RealmModel realm;
+
+    public AdminConsole(RealmModel realm) {
+        this.realm = realm;
+        this.authManager = new AppAuthManager();
+    }
+
+    public static class WhoAmI {
+        protected String userId;
+        protected String realm;
+        protected String displayName;
+
+        @JsonProperty("createRealm")
+        protected boolean createRealm;
+        @JsonProperty("realm_access")
+        protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
+
+        public WhoAmI() {
+        }
+
+        public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
+            this.userId = userId;
+            this.realm = realm;
+            this.displayName = displayName;
+            this.createRealm = createRealm;
+            this.realmAccess = realmAccess;
+        }
+
+        public String getUserId() {
+            return userId;
+        }
+
+        public void setUserId(String userId) {
+            this.userId = userId;
+        }
+
+        public String getRealm() {
+            return realm;
+        }
+
+        public void setRealm(String realm) {
+            this.realm = realm;
+        }
+
+        public String getDisplayName() {
+            return displayName;
+        }
+
+        public void setDisplayName(String displayName) {
+            this.displayName = displayName;
+        }
+
+        public boolean isCreateRealm() {
+            return createRealm;
+        }
+
+        public void setCreateRealm(boolean createRealm) {
+            this.createRealm = createRealm;
+        }
+
+        public Map<String, Set<String>> getRealmAccess() {
+            return realmAccess;
+        }
+
+        public void setRealmAccess(Map<String, Set<String>> realmAccess) {
+            this.realmAccess = realmAccess;
+        }
+    }
+
+    /**
+     * Adapter configuration for the admin console for this realm
+     *
+     * @return
+     */
+    @Path("config")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public ClientManager.InstallationAdapterConfig config() {
+        ClientModel consoleApp = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
+        if (consoleApp == null) {
+            throw new NotFoundException("Could not find admin console client");
+        }
+        return new ClientManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
+
+    }
+
+    /**
+     * Permission information
+     *
+     * @param headers
+     * @return
+     */
+    @Path("whoami")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public Response whoAmI(final @Context HttpHeaders headers) {
+        RealmManager realmManager = new RealmManager(session);
+        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
+        if (authResult == null) {
+            return Response.status(401).build();
+        }
+        UserModel user= authResult.getUser();
+        String displayName;
+        if ((user.getFirstName() != null && !user.getFirstName().trim().equals("")) || (user.getLastName() != null && !user.getLastName().trim().equals(""))) {
+            displayName = user.getFirstName();
+            if (user.getLastName() != null) {
+                displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
+            }
+        } else {
+            displayName = user.getUsername();
+        }
+
+        RealmModel masterRealm = getAdminstrationRealm(realmManager);
+        Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
+        if (masterRealm == null)
+            throw new NotFoundException("No realm found");
+        boolean createRealm = false;
+        if (realm.equals(masterRealm)) {
+            logger.debug("setting up realm access for a master realm user");
+            createRealm = user.hasRole(masterRealm.getRole(AdminRoles.CREATE_REALM));
+            addMasterRealmAccess(realm, user, realmAccess);
+        } else {
+            logger.debug("setting up realm access for a realm user");
+            addRealmAccess(realm, user, realmAccess);
+        }
+
+        return Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess)).build();
+    }
+
+    private void addRealmAccess(RealmModel realm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
+        RealmManager realmManager = new RealmManager(session);
+        ClientModel realmAdminApp = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm));
+        Set<RoleModel> roles = realmAdminApp.getRoles();
+        for (RoleModel role : roles) {
+            if (!user.hasRole(role)) continue;
+            if (!realmAdminAccess.containsKey(realm.getName())) {
+                realmAdminAccess.put(realm.getName(), new HashSet<String>());
+            }
+            realmAdminAccess.get(realm.getName()).add(role.getName());
+        }
+
+    }
+
+    private void addMasterRealmAccess(RealmModel masterRealm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
+        List<RealmModel> realms = session.realms().getRealms();
+        for (RealmModel realm : realms) {
+            ClientModel realmAdminApp = realm.getMasterAdminClient();
+            Set<RoleModel> roles = realmAdminApp.getRoles();
+            for (RoleModel role : roles) {
+                if (!user.hasRole(role)) continue;
+                if (!realmAdminAccess.containsKey(realm.getName())) {
+                    realmAdminAccess.put(realm.getName(), new HashSet<String>());
+                }
+                realmAdminAccess.get(realm.getName()).add(role.getName());
+            }
+        }
+    }
+
+    /**
+     * Logout from the admin console
+     *
+     * @return
+     */
+    @Path("logout")
+    @GET
+    @NoCache
+    public Response logout() {
+        URI redirect = AdminRoot.adminConsoleUrl(uriInfo).build(realm.getName());
+
+        return Response.status(302).location(
+                OIDCLoginProtocolService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
+        ).build();
+    }
+
+    protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
+        return realmManager.getKeycloakAdminstrationRealm();
+    }
+
+    /**
+     * Main page of this realm's admin console
+     *
+     * @return
+     * @throws URISyntaxException
+     */
+    @GET
+    @NoCache
+    public Response getMainPage() throws URISyntaxException, IOException, FreeMarkerException {
+        if (!uriInfo.getRequestUri().getPath().endsWith("/")) {
+            return Response.status(302).location(uriInfo.getRequestUriBuilder().path("/").build()).build();
+        } else {
+            String adminTheme = realm.getAdminTheme();
+            if (adminTheme == null) {
+                adminTheme = "keycloak";
+            }
+
+            Map<String, Object> map = new HashMap<>();
+
+            URI baseUri = uriInfo.getBaseUri();
+
+            String authUrl = baseUri.toString();
+            authUrl = authUrl.substring(0, authUrl.length() - 1);
+
+            map.put("authUrl", authUrl);
+            map.put("resourceUrl", Urls.themeRoot(baseUri) + "/admin/" + adminTheme);
+            map.put("resourceVersion", Version.RESOURCES_VERSION);
+
+            ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
+            Theme theme = themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
+
+            map.put("properties", theme.getProperties());
+
+            FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil();
+            String result = freeMarkerUtil.processTemplate(map, "index.ftl", theme);
+            Response.ResponseBuilder builder = Response.status(Response.Status.OK).type(MediaType.TEXT_HTML).entity(result);
+            BrowserSecurityHeaderSetup.headers(builder, realm);
+            return builder.build();
+        }
+    }
+
+    @GET
+    @Path("{indexhtml: index.html}") // this expression is a hack to get around jaxdoclet generation bug.  Doesn't like index.html
+    public Response getIndexHtmlRedirect() {
+        return Response.status(302).location(uriInfo.getRequestUriBuilder().path("../").build()).build();
+    }
+
+}
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 55861d0..e1d1fa3 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
@@ -1,249 +1,249 @@
-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;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.jboss.resteasy.spi.UnauthorizedException;
-import org.keycloak.ClientConnection;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-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.managers.AppAuthManager;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.Cors;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-import java.io.IOException;
-
-/**
- * Root resource for admin console and admin REST API
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Path("/admin")
-public class AdminRoot {
-    protected static final Logger logger = Logger.getLogger(AdminRoot.class);
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected ClientConnection clientConnection;
-
-    @Context
-    protected HttpRequest request;
-
-    @Context
-    protected HttpResponse response;
-
-    protected AppAuthManager authManager;
-    protected TokenManager tokenManager;
-
-    @Context
-    protected KeycloakSession session;
-
-    public AdminRoot() {
-        this.tokenManager = new TokenManager();
-        this.authManager = new AppAuthManager();
-    }
-
-    public static UriBuilder adminBaseUrl(UriInfo uriInfo) {
-        return adminBaseUrl(uriInfo.getBaseUriBuilder());
-    }
-
-    public static UriBuilder adminBaseUrl(UriBuilder base) {
-        return base.path(AdminRoot.class);
-    }
-
-    /**
-     * Convenience path to master realm admin console
-     *
-     * @return
-     */
-    @GET
-    public Response masterRealmAdminConsoleRedirect() {
-        RealmModel master = new RealmManager(session).getKeycloakAdminstrationRealm();
-        return Response.status(302).location(
-                uriInfo.getBaseUriBuilder().path(AdminRoot.class).path(AdminRoot.class, "getAdminConsole").path("/").build(master.getName())
-        ).build();
-    }
-
-    /**
-     * Convenience path to master realm admin console
-     *
-     * @return
-     */
-    @Path("index.{html:html}") // expression is actually "index.html" but this is a hack to get around jax-doclet bug
-    @GET
-    public Response masterRealmAdminConsoleRedirectHtml() {
-        return masterRealmAdminConsoleRedirect();
-    }
-
-    protected RealmModel locateRealm(String name, RealmManager realmManager) {
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) {
-            throw new NotFoundException("Realm " + name + " not found");
-        }
-        return realm;
-    }
-
-
-    public static UriBuilder adminConsoleUrl(UriInfo uriInfo) {
-        return adminConsoleUrl(uriInfo.getBaseUriBuilder());
-    }
-
-    public static UriBuilder adminConsoleUrl(UriBuilder base) {
-        return adminBaseUrl(base).path(AdminRoot.class, "getAdminConsole");
-    }
-
-    /**
-     * path to realm admin console ui
-     *
-     * @param name Realm name (not id!)
-     * @return
-     */
-    @Path("{realm}/console")
-    public AdminConsole getAdminConsole(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
-        AdminConsole service = new AdminConsole(realm);
-        ResteasyProviderFactory.getInstance().injectProperties(service);
-        return service;
-    }
-
-
-    protected AdminAuth authenticateRealmAdminRequest(HttpHeaders headers) {
-        String tokenString = authManager.extractAuthorizationHeaderToken(headers);
-        if (tokenString == null) throw new UnauthorizedException("Bearer");
-        JWSInput input = new JWSInput(tokenString);
-        AccessToken token;
-        try {
-            token = input.readJsonContent(AccessToken.class);
-        } catch (IOException e) {
-            throw new UnauthorizedException("Bearer token format error");
-        }
-        String realmName = token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(realmName);
-        if (realm == null) {
-            throw new UnauthorizedException("Unknown realm in token");
-        }
-        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
-        if (authResult == null) {
-            logger.debug("Token not valid");
-            throw new UnauthorizedException("Bearer");
-        }
-
-        ClientModel client = realm.getClientByClientId(token.getIssuedFor());
-        if (client == null) {
-            throw new NotFoundException("Could not find client for authorization");
-
-        }
-
-        return new AdminAuth(realm, authResult.getToken(), authResult.getUser(), client);
-    }
-
-    public static UriBuilder realmsUrl(UriInfo uriInfo) {
-        return realmsUrl(uriInfo.getBaseUriBuilder());
-    }
-
-    public static UriBuilder realmsUrl(UriBuilder base) {
-        return adminBaseUrl(base).path(AdminRoot.class, "getRealmsAdmin");
-    }
-
-
-    /**
-     * Base Path to realm admin REST interface
-     *
-     * @param headers
-     * @return
-     */
-    @Path("realms")
-    public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
-        handlePreflightRequest();
-
-        AdminAuth auth = authenticateRealmAdminRequest(headers);
-        if (auth != null) {
-            logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
-        }
-
-        Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
-        
-        RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
-        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
-        return adminResource;
-    }
-
-    /**
-     * General information about the server
-     *
-     * @param headers
-     * @return
-     */
-    @Path("serverinfo")
-    public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
-        handlePreflightRequest();
-
-        AdminAuth auth = authenticateRealmAdminRequest(headers);
-        if (!isAdmin(auth)) {
-            throw new ForbiddenException();
-        }
-
-        if (auth != null) {
-            logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
-        }
-
-        Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
-
-        ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
-        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
-        return adminResource;
-    }
-
-    protected boolean isAdmin(AdminAuth auth) {
-
-        RealmManager realmManager = new RealmManager(session);
-        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            if (auth.hasOneOfRealmRole(AdminRoles.ADMIN, AdminRoles.CREATE_REALM)) {
-                return true;
-            }
-            for (RealmModel realm : session.realms().getRealms()) {
-                ClientModel client = realm.getMasterAdminClient();
-                if (auth.hasOneOfAppRole(client, AdminRoles.ALL_REALM_ROLES)) {
-                    return true;
-                }
-            }
-            return false;
-        } else {
-            ClientModel client = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
-            return auth.hasOneOfAppRole(client, AdminRoles.ALL_REALM_ROLES);
-        }
-    }
-
-    protected void handlePreflightRequest() {
-        if (request.getHttpMethod().equalsIgnoreCase("OPTIONS")) {
-            logger.debug("Cors admin pre-flight");
-            Response response = Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
-            throw new NoLogWebApplicationException(response);
-        }
-    }
-
-}
+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;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.jboss.resteasy.spi.UnauthorizedException;
+import org.keycloak.ClientConnection;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+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.managers.AppAuthManager;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.Cors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import java.io.IOException;
+
+/**
+ * Root resource for admin console and admin REST API
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Path("/admin")
+public class AdminRoot {
+    protected static final Logger logger = Logger.getLogger(AdminRoot.class);
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected ClientConnection clientConnection;
+
+    @Context
+    protected HttpRequest request;
+
+    @Context
+    protected HttpResponse response;
+
+    protected AppAuthManager authManager;
+    protected TokenManager tokenManager;
+
+    @Context
+    protected KeycloakSession session;
+
+    public AdminRoot() {
+        this.tokenManager = new TokenManager();
+        this.authManager = new AppAuthManager();
+    }
+
+    public static UriBuilder adminBaseUrl(UriInfo uriInfo) {
+        return adminBaseUrl(uriInfo.getBaseUriBuilder());
+    }
+
+    public static UriBuilder adminBaseUrl(UriBuilder base) {
+        return base.path(AdminRoot.class);
+    }
+
+    /**
+     * Convenience path to master realm admin console
+     *
+     * @return
+     */
+    @GET
+    public Response masterRealmAdminConsoleRedirect() {
+        RealmModel master = new RealmManager(session).getKeycloakAdminstrationRealm();
+        return Response.status(302).location(
+                uriInfo.getBaseUriBuilder().path(AdminRoot.class).path(AdminRoot.class, "getAdminConsole").path("/").build(master.getName())
+        ).build();
+    }
+
+    /**
+     * Convenience path to master realm admin console
+     *
+     * @return
+     */
+    @Path("index.{html:html}") // expression is actually "index.html" but this is a hack to get around jax-doclet bug
+    @GET
+    public Response masterRealmAdminConsoleRedirectHtml() {
+        return masterRealmAdminConsoleRedirect();
+    }
+
+    protected RealmModel locateRealm(String name, RealmManager realmManager) {
+        RealmModel realm = realmManager.getRealmByName(name);
+        if (realm == null) {
+            throw new NotFoundException("Realm " + name + " not found");
+        }
+        return realm;
+    }
+
+
+    public static UriBuilder adminConsoleUrl(UriInfo uriInfo) {
+        return adminConsoleUrl(uriInfo.getBaseUriBuilder());
+    }
+
+    public static UriBuilder adminConsoleUrl(UriBuilder base) {
+        return adminBaseUrl(base).path(AdminRoot.class, "getAdminConsole");
+    }
+
+    /**
+     * path to realm admin console ui
+     *
+     * @param name Realm name (not id!)
+     * @return
+     */
+    @Path("{realm}/console")
+    public AdminConsole getAdminConsole(final @PathParam("realm") String name) {
+        RealmManager realmManager = new RealmManager(session);
+        RealmModel realm = locateRealm(name, realmManager);
+        AdminConsole service = new AdminConsole(realm);
+        ResteasyProviderFactory.getInstance().injectProperties(service);
+        return service;
+    }
+
+
+    protected AdminAuth authenticateRealmAdminRequest(HttpHeaders headers) {
+        String tokenString = authManager.extractAuthorizationHeaderToken(headers);
+        if (tokenString == null) throw new UnauthorizedException("Bearer");
+        JWSInput input = new JWSInput(tokenString);
+        AccessToken token;
+        try {
+            token = input.readJsonContent(AccessToken.class);
+        } catch (IOException e) {
+            throw new UnauthorizedException("Bearer token format error");
+        }
+        String realmName = token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
+        RealmManager realmManager = new RealmManager(session);
+        RealmModel realm = realmManager.getRealmByName(realmName);
+        if (realm == null) {
+            throw new UnauthorizedException("Unknown realm in token");
+        }
+        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
+        if (authResult == null) {
+            logger.debug("Token not valid");
+            throw new UnauthorizedException("Bearer");
+        }
+
+        ClientModel client = realm.getClientByClientId(token.getIssuedFor());
+        if (client == null) {
+            throw new NotFoundException("Could not find client for authorization");
+
+        }
+
+        return new AdminAuth(realm, authResult.getToken(), authResult.getUser(), client);
+    }
+
+    public static UriBuilder realmsUrl(UriInfo uriInfo) {
+        return realmsUrl(uriInfo.getBaseUriBuilder());
+    }
+
+    public static UriBuilder realmsUrl(UriBuilder base) {
+        return adminBaseUrl(base).path(AdminRoot.class, "getRealmsAdmin");
+    }
+
+
+    /**
+     * Base Path to realm admin REST interface
+     *
+     * @param headers
+     * @return
+     */
+    @Path("realms")
+    public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
+        handlePreflightRequest();
+
+        AdminAuth auth = authenticateRealmAdminRequest(headers);
+        if (auth != null) {
+            logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
+        }
+
+        Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
+        
+        RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
+        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
+        return adminResource;
+    }
+
+    /**
+     * General information about the server
+     *
+     * @param headers
+     * @return
+     */
+    @Path("serverinfo")
+    public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
+        handlePreflightRequest();
+
+        AdminAuth auth = authenticateRealmAdminRequest(headers);
+        if (!isAdmin(auth)) {
+            throw new ForbiddenException();
+        }
+
+        if (auth != null) {
+            logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
+        }
+
+        Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
+
+        ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
+        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
+        return adminResource;
+    }
+
+    protected boolean isAdmin(AdminAuth auth) {
+
+        RealmManager realmManager = new RealmManager(session);
+        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+            if (auth.hasOneOfRealmRole(AdminRoles.ADMIN, AdminRoles.CREATE_REALM)) {
+                return true;
+            }
+            for (RealmModel realm : session.realms().getRealms()) {
+                ClientModel client = realm.getMasterAdminClient();
+                if (auth.hasOneOfAppRole(client, AdminRoles.ALL_REALM_ROLES)) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            ClientModel client = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
+            return auth.hasOneOfAppRole(client, AdminRoles.ALL_REALM_ROLES);
+        }
+    }
+
+    protected void handlePreflightRequest() {
+        if (request.getHttpMethod().equalsIgnoreCase("OPTIONS")) {
+            logger.debug("Cors admin pre-flight");
+            Response response = Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
+            throw new NoLogWebApplicationException(response);
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index c43f6d9..03ddcfd 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -1,333 +1,333 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.jboss.resteasy.spi.BadRequestException;
-import org.jboss.resteasy.spi.NotAcceptableException;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.util.CertificateUtils;
-import org.keycloak.util.PemUtils;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientAttributeCertificateResource {
-    
-    public static final String PRIVATE_KEY = "private.key";
-    public static final String X509CERTIFICATE = "certificate";
-
-    protected RealmModel realm;
-    private RealmAuth auth;
-    protected ClientModel client;
-    protected KeycloakSession session;
-    protected AdminEventBuilder adminEvent;
-    protected String attributePrefix;
-    protected String privateAttribute;
-    protected String certificateAttribute;
-
-    public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.auth = auth;
-        this.client = client;
-        this.session = session;
-        this.attributePrefix = attributePrefix;
-        this.privateAttribute = attributePrefix + "." + PRIVATE_KEY;
-        this.certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
-        this.adminEvent = adminEvent;
-    }
-
-    public static class ClientKeyPairInfo {
-        protected String privateKey;
-        protected String publicKey;
-        protected String certificate;
-
-        public String getPrivateKey() {
-            return privateKey;
-        }
-
-        public void setPrivateKey(String privateKey) {
-            this.privateKey = privateKey;
-        }
-
-        public String getCertificate() {
-            return certificate;
-        }
-
-        public void setCertificate(String certificate) {
-            this.certificate = certificate;
-        }
-    }
-
-    /**
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public ClientKeyPairInfo getKeyInfo() {
-        ClientKeyPairInfo info = new ClientKeyPairInfo();
-        info.setCertificate(client.getAttribute(certificateAttribute));
-        info.setPrivateKey(client.getAttribute(privateAttribute));
-        return info;
-    }
-
-    /**
-     *
-     * @return
-     */
-    @POST
-    @NoCache
-    @Path("generate")
-    @Produces(MediaType.APPLICATION_JSON)
-    public ClientKeyPairInfo generate() {
-        auth.requireManage();
-
-        String subject = client.getClientId();
-        KeyPair keyPair = null;
-        try {
-            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
-            generator.initialize(2048);
-            keyPair = generator.generateKeyPair();
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-        X509Certificate certificate = null;
-        try {
-            certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, subject);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(keyPair.getPrivate());
-        String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
-
-        client.setAttribute(privateAttribute, privateKeyPem);
-        client.setAttribute(certificateAttribute, certPem);
-
-        KeycloakModelUtils.generateClientKeyPairCertificate(client);
-        ClientKeyPairInfo info = new ClientKeyPairInfo();
-        info.setCertificate(client.getAttribute(certificateAttribute));
-        info.setPrivateKey(client.getAttribute(privateAttribute));
-        
-        adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
-
-        return info;
-    }
-
-    /**
-     *
-     * @param uriInfo
-     * @param input
-     * @return
-     * @throws IOException
-     */
-    @POST
-    @Path("upload")
-    @Consumes(MediaType.MULTIPART_FORM_DATA)
-    @Produces(MediaType.APPLICATION_JSON)
-    public ClientKeyPairInfo uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
-        auth.requireManage();
-        ClientKeyPairInfo info = new ClientKeyPairInfo();
-        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
-        List<InputPart> inputParts = uploadForm.get("file");
-
-        String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
-        String keyAlias = uploadForm.get("keyAlias").get(0).getBodyAsString();
-        List<InputPart> keyPasswordPart = uploadForm.get("keyPassword");
-        char[] keyPassword = keyPasswordPart != null ? keyPasswordPart.get(0).getBodyAsString().toCharArray() : null;
-
-        List<InputPart> storePasswordPart = uploadForm.get("storePassword");
-        char[] storePassword = storePasswordPart != null ? storePasswordPart.get(0).getBodyAsString().toCharArray() : null;
-        PrivateKey privateKey = null;
-        X509Certificate certificate = null;
-        try {
-            KeyStore keyStore = null;
-            if (keystoreFormat.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
-            else keyStore = KeyStore.getInstance(keystoreFormat, "BC");
-            keyStore.load(inputParts.get(0).getBody(InputStream.class, null), storePassword);
-            try {
-                privateKey = (PrivateKey)keyStore.getKey(keyAlias, keyPassword);
-            } catch (Exception e) {
-                // ignore
-            }
-            certificate = (X509Certificate)keyStore.getCertificate(keyAlias);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        if (privateKey != null) {
-            String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-            client.setAttribute(privateAttribute, privateKeyPem);
-            info.setPrivateKey(privateKeyPem);
-        } else if (certificate != null) {
-            client.removeAttribute(privateAttribute);
-        }
-
-        if (certificate != null) {
-            String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
-            client.setAttribute(certificateAttribute, certPem);
-            info.setCertificate(certPem);
-        }
-        
-        adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
-        return info;
-    }
-
-
-    public static class KeyStoreConfig {
-        protected Boolean realmCertificate;
-        protected String storePassword;
-        protected String keyPassword;
-        protected String keyAlias;
-        protected String realmAlias;
-        protected String format;
-
-        public Boolean isRealmCertificate() {
-            return realmCertificate;
-        }
-
-        public void setRealmCertificate(Boolean realmCertificate) {
-            this.realmCertificate = realmCertificate;
-        }
-
-        public String getStorePassword() {
-            return storePassword;
-        }
-
-        public void setStorePassword(String storePassword) {
-            this.storePassword = storePassword;
-        }
-
-        public String getKeyPassword() {
-            return keyPassword;
-        }
-
-        public void setKeyPassword(String keyPassword) {
-            this.keyPassword = keyPassword;
-        }
-
-        public String getKeyAlias() {
-            return keyAlias;
-        }
-
-        public void setKeyAlias(String keyAlias) {
-            this.keyAlias = keyAlias;
-        }
-
-        public String getRealmAlias() {
-            return realmAlias;
-        }
-
-        public void setRealmAlias(String realmAlias) {
-            this.realmAlias = realmAlias;
-        }
-
-        public String getFormat() {
-            return format;
-        }
-
-        public void setFormat(String format) {
-            this.format = format;
-        }
-    }
-
-    /**
-     *
-     * @param config
-     * @return
-     */
-    @POST
-    @NoCache
-    @Path("/download")
-    @Produces(MediaType.APPLICATION_OCTET_STREAM)
-    @Consumes(MediaType.APPLICATION_JSON)
-    public byte[] getKeystore(final KeyStoreConfig config) {
-        auth.requireView();
-        if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
-            throw new NotAcceptableException("Only support jks format.");
-        }
-        String format = config.getFormat();
-        String privatePem = client.getAttribute(privateAttribute);
-        String certPem = client.getAttribute(certificateAttribute);
-        if (privatePem == null && certPem == null) {
-            throw new NotFoundException("keypair not generated for client");
-        }
-        if (privatePem != null && config.getKeyPassword() == null) {
-            throw new BadRequestException("Need to specify a key password for jks download");
-        }
-        if (config.getStorePassword() == null) {
-            throw new BadRequestException("Need to specify a store password for jks download");
-        }
-        final KeyStore keyStore;
-        try {
-            if (format.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
-            else keyStore = KeyStore.getInstance(format, "BC");
-            keyStore.load(null, null);
-            String keyAlias = config.getKeyAlias();
-            if (keyAlias == null) keyAlias = client.getClientId();
-            if (privatePem != null) {
-                PrivateKey privateKey = PemUtils.decodePrivateKey(privatePem);
-                X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
-
-
-                Certificate[] chain =  {clientCert};
-
-                keyStore.setKeyEntry(keyAlias, privateKey, config.getKeyPassword().trim().toCharArray(), chain);
-            } else {
-                X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
-                keyStore.setCertificateEntry(keyAlias, clientCert);
-            }
-
-
-            if (config.isRealmCertificate() == null || config.isRealmCertificate().booleanValue()) {
-                X509Certificate certificate = realm.getCertificate();
-                if (certificate == null) {
-                    KeycloakModelUtils.generateRealmCertificate(realm);
-                    certificate = realm.getCertificate();
-                }
-                String certificateAlias = config.getRealmAlias();
-                if (certificateAlias == null) certificateAlias = realm.getName();
-                keyStore.setCertificateEntry(certificateAlias, certificate);
-
-            }
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            keyStore.store(stream, config.getStorePassword().trim().toCharArray());
-            stream.flush();
-            stream.close();
-            byte[] rtn = stream.toByteArray();
-            return rtn;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.plugins.providers.multipart.InputPart;
+import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
+import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.NotAcceptableException;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.util.CertificateUtils;
+import org.keycloak.util.PemUtils;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientAttributeCertificateResource {
+    
+    public static final String PRIVATE_KEY = "private.key";
+    public static final String X509CERTIFICATE = "certificate";
+
+    protected RealmModel realm;
+    private RealmAuth auth;
+    protected ClientModel client;
+    protected KeycloakSession session;
+    protected AdminEventBuilder adminEvent;
+    protected String attributePrefix;
+    protected String privateAttribute;
+    protected String certificateAttribute;
+
+    public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.auth = auth;
+        this.client = client;
+        this.session = session;
+        this.attributePrefix = attributePrefix;
+        this.privateAttribute = attributePrefix + "." + PRIVATE_KEY;
+        this.certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
+        this.adminEvent = adminEvent;
+    }
+
+    public static class ClientKeyPairInfo {
+        protected String privateKey;
+        protected String publicKey;
+        protected String certificate;
+
+        public String getPrivateKey() {
+            return privateKey;
+        }
+
+        public void setPrivateKey(String privateKey) {
+            this.privateKey = privateKey;
+        }
+
+        public String getCertificate() {
+            return certificate;
+        }
+
+        public void setCertificate(String certificate) {
+            this.certificate = certificate;
+        }
+    }
+
+    /**
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public ClientKeyPairInfo getKeyInfo() {
+        ClientKeyPairInfo info = new ClientKeyPairInfo();
+        info.setCertificate(client.getAttribute(certificateAttribute));
+        info.setPrivateKey(client.getAttribute(privateAttribute));
+        return info;
+    }
+
+    /**
+     *
+     * @return
+     */
+    @POST
+    @NoCache
+    @Path("generate")
+    @Produces(MediaType.APPLICATION_JSON)
+    public ClientKeyPairInfo generate() {
+        auth.requireManage();
+
+        String subject = client.getClientId();
+        KeyPair keyPair = null;
+        try {
+            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+            generator.initialize(2048);
+            keyPair = generator.generateKeyPair();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+        X509Certificate certificate = null;
+        try {
+            certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, subject);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(keyPair.getPrivate());
+        String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
+
+        client.setAttribute(privateAttribute, privateKeyPem);
+        client.setAttribute(certificateAttribute, certPem);
+
+        KeycloakModelUtils.generateClientKeyPairCertificate(client);
+        ClientKeyPairInfo info = new ClientKeyPairInfo();
+        info.setCertificate(client.getAttribute(certificateAttribute));
+        info.setPrivateKey(client.getAttribute(privateAttribute));
+        
+        adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
+
+        return info;
+    }
+
+    /**
+     *
+     * @param uriInfo
+     * @param input
+     * @return
+     * @throws IOException
+     */
+    @POST
+    @Path("upload")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    @Produces(MediaType.APPLICATION_JSON)
+    public ClientKeyPairInfo uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
+        auth.requireManage();
+        ClientKeyPairInfo info = new ClientKeyPairInfo();
+        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
+        List<InputPart> inputParts = uploadForm.get("file");
+
+        String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
+        String keyAlias = uploadForm.get("keyAlias").get(0).getBodyAsString();
+        List<InputPart> keyPasswordPart = uploadForm.get("keyPassword");
+        char[] keyPassword = keyPasswordPart != null ? keyPasswordPart.get(0).getBodyAsString().toCharArray() : null;
+
+        List<InputPart> storePasswordPart = uploadForm.get("storePassword");
+        char[] storePassword = storePasswordPart != null ? storePasswordPart.get(0).getBodyAsString().toCharArray() : null;
+        PrivateKey privateKey = null;
+        X509Certificate certificate = null;
+        try {
+            KeyStore keyStore = null;
+            if (keystoreFormat.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
+            else keyStore = KeyStore.getInstance(keystoreFormat, "BC");
+            keyStore.load(inputParts.get(0).getBody(InputStream.class, null), storePassword);
+            try {
+                privateKey = (PrivateKey)keyStore.getKey(keyAlias, keyPassword);
+            } catch (Exception e) {
+                // ignore
+            }
+            certificate = (X509Certificate)keyStore.getCertificate(keyAlias);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        if (privateKey != null) {
+            String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+            client.setAttribute(privateAttribute, privateKeyPem);
+            info.setPrivateKey(privateKeyPem);
+        } else if (certificate != null) {
+            client.removeAttribute(privateAttribute);
+        }
+
+        if (certificate != null) {
+            String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
+            client.setAttribute(certificateAttribute, certPem);
+            info.setCertificate(certPem);
+        }
+        
+        adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
+        return info;
+    }
+
+
+    public static class KeyStoreConfig {
+        protected Boolean realmCertificate;
+        protected String storePassword;
+        protected String keyPassword;
+        protected String keyAlias;
+        protected String realmAlias;
+        protected String format;
+
+        public Boolean isRealmCertificate() {
+            return realmCertificate;
+        }
+
+        public void setRealmCertificate(Boolean realmCertificate) {
+            this.realmCertificate = realmCertificate;
+        }
+
+        public String getStorePassword() {
+            return storePassword;
+        }
+
+        public void setStorePassword(String storePassword) {
+            this.storePassword = storePassword;
+        }
+
+        public String getKeyPassword() {
+            return keyPassword;
+        }
+
+        public void setKeyPassword(String keyPassword) {
+            this.keyPassword = keyPassword;
+        }
+
+        public String getKeyAlias() {
+            return keyAlias;
+        }
+
+        public void setKeyAlias(String keyAlias) {
+            this.keyAlias = keyAlias;
+        }
+
+        public String getRealmAlias() {
+            return realmAlias;
+        }
+
+        public void setRealmAlias(String realmAlias) {
+            this.realmAlias = realmAlias;
+        }
+
+        public String getFormat() {
+            return format;
+        }
+
+        public void setFormat(String format) {
+            this.format = format;
+        }
+    }
+
+    /**
+     *
+     * @param config
+     * @return
+     */
+    @POST
+    @NoCache
+    @Path("/download")
+    @Produces(MediaType.APPLICATION_OCTET_STREAM)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public byte[] getKeystore(final KeyStoreConfig config) {
+        auth.requireView();
+        if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
+            throw new NotAcceptableException("Only support jks format.");
+        }
+        String format = config.getFormat();
+        String privatePem = client.getAttribute(privateAttribute);
+        String certPem = client.getAttribute(certificateAttribute);
+        if (privatePem == null && certPem == null) {
+            throw new NotFoundException("keypair not generated for client");
+        }
+        if (privatePem != null && config.getKeyPassword() == null) {
+            throw new BadRequestException("Need to specify a key password for jks download");
+        }
+        if (config.getStorePassword() == null) {
+            throw new BadRequestException("Need to specify a store password for jks download");
+        }
+        final KeyStore keyStore;
+        try {
+            if (format.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
+            else keyStore = KeyStore.getInstance(format, "BC");
+            keyStore.load(null, null);
+            String keyAlias = config.getKeyAlias();
+            if (keyAlias == null) keyAlias = client.getClientId();
+            if (privatePem != null) {
+                PrivateKey privateKey = PemUtils.decodePrivateKey(privatePem);
+                X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
+
+
+                Certificate[] chain =  {clientCert};
+
+                keyStore.setKeyEntry(keyAlias, privateKey, config.getKeyPassword().trim().toCharArray(), chain);
+            } else {
+                X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
+                keyStore.setCertificateEntry(keyAlias, clientCert);
+            }
+
+
+            if (config.isRealmCertificate() == null || config.isRealmCertificate().booleanValue()) {
+                X509Certificate certificate = realm.getCertificate();
+                if (certificate == null) {
+                    KeycloakModelUtils.generateRealmCertificate(realm);
+                    certificate = realm.getCertificate();
+                }
+                String certificateAlias = config.getRealmAlias();
+                if (certificateAlias == null) certificateAlias = realm.getName();
+                keyStore.setCertificateEntry(certificateAlias, certificate);
+
+            }
+            ByteArrayOutputStream stream = new ByteArrayOutputStream();
+            keyStore.store(stream, config.getStorePassword().trim().toCharArray());
+            stream.flush();
+            stream.close();
+            byte[] rtn = stream.toByteArray();
+            return rtn;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+}
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 2a9bcfc..3aa1190 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
@@ -1,431 +1,431 @@
-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;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.adapters.action.GlobalRequestResult;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.UserSessionRepresentation;
-import org.keycloak.services.managers.ClientManager;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.managers.ResourceAdminManager;
-import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.ErrorResponse;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Base resource class for managing one particular client of a realm.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientResource {
-    protected static final Logger logger = Logger.getLogger(ClientResource.class);
-    protected RealmModel realm;
-    private RealmAuth auth;
-    private AdminEventBuilder adminEvent;
-    protected ClientModel client;
-    protected KeycloakSession session;
-    
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected KeycloakApplication keycloak;
-
-    protected KeycloakApplication getKeycloakApplication() {
-        return keycloak;
-    }
-
-    public ClientResource(RealmModel realm, RealmAuth auth, ClientModel clientModel, KeycloakSession session, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.auth = auth;
-        this.client = clientModel;
-        this.session = session;
-        this.adminEvent = adminEvent;
-
-        auth.init(RealmAuth.Resource.CLIENT);
-    }
-
-    @Path("protocol-mappers")
-    public ProtocolMappersResource getProtocolMappers() {
-        ProtocolMappersResource mappers = new ProtocolMappersResource(client, auth, adminEvent);
-        ResteasyProviderFactory.getInstance().injectProperties(mappers);
-        return mappers;
-    }
-
-    /**
-     * Update the client.
-     * @param rep
-     * @return
-     */
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response update(final ClientRepresentation rep) {
-        auth.requireManage();
-
-        try {
-            RepresentationToModel.updateClient(rep, client);
-            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-            return Response.noContent().build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
-        }
-    }
-
-
-    /**
-     * Get representation of the client.
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public ClientRepresentation getClient() {
-        auth.requireView();
-        return ModelToRepresentation.toRepresentation(client);
-    }
-
-    /**
-     *
-     * @param attributePrefix
-     * @return
-     */
-    @Path("certificates/{attr}")
-    public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
-        return new ClientAttributeCertificateResource(realm, auth, client, session, attributePrefix, adminEvent);
-    }
-
-
-    /**
-     * Return keycloak.json file for this client to be used to configure the adapter of that client.
-     *
-     * @return
-     * @throws IOException
-     */
-    @GET
-    @NoCache
-    @Path("installation/json")
-    @Produces(MediaType.APPLICATION_JSON)
-    public String getInstallation() throws IOException {
-        auth.requireView();
-
-        ClientManager clientManager = new ClientManager(new RealmManager(session));
-        Object rep = clientManager.toInstallationRepresentation(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
-
-        // TODO Temporary solution to pretty-print
-        return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
-    }
-
-    /**
-     * Return XML that can be included in the JBoss/Wildfly Keycloak subsystem to configure the adapter of that client.
-     *
-     * @return
-     * @throws IOException
-     */
-    @GET
-    @NoCache
-    @Path("installation/jboss")
-    @Produces(MediaType.TEXT_PLAIN)
-    public String getJBossInstallation() throws IOException {
-        auth.requireView();
-
-        ClientManager clientManager = new ClientManager(new RealmManager(session));
-        return clientManager.toJBossSubsystemConfig(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
-    }
-
-    /**
-     * Delete this client.
-     *
-     */
-    @DELETE
-    @NoCache
-    public void deleteClient() {
-        auth.requireManage();
-        new ClientManager(new RealmManager(session)).removeClient(realm, client);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-
-    /**
-     * Generates a new secret for this client
-     *
-     * @return
-     */
-    @Path("client-secret")
-    @POST
-    @Produces(MediaType.APPLICATION_JSON)
-    @Consumes(MediaType.APPLICATION_JSON)
-    public CredentialRepresentation regenerateSecret() {
-        auth.requireManage();
-
-        logger.debug("regenerateSecret");
-        UserCredentialModel cred = KeycloakModelUtils.generateSecret(client);
-        CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(rep).success();
-        return rep;
-    }
-
-    /**
-     * Get the secret of this client
-     *
-     * @return
-     */
-    @Path("client-secret")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public CredentialRepresentation getClientSecret() {
-        auth.requireView();
-
-        logger.debug("getClientSecret");
-        UserCredentialModel model = UserCredentialModel.secret(client.getSecret());
-        if (model == null) throw new NotFoundException("Client does not have a secret");
-        return ModelToRepresentation.toRepresentation(model);
-    }
-
-    /**
-     * Base path for managing the scope mappings for this client
-     *
-     * @return
-     */
-    @Path("scope-mappings")
-    public ScopeMappedResource getScopeMappedResource() {
-        return new ScopeMappedResource(realm, auth, client, session, adminEvent);
-    }
-
-    @Path("roles")
-    public RoleContainerResource getRoleContainerResource() {
-        return new RoleContainerResource(uriInfo, realm, auth, client, adminEvent);
-    }
-
-    /**
-     * Returns set of allowed origin.  This is used for CORS requests.  Access tokens will have
-     * their allowedOrigins claim set to this value for tokens created for this client.
-     *
-     * @return
-     */
-    @Path("allowed-origins")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<String> getAllowedOrigins()
-    {
-        auth.requireView();
-        return client.getWebOrigins();
-    }
-
-    /**
-     * Change the set of allowed origins.   This is used for CORS requests.  Access tokens will have
-     * their allowedOrigins claim set to this value for tokens created for this client.
-     *
-     * @param allowedOrigins
-     */
-    @Path("allowed-origins")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void updateAllowedOrigins(Set<String> allowedOrigins)
-    {
-        auth.requireManage();
-
-        client.setWebOrigins(allowedOrigins);
-        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(client).success();
-    }
-
-    /**
-     * Remove set of allowed origins from current allowed origins list.  This is used for CORS requests.  Access tokens will have
-     * their allowedOrigins claim set to this value for tokens created for this client.
-     *
-     * @param allowedOrigins
-     */
-    @Path("allowed-origins")
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteAllowedOrigins(Set<String> allowedOrigins)
-    {
-        auth.requireManage();
-
-        for (String origin : allowedOrigins) {
-            client.removeWebOrigin(origin);
-        }
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * If the client has an admin URL, push the client's revocation policy to it.
-     *
-     */
-    @Path("push-revocation")
-    @POST
-    public GlobalRequestResult pushRevocation() {
-        auth.requireManage();
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-        return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
-    
-    }
-    
-    /**
-     * Number of user sessions associated with this client
-     *
-     * {
-     *     "count": number
-     * }
-     *
-     * @return
-     */
-    @Path("session-count")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Map<String, Integer> getApplicationSessionCount() {
-        auth.requireView();
-        Map<String, Integer> map = new HashMap<String, Integer>();
-        map.put("count", session.sessions().getActiveUserSessions(client.getRealm(), client));
-        return map;
-    }
-
-    /**
-     * Return a list of user sessions associated with this client
-     *
-     * @return
-     */
-    @Path("user-sessions")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<UserSessionRepresentation> getUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
-        auth.requireView();
-        firstResult = firstResult != null ? firstResult : -1;
-        maxResults = maxResults != null ? maxResults : -1;
-        List<UserSessionRepresentation> sessions = new ArrayList<UserSessionRepresentation>();
-        for (UserSessionModel userSession : session.sessions().getUserSessions(client.getRealm(), client, firstResult, maxResults)) {
-            UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession);
-            sessions.add(rep);
-        }
-        return sessions;
-    }
-
-    /**
-     * If the client has an admin URL, invalidate all sessions associated with that client directly.
-     *
-     */
-    @Path("logout-all")
-    @POST
-    public GlobalRequestResult logoutAll() {
-        auth.requireManage();
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-        return new ResourceAdminManager(session).logoutClient(uriInfo.getRequestUri(), realm, client);
-
-    }
-
-    /**
-     * If the client has an admin URL, invalidate the sessions for a particular user directly.
-     *
-     */
-    @Path("logout-user/{username}")
-    @POST
-    public void logout(final @PathParam("username") String username) {
-        auth.requireManage();
-        UserModel user = session.users().getUserByUsername(username, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-        new ResourceAdminManager(session).logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user);
-
-    }
-
-    /**
-     * Manually register cluster node to this client - usually it's not needed to call this directly as adapter should handle
-     * by sending registration request to Keycloak
-     *
-     * @param formParams
-     */
-    @Path("nodes")
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void registerNode(Map<String, String> formParams) {
-        auth.requireManage();
-        String node = formParams.get("node");
-        if (node == null) {
-            throw new BadRequestException("Node not found in params");
-        }
-        if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
-        client.registerNode(node, Time.currentTime());
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * Unregister cluster node from this client
-     *
-     * @param node
-     */
-    @Path("nodes/{node}")
-    @DELETE
-    @NoCache
-    public void unregisterNode(final @PathParam("node") String node) {
-        auth.requireManage();
-        if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
-
-        Integer time = client.getRegisteredNodes().get(node);
-        if (time == null) {
-            throw new NotFoundException("Client does not have a node " + node);
-        }
-        client.unregisterNode(node);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * Test if registered cluster nodes are available by sending 'ping' request to all of them
-     *
-     * @return
-     */
-    @Path("test-nodes-available")
-    @GET
-    @NoCache
-    public GlobalRequestResult testNodesAvailable() {
-        auth.requireManage();
-        logger.debug("Test availability of cluster nodes");
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-        return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
-
-    }
-
-}
+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;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.adapters.action.GlobalRequestResult;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.services.managers.ClientManager;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.ErrorResponse;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Base resource class for managing one particular client of a realm.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientResource {
+    protected static final Logger logger = Logger.getLogger(ClientResource.class);
+    protected RealmModel realm;
+    private RealmAuth auth;
+    private AdminEventBuilder adminEvent;
+    protected ClientModel client;
+    protected KeycloakSession session;
+    
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected KeycloakApplication keycloak;
+
+    protected KeycloakApplication getKeycloakApplication() {
+        return keycloak;
+    }
+
+    public ClientResource(RealmModel realm, RealmAuth auth, ClientModel clientModel, KeycloakSession session, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.auth = auth;
+        this.client = clientModel;
+        this.session = session;
+        this.adminEvent = adminEvent;
+
+        auth.init(RealmAuth.Resource.CLIENT);
+    }
+
+    @Path("protocol-mappers")
+    public ProtocolMappersResource getProtocolMappers() {
+        ProtocolMappersResource mappers = new ProtocolMappersResource(client, auth, adminEvent);
+        ResteasyProviderFactory.getInstance().injectProperties(mappers);
+        return mappers;
+    }
+
+    /**
+     * Update the client.
+     * @param rep
+     * @return
+     */
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response update(final ClientRepresentation rep) {
+        auth.requireManage();
+
+        try {
+            RepresentationToModel.updateClient(rep, client);
+            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+            return Response.noContent().build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
+        }
+    }
+
+
+    /**
+     * Get representation of the client.
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public ClientRepresentation getClient() {
+        auth.requireView();
+        return ModelToRepresentation.toRepresentation(client);
+    }
+
+    /**
+     *
+     * @param attributePrefix
+     * @return
+     */
+    @Path("certificates/{attr}")
+    public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
+        return new ClientAttributeCertificateResource(realm, auth, client, session, attributePrefix, adminEvent);
+    }
+
+
+    /**
+     * Return keycloak.json file for this client to be used to configure the adapter of that client.
+     *
+     * @return
+     * @throws IOException
+     */
+    @GET
+    @NoCache
+    @Path("installation/json")
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getInstallation() throws IOException {
+        auth.requireView();
+
+        ClientManager clientManager = new ClientManager(new RealmManager(session));
+        Object rep = clientManager.toInstallationRepresentation(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
+
+        // TODO Temporary solution to pretty-print
+        return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
+    }
+
+    /**
+     * Return XML that can be included in the JBoss/Wildfly Keycloak subsystem to configure the adapter of that client.
+     *
+     * @return
+     * @throws IOException
+     */
+    @GET
+    @NoCache
+    @Path("installation/jboss")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getJBossInstallation() throws IOException {
+        auth.requireView();
+
+        ClientManager clientManager = new ClientManager(new RealmManager(session));
+        return clientManager.toJBossSubsystemConfig(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
+    }
+
+    /**
+     * Delete this client.
+     *
+     */
+    @DELETE
+    @NoCache
+    public void deleteClient() {
+        auth.requireManage();
+        new ClientManager(new RealmManager(session)).removeClient(realm, client);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+
+    /**
+     * Generates a new secret for this client
+     *
+     * @return
+     */
+    @Path("client-secret")
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public CredentialRepresentation regenerateSecret() {
+        auth.requireManage();
+
+        logger.debug("regenerateSecret");
+        UserCredentialModel cred = KeycloakModelUtils.generateSecret(client);
+        CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(rep).success();
+        return rep;
+    }
+
+    /**
+     * Get the secret of this client
+     *
+     * @return
+     */
+    @Path("client-secret")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public CredentialRepresentation getClientSecret() {
+        auth.requireView();
+
+        logger.debug("getClientSecret");
+        UserCredentialModel model = UserCredentialModel.secret(client.getSecret());
+        if (model == null) throw new NotFoundException("Client does not have a secret");
+        return ModelToRepresentation.toRepresentation(model);
+    }
+
+    /**
+     * Base path for managing the scope mappings for this client
+     *
+     * @return
+     */
+    @Path("scope-mappings")
+    public ScopeMappedResource getScopeMappedResource() {
+        return new ScopeMappedResource(realm, auth, client, session, adminEvent);
+    }
+
+    @Path("roles")
+    public RoleContainerResource getRoleContainerResource() {
+        return new RoleContainerResource(uriInfo, realm, auth, client, adminEvent);
+    }
+
+    /**
+     * Returns set of allowed origin.  This is used for CORS requests.  Access tokens will have
+     * their allowedOrigins claim set to this value for tokens created for this client.
+     *
+     * @return
+     */
+    @Path("allowed-origins")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<String> getAllowedOrigins()
+    {
+        auth.requireView();
+        return client.getWebOrigins();
+    }
+
+    /**
+     * Change the set of allowed origins.   This is used for CORS requests.  Access tokens will have
+     * their allowedOrigins claim set to this value for tokens created for this client.
+     *
+     * @param allowedOrigins
+     */
+    @Path("allowed-origins")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void updateAllowedOrigins(Set<String> allowedOrigins)
+    {
+        auth.requireManage();
+
+        client.setWebOrigins(allowedOrigins);
+        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(client).success();
+    }
+
+    /**
+     * Remove set of allowed origins from current allowed origins list.  This is used for CORS requests.  Access tokens will have
+     * their allowedOrigins claim set to this value for tokens created for this client.
+     *
+     * @param allowedOrigins
+     */
+    @Path("allowed-origins")
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteAllowedOrigins(Set<String> allowedOrigins)
+    {
+        auth.requireManage();
+
+        for (String origin : allowedOrigins) {
+            client.removeWebOrigin(origin);
+        }
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * If the client has an admin URL, push the client's revocation policy to it.
+     *
+     */
+    @Path("push-revocation")
+    @POST
+    public GlobalRequestResult pushRevocation() {
+        auth.requireManage();
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
+    
+    }
+    
+    /**
+     * Number of user sessions associated with this client
+     *
+     * {
+     *     "count": number
+     * }
+     *
+     * @return
+     */
+    @Path("session-count")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Map<String, Integer> getApplicationSessionCount() {
+        auth.requireView();
+        Map<String, Integer> map = new HashMap<String, Integer>();
+        map.put("count", session.sessions().getActiveUserSessions(client.getRealm(), client));
+        return map;
+    }
+
+    /**
+     * Return a list of user sessions associated with this client
+     *
+     * @return
+     */
+    @Path("user-sessions")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<UserSessionRepresentation> getUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
+        auth.requireView();
+        firstResult = firstResult != null ? firstResult : -1;
+        maxResults = maxResults != null ? maxResults : -1;
+        List<UserSessionRepresentation> sessions = new ArrayList<UserSessionRepresentation>();
+        for (UserSessionModel userSession : session.sessions().getUserSessions(client.getRealm(), client, firstResult, maxResults)) {
+            UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession);
+            sessions.add(rep);
+        }
+        return sessions;
+    }
+
+    /**
+     * If the client has an admin URL, invalidate all sessions associated with that client directly.
+     *
+     */
+    @Path("logout-all")
+    @POST
+    public GlobalRequestResult logoutAll() {
+        auth.requireManage();
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        return new ResourceAdminManager(session).logoutClient(uriInfo.getRequestUri(), realm, client);
+
+    }
+
+    /**
+     * If the client has an admin URL, invalidate the sessions for a particular user directly.
+     *
+     */
+    @Path("logout-user/{username}")
+    @POST
+    public void logout(final @PathParam("username") String username) {
+        auth.requireManage();
+        UserModel user = session.users().getUserByUsername(username, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        new ResourceAdminManager(session).logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user);
+
+    }
+
+    /**
+     * Manually register cluster node to this client - usually it's not needed to call this directly as adapter should handle
+     * by sending registration request to Keycloak
+     *
+     * @param formParams
+     */
+    @Path("nodes")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void registerNode(Map<String, String> formParams) {
+        auth.requireManage();
+        String node = formParams.get("node");
+        if (node == null) {
+            throw new BadRequestException("Node not found in params");
+        }
+        if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
+        client.registerNode(node, Time.currentTime());
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * Unregister cluster node from this client
+     *
+     * @param node
+     */
+    @Path("nodes/{node}")
+    @DELETE
+    @NoCache
+    public void unregisterNode(final @PathParam("node") String node) {
+        auth.requireManage();
+        if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
+
+        Integer time = client.getRegisteredNodes().get(node);
+        if (time == null) {
+            throw new NotFoundException("Client does not have a node " + node);
+        }
+        client.unregisterNode(node);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * Test if registered cluster nodes are available by sending 'ping' request to all of them
+     *
+     * @return
+     */
+    @Path("test-nodes-available")
+    @GET
+    @NoCache
+    public GlobalRequestResult testNodesAvailable() {
+        auth.requireManage();
+        logger.debug("Test availability of cluster nodes");
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
+
+    }
+
+}
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 5d7c703..77abf12 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
@@ -1,125 +1,125 @@
-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;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.services.ErrorResponse;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Base resource class for managing a realm's clients.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ClientsResource {
-    protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
-    protected RealmModel realm;
-    private RealmAuth auth;
-    private AdminEventBuilder adminEvent;
-    
-    @Context
-    protected KeycloakSession session;
-
-    public ClientsResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.auth = auth;
-        this.adminEvent = adminEvent;
-        
-        auth.init(RealmAuth.Resource.CLIENT);
-    }
-
-    /**
-     * List of clients belonging to this realm.
-     *
-     * @return
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<ClientRepresentation> getClients() {
-        auth.requireAny();
-
-        List<ClientRepresentation> rep = new ArrayList<>();
-        List<ClientModel> clientModels = realm.getClients();
-
-        boolean view = auth.hasView();
-        for (ClientModel clientModel : clientModels) {
-            if (view) {
-                rep.add(ModelToRepresentation.toRepresentation(clientModel));
-            } else {
-                ClientRepresentation client = new ClientRepresentation();
-                client.setId(clientModel.getId());
-                client.setClientId(clientModel.getClientId());
-                rep.add(client);
-            }
-        }
-        return rep;
-    }
-
-    /**
-     * Create a new client.  Client client_id must be unique!
-     *
-     * @param uriInfo
-     * @param rep
-     * @return
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createClient(final @Context UriInfo uriInfo, final ClientRepresentation rep) {
-        auth.requireManage();
-
-        try {
-            ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
-            
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, clientModel.getId()).representation(rep).success();
-            
-            return Response.created(uriInfo.getAbsolutePathBuilder().path(clientModel.getId()).build()).build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
-        }
-    }
-
-    /**
-     * Base path for managing a specific client.
-     *
-     * @param id id of client (not client-id)
-     * @return
-     */
-    @Path("{id}")
-    public ClientResource getClient(final @PathParam("id") String id) {
-        ClientModel clientModel = realm.getClientById(id);
-        if (clientModel == null) {
-            throw new NotFoundException("Could not find client: " + id);
-        }
-
-        session.getContext().setClient(clientModel);
-
-        ClientResource clientResource = new ClientResource(realm, auth, clientModel, session, adminEvent);
-        ResteasyProviderFactory.getInstance().injectProperties(clientResource);
-        return clientResource;
-    }
-
-}
+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;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.services.ErrorResponse;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base resource class for managing a realm's clients.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientsResource {
+    protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
+    protected RealmModel realm;
+    private RealmAuth auth;
+    private AdminEventBuilder adminEvent;
+    
+    @Context
+    protected KeycloakSession session;
+
+    public ClientsResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.auth = auth;
+        this.adminEvent = adminEvent;
+        
+        auth.init(RealmAuth.Resource.CLIENT);
+    }
+
+    /**
+     * List of clients belonging to this realm.
+     *
+     * @return
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<ClientRepresentation> getClients() {
+        auth.requireAny();
+
+        List<ClientRepresentation> rep = new ArrayList<>();
+        List<ClientModel> clientModels = realm.getClients();
+
+        boolean view = auth.hasView();
+        for (ClientModel clientModel : clientModels) {
+            if (view) {
+                rep.add(ModelToRepresentation.toRepresentation(clientModel));
+            } else {
+                ClientRepresentation client = new ClientRepresentation();
+                client.setId(clientModel.getId());
+                client.setClientId(clientModel.getClientId());
+                rep.add(client);
+            }
+        }
+        return rep;
+    }
+
+    /**
+     * Create a new client.  Client client_id must be unique!
+     *
+     * @param uriInfo
+     * @param rep
+     * @return
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createClient(final @Context UriInfo uriInfo, final ClientRepresentation rep) {
+        auth.requireManage();
+
+        try {
+            ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
+            
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, clientModel.getId()).representation(rep).success();
+            
+            return Response.created(uriInfo.getAbsolutePathBuilder().path(clientModel.getId()).build()).build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
+        }
+    }
+
+    /**
+     * Base path for managing a specific client.
+     *
+     * @param id id of client (not client-id)
+     * @return
+     */
+    @Path("{id}")
+    public ClientResource getClient(final @PathParam("id") String id) {
+        ClientModel clientModel = realm.getClientById(id);
+        if (clientModel == null) {
+            throw new NotFoundException("Could not find client: " + id);
+        }
+
+        session.getContext().setClient(clientModel);
+
+        ClientResource clientResource = new ClientResource(realm, auth, clientModel, session, adminEvent);
+        ResteasyProviderFactory.getInstance().injectProperties(clientResource);
+        return clientResource;
+    }
+
+}
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 c97e9af..83e6c2f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -1,279 +1,279 @@
-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;
-import org.keycloak.broker.provider.IdentityProviderFactory;
-import org.keycloak.broker.provider.IdentityProviderMapper;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.representations.idm.ConfigPropertyRepresentation;
-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.social.SocialIdentityProvider;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Pedro Igor
- */
-public class IdentityProviderResource {
-
-    private static Logger logger = Logger.getLogger(IdentityProviderResource.class);
-
-    private final RealmAuth auth;
-    private final RealmModel realm;
-    private final KeycloakSession session;
-    private final IdentityProviderModel identityProviderModel;
-    private final AdminEventBuilder adminEvent;
-    
-    @Context private UriInfo uriInfo;
-
-    public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.session = session;
-        this.identityProviderModel = identityProviderModel;
-        this.auth = auth;
-        this.adminEvent = adminEvent;
-    }
-
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public IdentityProviderRepresentation getIdentityProvider() {
-        this.auth.requireView();
-        IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel);
-        return rep;
-    }
-
-    @DELETE
-    @NoCache
-    public Response delete() {
-        this.auth.requireManage();
-
-        this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
-        
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-        
-        return Response.noContent().build();
-    }
-
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    @NoCache
-    public Response update(IdentityProviderRepresentation providerRep) {
-        try {
-            this.auth.requireManage();
-
-            String internalId = providerRep.getInternalId();
-            String newProviderId = providerRep.getAlias();
-            String oldProviderId = getProviderIdByInternalId(this.realm, internalId);
-
-            this.realm.updateIdentityProvider(RepresentationToModel.toModel(providerRep));
-
-            if (oldProviderId != null && !oldProviderId.equals(newProviderId)) {
-
-                // Admin changed the ID (alias) of identity provider. We must update all clients and users
-                logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
-
-                updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
-            }
-            
-            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(providerRep).success();
-            
-            return Response.noContent().build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Identity Provider " + providerRep.getAlias() + " already exists");
-        }
-    }
-
-    // return ID of IdentityProvider from realm based on internalId of this provider
-    private String getProviderIdByInternalId(RealmModel realm, String providerInternalId) {
-        List<IdentityProviderModel> providerModels = realm.getIdentityProviders();
-        for (IdentityProviderModel providerModel : providerModels) {
-            if (providerModel.getInternalId().equals(providerInternalId)) {
-                return providerModel.getAlias();
-            }
-        }
-
-        return null;
-    }
-
-    private void updateUsersAfterProviderAliasChange(List<UserModel> users, String oldProviderId, String newProviderId) {
-        for (UserModel user : users) {
-            FederatedIdentityModel federatedIdentity = this.session.users().getFederatedIdentity(user, oldProviderId, this.realm);
-            if (federatedIdentity != null) {
-                // Remove old link first
-                this.session.users().removeFederatedIdentity(this.realm, user, oldProviderId);
-
-                // And create new
-                FederatedIdentityModel newFederatedIdentity = new FederatedIdentityModel(newProviderId, federatedIdentity.getUserId(), federatedIdentity.getUserName(),
-                        federatedIdentity.getToken());
-                this.session.users().addFederatedIdentity(this.realm, user, newFederatedIdentity);
-            }
-        }
-    }
-
-
-    private IdentityProviderFactory getIdentityProviderFactory() {
-        List<ProviderFactory> allProviders = new ArrayList<ProviderFactory>();
-
-        allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(IdentityProvider.class));
-        allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(SocialIdentityProvider.class));
-
-        for (ProviderFactory providerFactory : allProviders) {
-            if (providerFactory.getId().equals(identityProviderModel.getProviderId())) return (IdentityProviderFactory)providerFactory;
-        }
-
-        return null;
-    }
-
-
-    @GET
-    @Path("export")
-    @NoCache
-    public Response export(@Context UriInfo uriInfo, @QueryParam("format") String format) {
-        try {
-            this.auth.requireView();
-            IdentityProviderFactory factory = getIdentityProviderFactory();
-            return factory.create(identityProviderModel).export(uriInfo, realm, format);
-        } catch (Exception e) {
-            return ErrorResponse.error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
-        }
-    }
-
-    @GET
-    @Path("mapper-types")
-    @NoCache
-    public Map<String, IdentityProviderMapperTypeRepresentation> getMapperTypes() {
-        this.auth.requireView();
-        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
-        Map<String, IdentityProviderMapperTypeRepresentation> types = new HashMap<>();
-        List<ProviderFactory> factories = sessionFactory.getProviderFactories(IdentityProviderMapper.class);
-        for (ProviderFactory factory : factories) {
-            IdentityProviderMapper mapper = (IdentityProviderMapper)factory;
-            for (String type : mapper.getCompatibleProviders()) {
-                if (IdentityProviderMapper.ANY_PROVIDER.equals(type) || type.equals(identityProviderModel.getProviderId())) {
-                    IdentityProviderMapperTypeRepresentation rep = new IdentityProviderMapperTypeRepresentation();
-                    rep.setId(mapper.getId());
-                    rep.setCategory(mapper.getDisplayCategory());
-                    rep.setName(mapper.getDisplayType());
-                    rep.setHelpText(mapper.getHelpText());
-                    List<ProviderConfigProperty> configProperties = mapper.getConfigProperties();
-                    for (ProviderConfigProperty prop : configProperties) {
-                        ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
-                        propRep.setName(prop.getName());
-                        propRep.setLabel(prop.getLabel());
-                        propRep.setType(prop.getType());
-                        propRep.setDefaultValue(prop.getDefaultValue());
-                        propRep.setHelpText(prop.getHelpText());
-                        rep.getProperties().add(propRep);
-                    }
-                    types.put(rep.getId(), rep);
-                    break;
-                }
-            }
-        }
-        return types;
-    }
-
-    @GET
-    @Path("mappers")
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<IdentityProviderMapperRepresentation> getMappers() {
-        this.auth.requireView();
-        List<IdentityProviderMapperRepresentation> mappers = new LinkedList<>();
-        for (IdentityProviderMapperModel model : realm.getIdentityProviderMappersByAlias(identityProviderModel.getAlias())) {
-            mappers.add(ModelToRepresentation.toRepresentation(model));
-        }
-        return mappers;
-    }
-
-    @POST
-    @Path("mappers")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response addMapper(IdentityProviderMapperRepresentation mapper) {
-        auth.requireManage();
-        IdentityProviderMapperModel model = RepresentationToModel.toModel(mapper);
-        model = realm.addIdentityProviderMapper(model);
-        
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId())
-            .representation(mapper).success();
-        
-        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
-
-    }
-
-    @GET
-    @NoCache
-    @Path("mappers/{id}")
-    @Produces(MediaType.APPLICATION_JSON)
-    public IdentityProviderMapperRepresentation getMapperById(@PathParam("id") String id) {
-        auth.requireView();
-        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        return ModelToRepresentation.toRepresentation(model);
-    }
-
-    @PUT
-    @NoCache
-    @Path("mappers/{id}")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void update(@PathParam("id") String id, IdentityProviderMapperRepresentation rep) {
-        auth.requireManage();
-        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        model = RepresentationToModel.toModel(rep);
-        realm.updateIdentityProviderMapper(model);
-        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-
-    }
-
-    @DELETE
-    @NoCache
-    @Path("mappers/{id}")
-    public void delete(@PathParam("id") String id) {
-        auth.requireManage();
-        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        realm.removeIdentityProviderMapper(model);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-
-    }
-
-
-}
+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;
+import org.keycloak.broker.provider.IdentityProviderFactory;
+import org.keycloak.broker.provider.IdentityProviderMapper;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.idm.ConfigPropertyRepresentation;
+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.social.SocialIdentityProvider;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Pedro Igor
+ */
+public class IdentityProviderResource {
+
+    private static Logger logger = Logger.getLogger(IdentityProviderResource.class);
+
+    private final RealmAuth auth;
+    private final RealmModel realm;
+    private final KeycloakSession session;
+    private final IdentityProviderModel identityProviderModel;
+    private final AdminEventBuilder adminEvent;
+    
+    @Context private UriInfo uriInfo;
+
+    public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.session = session;
+        this.identityProviderModel = identityProviderModel;
+        this.auth = auth;
+        this.adminEvent = adminEvent;
+    }
+
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public IdentityProviderRepresentation getIdentityProvider() {
+        this.auth.requireView();
+        IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel);
+        return rep;
+    }
+
+    @DELETE
+    @NoCache
+    public Response delete() {
+        this.auth.requireManage();
+
+        this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
+        
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+        
+        return Response.noContent().build();
+    }
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @NoCache
+    public Response update(IdentityProviderRepresentation providerRep) {
+        try {
+            this.auth.requireManage();
+
+            String internalId = providerRep.getInternalId();
+            String newProviderId = providerRep.getAlias();
+            String oldProviderId = getProviderIdByInternalId(this.realm, internalId);
+
+            this.realm.updateIdentityProvider(RepresentationToModel.toModel(providerRep));
+
+            if (oldProviderId != null && !oldProviderId.equals(newProviderId)) {
+
+                // Admin changed the ID (alias) of identity provider. We must update all clients and users
+                logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
+
+                updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
+            }
+            
+            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(providerRep).success();
+            
+            return Response.noContent().build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Identity Provider " + providerRep.getAlias() + " already exists");
+        }
+    }
+
+    // return ID of IdentityProvider from realm based on internalId of this provider
+    private String getProviderIdByInternalId(RealmModel realm, String providerInternalId) {
+        List<IdentityProviderModel> providerModels = realm.getIdentityProviders();
+        for (IdentityProviderModel providerModel : providerModels) {
+            if (providerModel.getInternalId().equals(providerInternalId)) {
+                return providerModel.getAlias();
+            }
+        }
+
+        return null;
+    }
+
+    private void updateUsersAfterProviderAliasChange(List<UserModel> users, String oldProviderId, String newProviderId) {
+        for (UserModel user : users) {
+            FederatedIdentityModel federatedIdentity = this.session.users().getFederatedIdentity(user, oldProviderId, this.realm);
+            if (federatedIdentity != null) {
+                // Remove old link first
+                this.session.users().removeFederatedIdentity(this.realm, user, oldProviderId);
+
+                // And create new
+                FederatedIdentityModel newFederatedIdentity = new FederatedIdentityModel(newProviderId, federatedIdentity.getUserId(), federatedIdentity.getUserName(),
+                        federatedIdentity.getToken());
+                this.session.users().addFederatedIdentity(this.realm, user, newFederatedIdentity);
+            }
+        }
+    }
+
+
+    private IdentityProviderFactory getIdentityProviderFactory() {
+        List<ProviderFactory> allProviders = new ArrayList<ProviderFactory>();
+
+        allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(IdentityProvider.class));
+        allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(SocialIdentityProvider.class));
+
+        for (ProviderFactory providerFactory : allProviders) {
+            if (providerFactory.getId().equals(identityProviderModel.getProviderId())) return (IdentityProviderFactory)providerFactory;
+        }
+
+        return null;
+    }
+
+
+    @GET
+    @Path("export")
+    @NoCache
+    public Response export(@Context UriInfo uriInfo, @QueryParam("format") String format) {
+        try {
+            this.auth.requireView();
+            IdentityProviderFactory factory = getIdentityProviderFactory();
+            return factory.create(identityProviderModel).export(uriInfo, realm, format);
+        } catch (Exception e) {
+            return ErrorResponse.error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
+        }
+    }
+
+    @GET
+    @Path("mapper-types")
+    @NoCache
+    public Map<String, IdentityProviderMapperTypeRepresentation> getMapperTypes() {
+        this.auth.requireView();
+        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+        Map<String, IdentityProviderMapperTypeRepresentation> types = new HashMap<>();
+        List<ProviderFactory> factories = sessionFactory.getProviderFactories(IdentityProviderMapper.class);
+        for (ProviderFactory factory : factories) {
+            IdentityProviderMapper mapper = (IdentityProviderMapper)factory;
+            for (String type : mapper.getCompatibleProviders()) {
+                if (IdentityProviderMapper.ANY_PROVIDER.equals(type) || type.equals(identityProviderModel.getProviderId())) {
+                    IdentityProviderMapperTypeRepresentation rep = new IdentityProviderMapperTypeRepresentation();
+                    rep.setId(mapper.getId());
+                    rep.setCategory(mapper.getDisplayCategory());
+                    rep.setName(mapper.getDisplayType());
+                    rep.setHelpText(mapper.getHelpText());
+                    List<ProviderConfigProperty> configProperties = mapper.getConfigProperties();
+                    for (ProviderConfigProperty prop : configProperties) {
+                        ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
+                        propRep.setName(prop.getName());
+                        propRep.setLabel(prop.getLabel());
+                        propRep.setType(prop.getType());
+                        propRep.setDefaultValue(prop.getDefaultValue());
+                        propRep.setHelpText(prop.getHelpText());
+                        rep.getProperties().add(propRep);
+                    }
+                    types.put(rep.getId(), rep);
+                    break;
+                }
+            }
+        }
+        return types;
+    }
+
+    @GET
+    @Path("mappers")
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<IdentityProviderMapperRepresentation> getMappers() {
+        this.auth.requireView();
+        List<IdentityProviderMapperRepresentation> mappers = new LinkedList<>();
+        for (IdentityProviderMapperModel model : realm.getIdentityProviderMappersByAlias(identityProviderModel.getAlias())) {
+            mappers.add(ModelToRepresentation.toRepresentation(model));
+        }
+        return mappers;
+    }
+
+    @POST
+    @Path("mappers")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response addMapper(IdentityProviderMapperRepresentation mapper) {
+        auth.requireManage();
+        IdentityProviderMapperModel model = RepresentationToModel.toModel(mapper);
+        model = realm.addIdentityProviderMapper(model);
+        
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId())
+            .representation(mapper).success();
+        
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+
+    }
+
+    @GET
+    @NoCache
+    @Path("mappers/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public IdentityProviderMapperRepresentation getMapperById(@PathParam("id") String id) {
+        auth.requireView();
+        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        return ModelToRepresentation.toRepresentation(model);
+    }
+
+    @PUT
+    @NoCache
+    @Path("mappers/{id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void update(@PathParam("id") String id, IdentityProviderMapperRepresentation rep) {
+        auth.requireManage();
+        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        model = RepresentationToModel.toModel(rep);
+        realm.updateIdentityProviderMapper(model);
+        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+
+    }
+
+    @DELETE
+    @NoCache
+    @Path("mappers/{id}")
+    public void delete(@PathParam("id") String id) {
+        auth.requireManage();
+        IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        realm.removeIdentityProviderMapper(model);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+
+    }
+
+
+}
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 da58006..145a26d 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
@@ -1,162 +1,162 @@
-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;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Base resource for managing users
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProtocolMappersResource {
-    protected static final Logger logger = Logger.getLogger(ProtocolMappersResource.class);
-    
-    protected ClientModel client;
-
-    protected  RealmAuth auth;
-    
-    protected AdminEventBuilder adminEvent;
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected KeycloakSession session;
-
-    public ProtocolMappersResource(ClientModel client, RealmAuth auth, AdminEventBuilder adminEvent) {
-        this.auth = auth;
-        this.client = client;
-        this.adminEvent = adminEvent;
-
-        auth.init(RealmAuth.Resource.USER);
-    }
-
-    /**
-     * Map of mappers by name for a specific protocol
-     *
-     * @param protocol
-     * @return
-     */
-    @GET
-    @NoCache
-    @Path("protocol/{protocol}")
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<ProtocolMapperRepresentation> getMappersPerProtocol(@PathParam("protocol") String protocol) {
-        auth.requireView();
-        List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
-        for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
-            if (mapper.getProtocol().equals(protocol)) mappers.add(ModelToRepresentation.toRepresentation(mapper));
-        }
-        return mappers;
-    }
-
-    /**
-     * creates mapper
-     *
-     * @param rep
-     */
-    @Path("models")
-    @POST
-    @NoCache
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createMapper(ProtocolMapperRepresentation rep) {
-        auth.requireManage();
-        ProtocolMapperModel model = RepresentationToModel.toModel(rep);
-        model = client.addProtocolMapper(model);
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
-        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
-    }
-    /**
-     * creates multiple mapper
-     *
-     */
-    @Path("add-models")
-    @POST
-    @NoCache
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void createMapper(List<ProtocolMapperRepresentation> reps) {
-        auth.requireManage();
-        ProtocolMapperModel model = null;
-        for (ProtocolMapperRepresentation rep : reps) {
-            model = RepresentationToModel.toModel(rep);
-            model = client.addProtocolMapper(model);
-        }
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(reps).success();
-    }
-
-    @GET
-    @NoCache
-    @Path("models")
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<ProtocolMapperRepresentation> getMappers() {
-        auth.requireView();
-        List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
-        for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
-            mappers.add(ModelToRepresentation.toRepresentation(mapper));
-        }
-        return mappers;
-    }
-
-    @GET
-    @NoCache
-    @Path("models/{id}")
-    @Produces(MediaType.APPLICATION_JSON)
-    public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) {
-        auth.requireView();
-        ProtocolMapperModel model = client.getProtocolMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        return ModelToRepresentation.toRepresentation(model);
-    }
-
-    @PUT
-    @NoCache
-    @Path("models/{id}")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) {
-        auth.requireManage();
-        ProtocolMapperModel model = client.getProtocolMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        model = RepresentationToModel.toModel(rep);
-        client.updateProtocolMapper(model);
-        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-    }
-
-    @DELETE
-    @NoCache
-    @Path("models/{id}")
-    public void delete(@PathParam("id") String id) {
-        auth.requireManage();
-        ProtocolMapperModel model = client.getProtocolMapperById(id);
-        if (model == null) throw new NotFoundException("Model not found");
-        client.removeProtocolMapper(model);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-
-    }
-
-}
+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;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Base resource for managing users
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProtocolMappersResource {
+    protected static final Logger logger = Logger.getLogger(ProtocolMappersResource.class);
+    
+    protected ClientModel client;
+
+    protected  RealmAuth auth;
+    
+    protected AdminEventBuilder adminEvent;
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected KeycloakSession session;
+
+    public ProtocolMappersResource(ClientModel client, RealmAuth auth, AdminEventBuilder adminEvent) {
+        this.auth = auth;
+        this.client = client;
+        this.adminEvent = adminEvent;
+
+        auth.init(RealmAuth.Resource.USER);
+    }
+
+    /**
+     * Map of mappers by name for a specific protocol
+     *
+     * @param protocol
+     * @return
+     */
+    @GET
+    @NoCache
+    @Path("protocol/{protocol}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<ProtocolMapperRepresentation> getMappersPerProtocol(@PathParam("protocol") String protocol) {
+        auth.requireView();
+        List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
+        for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
+            if (mapper.getProtocol().equals(protocol)) mappers.add(ModelToRepresentation.toRepresentation(mapper));
+        }
+        return mappers;
+    }
+
+    /**
+     * creates mapper
+     *
+     * @param rep
+     */
+    @Path("models")
+    @POST
+    @NoCache
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createMapper(ProtocolMapperRepresentation rep) {
+        auth.requireManage();
+        ProtocolMapperModel model = RepresentationToModel.toModel(rep);
+        model = client.addProtocolMapper(model);
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+    }
+    /**
+     * creates multiple mapper
+     *
+     */
+    @Path("add-models")
+    @POST
+    @NoCache
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void createMapper(List<ProtocolMapperRepresentation> reps) {
+        auth.requireManage();
+        ProtocolMapperModel model = null;
+        for (ProtocolMapperRepresentation rep : reps) {
+            model = RepresentationToModel.toModel(rep);
+            model = client.addProtocolMapper(model);
+        }
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(reps).success();
+    }
+
+    @GET
+    @NoCache
+    @Path("models")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<ProtocolMapperRepresentation> getMappers() {
+        auth.requireView();
+        List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
+        for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
+            mappers.add(ModelToRepresentation.toRepresentation(mapper));
+        }
+        return mappers;
+    }
+
+    @GET
+    @NoCache
+    @Path("models/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) {
+        auth.requireView();
+        ProtocolMapperModel model = client.getProtocolMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        return ModelToRepresentation.toRepresentation(model);
+    }
+
+    @PUT
+    @NoCache
+    @Path("models/{id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) {
+        auth.requireManage();
+        ProtocolMapperModel model = client.getProtocolMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        model = RepresentationToModel.toModel(rep);
+        client.updateProtocolMapper(model);
+        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+    }
+
+    @DELETE
+    @NoCache
+    @Path("models/{id}")
+    public void delete(@PathParam("id") String id) {
+        auth.requireManage();
+        ProtocolMapperModel model = client.getProtocolMapperById(id);
+        if (model == null) throw new NotFoundException("Model not found");
+        client.removeProtocolMapper(model);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
index fc778d0..be3d6ed 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
@@ -1,99 +1,99 @@
-package org.keycloak.services.resources.admin;
-
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ImpersonationConstants;
-import org.keycloak.services.ForbiddenException;
-
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class RealmAuth {
-
-    private Resource resource;
-
-    public enum Resource {
-        CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER, IMPERSONATION
-    }
-
-    private AdminAuth auth;
-    private ClientModel realmAdminApp;
-
-    public RealmAuth(AdminAuth auth, ClientModel realmAdminApp) {
-        this.auth = auth;
-        this.realmAdminApp = realmAdminApp;
-    }
-
-    public RealmAuth init(Resource resource) {
-        this.resource = resource;
-        return this;
-    }
-
-    public AdminAuth getAuth() {
-        return auth;
-    }
-
-    public void requireAny() {
-        if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public boolean hasView() {
-        return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
-    }
-
-    public boolean hasManage() {
-        return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
-    }
-
-    public void requireView() {
-        if (!hasView()) {
-            throw new ForbiddenException();
-        }
-    }
-
-    public void requireManage() {
-        if (!hasManage()) {
-            throw new ForbiddenException();
-        }
-    }
-
-    private String getViewRole(Resource resource) {
-        switch (resource) {
-            case CLIENT:
-                return AdminRoles.VIEW_CLIENTS;
-            case USER:
-                return AdminRoles.VIEW_USERS;
-            case REALM:
-                return AdminRoles.VIEW_REALM;
-            case EVENTS:
-                return AdminRoles.VIEW_EVENTS;
-            case IDENTITY_PROVIDER:
-                return AdminRoles.VIEW_IDENTITY_PROVIDERS;
-            default:
-                throw new IllegalStateException();
-        }
-    }
-
-    private String getManageRole(Resource resource) {
-        switch (resource) {
-            case CLIENT:
-                return AdminRoles.MANAGE_CLIENTS;
-            case USER:
-                return AdminRoles.MANAGE_USERS;
-            case REALM:
-                return AdminRoles.MANAGE_REALM;
-            case EVENTS:
-                return AdminRoles.MANAGE_EVENTS;
-            case IDENTITY_PROVIDER:
-                return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
-            case IMPERSONATION:
-                return ImpersonationConstants.IMPERSONATION_ROLE;
-            default:
-                throw new IllegalStateException();
-        }
-    }
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ImpersonationConstants;
+import org.keycloak.services.ForbiddenException;
+
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class RealmAuth {
+
+    private Resource resource;
+
+    public enum Resource {
+        CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER, IMPERSONATION
+    }
+
+    private AdminAuth auth;
+    private ClientModel realmAdminApp;
+
+    public RealmAuth(AdminAuth auth, ClientModel realmAdminApp) {
+        this.auth = auth;
+        this.realmAdminApp = realmAdminApp;
+    }
+
+    public RealmAuth init(Resource resource) {
+        this.resource = resource;
+        return this;
+    }
+
+    public AdminAuth getAuth() {
+        return auth;
+    }
+
+    public void requireAny() {
+        if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public boolean hasView() {
+        return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
+    }
+
+    public boolean hasManage() {
+        return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
+    }
+
+    public void requireView() {
+        if (!hasView()) {
+            throw new ForbiddenException();
+        }
+    }
+
+    public void requireManage() {
+        if (!hasManage()) {
+            throw new ForbiddenException();
+        }
+    }
+
+    private String getViewRole(Resource resource) {
+        switch (resource) {
+            case CLIENT:
+                return AdminRoles.VIEW_CLIENTS;
+            case USER:
+                return AdminRoles.VIEW_USERS;
+            case REALM:
+                return AdminRoles.VIEW_REALM;
+            case EVENTS:
+                return AdminRoles.VIEW_EVENTS;
+            case IDENTITY_PROVIDER:
+                return AdminRoles.VIEW_IDENTITY_PROVIDERS;
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+    private String getManageRole(Resource resource) {
+        switch (resource) {
+            case CLIENT:
+                return AdminRoles.MANAGE_CLIENTS;
+            case USER:
+                return AdminRoles.MANAGE_USERS;
+            case REALM:
+                return AdminRoles.MANAGE_REALM;
+            case EVENTS:
+                return AdminRoles.MANAGE_EVENTS;
+            case IDENTITY_PROVIDER:
+                return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
+            case IMPERSONATION:
+                return ImpersonationConstants.IMPERSONATION_ROLE;
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+}
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 5b5a611..88117ca 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
@@ -1,234 +1,234 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.ClientConnection;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.ErrorResponse;
-import org.keycloak.util.JsonSerialization;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.CacheControl;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Top level resource for Admin REST API
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmsAdminResource {
-    protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
-    protected AdminAuth auth;
-    protected TokenManager tokenManager;
-
-    @Context
-    protected KeycloakSession session;
-    
-    @Context
-    protected KeycloakApplication keycloak;
-    
-    @Context
-    protected ClientConnection clientConnection;
-
-    public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
-        this.auth = auth;
-        this.tokenManager = tokenManager;
-    }
-
-    public static final CacheControl noCache = new CacheControl();
-
-    static {
-        noCache.setNoCache(true);
-    }
-
-    /**
-     * Returns a list of realms.  This list is filtered based on what realms the caller is allowed to view.
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<RealmRepresentation> getRealms() {
-        RealmManager realmManager = new RealmManager(session);
-        List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
-        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            List<RealmModel> realms = session.realms().getRealms();
-            for (RealmModel realm : realms) {
-                addRealmRep(reps, realm, realm.getMasterAdminClient());
-            }
-        } else {
-            ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
-            addRealmRep(reps, auth.getRealm(), adminApp);
-        }
-        logger.debug(("getRealms()"));
-        return reps;
-    }
-
-    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ClientModel realmManagementClient) {
-        if (auth.hasAppRole(realmManagementClient, AdminRoles.MANAGE_REALM)) {
-            reps.add(ModelToRepresentation.toRepresentation(realm, false));
-        } else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) {
-            RealmRepresentation rep = new RealmRepresentation();
-            rep.setRealm(realm.getName());
-            reps.add(rep);
-        }
-    }
-
-    /**
-     * Import a realm from a full representation of that realm.  Realm name must be unique.
-     *
-     * @param uriInfo
-     * @param rep JSON representation
-     * @return
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
-        RealmManager realmManager = new RealmManager(session);
-        realmManager.setContextPath(keycloak.getContextPath());
-        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            throw new ForbiddenException();
-        }
-        if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
-            throw new ForbiddenException();
-        }
-
-        logger.debugv("importRealm: {0}", rep.getRealm());
-
-        try {
-            RealmModel realm = realmManager.importRealm(rep);
-            grantPermissionsToRealmCreator(realm);
-
-            URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
-            logger.debugv("imported realm success, sending back: {0}", location.toString());
-            
-            return Response.created(location).build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
-        }
-    }
-
-    /**
-     * Upload a realm from a uploaded JSON file.  The posted represenation is expected to be a multipart/form-data encapsulation
-     * of a JSON file.  The same format a browser would use when uploading a file.
-     *
-     * @param uriInfo
-     * @param input multipart/form data
-     * @return
-     * @throws IOException
-     */
-    @POST
-    @Consumes(MediaType.MULTIPART_FORM_DATA)
-    public Response uploadRealm(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
-        RealmManager realmManager = new RealmManager(session);
-        realmManager.setContextPath(keycloak.getContextPath());
-        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            throw new ForbiddenException();
-        }
-        if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
-            throw new ForbiddenException();
-        }
-
-        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
-        List<InputPart> inputParts = uploadForm.get("file");
-        RealmRepresentation rep = null;
-        
-        for (InputPart inputPart : inputParts) {
-            // inputPart.getBody doesn't work as content-type is wrong, and inputPart.setMediaType is not supported on AS7 (RestEasy 2.3.2.Final)
-            rep = JsonSerialization.readValue(inputPart.getBodyAsString(), RealmRepresentation.class);
-
-            RealmModel realm = realmManager.importRealm(rep);
-
-            grantPermissionsToRealmCreator(realm);
-            
-            URI location = null;
-            if (inputParts.size() == 1) {
-                location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
-                return Response.created(location).build();
-            }
-        }
-        
-        return Response.noContent().build();
-    }
-
-    private void grantPermissionsToRealmCreator(RealmModel realm) {
-        if (auth.hasRealmRole(AdminRoles.ADMIN)) {
-            return;
-        }
-
-        RealmModel adminRealm = new RealmManager(session).getKeycloakAdminstrationRealm();
-        ClientModel realmAdminApp = realm.getMasterAdminClient();
-        for (String r : AdminRoles.ALL_REALM_ROLES) {
-            RoleModel role = realmAdminApp.getRole(r);
-            auth.getUser().grantRole(role);
-        }
-    }
-
-    /**
-     * Base path for the admin REST API for one particular realm.
-     *
-     * @param headers
-     * @param name realm name (not id!)
-     * @return
-     */
-    @Path("{realm}")
-    public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
-                                            @PathParam("realm") final String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) throw new NotFoundException("{realm} = " + name);
-
-        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())
-                && !auth.getRealm().equals(realm)) {
-            throw new ForbiddenException();
-        }
-        RealmAuth realmAuth;
-
-        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            realmAuth = new RealmAuth(auth, realm.getMasterAdminClient());
-        } else {
-            realmAuth = new RealmAuth(auth, realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())));
-        }
-        
-        AdminEventBuilder adminEvent = new AdminEventBuilder(realm, auth, session, clientConnection);
-        session.getContext().setRealm(realm);
-
-        RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager, adminEvent);
-        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
-        //resourceContext.initResource(adminResource);
-        return adminResource;
-    }
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.plugins.providers.multipart.InputPart;
+import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.ErrorResponse;
+import org.keycloak.util.JsonSerialization;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Top level resource for Admin REST API
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmsAdminResource {
+    protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
+    protected AdminAuth auth;
+    protected TokenManager tokenManager;
+
+    @Context
+    protected KeycloakSession session;
+    
+    @Context
+    protected KeycloakApplication keycloak;
+    
+    @Context
+    protected ClientConnection clientConnection;
+
+    public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
+        this.auth = auth;
+        this.tokenManager = tokenManager;
+    }
+
+    public static final CacheControl noCache = new CacheControl();
+
+    static {
+        noCache.setNoCache(true);
+    }
+
+    /**
+     * Returns a list of realms.  This list is filtered based on what realms the caller is allowed to view.
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<RealmRepresentation> getRealms() {
+        RealmManager realmManager = new RealmManager(session);
+        List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
+        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+            List<RealmModel> realms = session.realms().getRealms();
+            for (RealmModel realm : realms) {
+                addRealmRep(reps, realm, realm.getMasterAdminClient());
+            }
+        } else {
+            ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
+            addRealmRep(reps, auth.getRealm(), adminApp);
+        }
+        logger.debug(("getRealms()"));
+        return reps;
+    }
+
+    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ClientModel realmManagementClient) {
+        if (auth.hasAppRole(realmManagementClient, AdminRoles.MANAGE_REALM)) {
+            reps.add(ModelToRepresentation.toRepresentation(realm, false));
+        } else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) {
+            RealmRepresentation rep = new RealmRepresentation();
+            rep.setRealm(realm.getName());
+            reps.add(rep);
+        }
+    }
+
+    /**
+     * Import a realm from a full representation of that realm.  Realm name must be unique.
+     *
+     * @param uriInfo
+     * @param rep JSON representation
+     * @return
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
+        RealmManager realmManager = new RealmManager(session);
+        realmManager.setContextPath(keycloak.getContextPath());
+        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+            throw new ForbiddenException();
+        }
+        if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
+            throw new ForbiddenException();
+        }
+
+        logger.debugv("importRealm: {0}", rep.getRealm());
+
+        try {
+            RealmModel realm = realmManager.importRealm(rep);
+            grantPermissionsToRealmCreator(realm);
+
+            URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
+            logger.debugv("imported realm success, sending back: {0}", location.toString());
+            
+            return Response.created(location).build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
+        }
+    }
+
+    /**
+     * Upload a realm from a uploaded JSON file.  The posted represenation is expected to be a multipart/form-data encapsulation
+     * of a JSON file.  The same format a browser would use when uploading a file.
+     *
+     * @param uriInfo
+     * @param input multipart/form data
+     * @return
+     * @throws IOException
+     */
+    @POST
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    public Response uploadRealm(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
+        RealmManager realmManager = new RealmManager(session);
+        realmManager.setContextPath(keycloak.getContextPath());
+        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+            throw new ForbiddenException();
+        }
+        if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
+            throw new ForbiddenException();
+        }
+
+        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
+        List<InputPart> inputParts = uploadForm.get("file");
+        RealmRepresentation rep = null;
+        
+        for (InputPart inputPart : inputParts) {
+            // inputPart.getBody doesn't work as content-type is wrong, and inputPart.setMediaType is not supported on AS7 (RestEasy 2.3.2.Final)
+            rep = JsonSerialization.readValue(inputPart.getBodyAsString(), RealmRepresentation.class);
+
+            RealmModel realm = realmManager.importRealm(rep);
+
+            grantPermissionsToRealmCreator(realm);
+            
+            URI location = null;
+            if (inputParts.size() == 1) {
+                location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
+                return Response.created(location).build();
+            }
+        }
+        
+        return Response.noContent().build();
+    }
+
+    private void grantPermissionsToRealmCreator(RealmModel realm) {
+        if (auth.hasRealmRole(AdminRoles.ADMIN)) {
+            return;
+        }
+
+        RealmModel adminRealm = new RealmManager(session).getKeycloakAdminstrationRealm();
+        ClientModel realmAdminApp = realm.getMasterAdminClient();
+        for (String r : AdminRoles.ALL_REALM_ROLES) {
+            RoleModel role = realmAdminApp.getRole(r);
+            auth.getUser().grantRole(role);
+        }
+    }
+
+    /**
+     * Base path for the admin REST API for one particular realm.
+     *
+     * @param headers
+     * @param name realm name (not id!)
+     * @return
+     */
+    @Path("{realm}")
+    public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
+                                            @PathParam("realm") final String name) {
+        RealmManager realmManager = new RealmManager(session);
+        RealmModel realm = realmManager.getRealmByName(name);
+        if (realm == null) throw new NotFoundException("{realm} = " + name);
+
+        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())
+                && !auth.getRealm().equals(realm)) {
+            throw new ForbiddenException();
+        }
+        RealmAuth realmAuth;
+
+        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+            realmAuth = new RealmAuth(auth, realm.getMasterAdminClient());
+        } else {
+            realmAuth = new RealmAuth(auth, realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())));
+        }
+        
+        AdminEventBuilder adminEvent = new AdminEventBuilder(realm, auth, session, clientConnection);
+        session.getContext().setRealm(realm);
+
+        RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager, adminEvent);
+        ResteasyProviderFactory.getInstance().injectProperties(adminResource);
+        //resourceContext.initResource(adminResource);
+        return adminResource;
+    }
+
+}
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 e713640..563d2ca 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
@@ -1,231 +1,231 @@
-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;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.RoleRepresentation;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Sometimes its easier to just interact with roles by their ID instead of container/role-name
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleByIdResource extends RoleResource {
-    protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
-    private final RealmModel realm;
-    private final RealmAuth auth;
-    private AdminEventBuilder adminEvent;
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private UriInfo uriInfo;
-
-    public RoleByIdResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
-        super(realm);
-
-        this.realm = realm;
-        this.auth = auth;
-        this.adminEvent = adminEvent;
-    }
-
-    /**
-     * Get a specific role's representation
-     *
-     * @param id id of role
-     * @return
-     */
-    @Path("{role-id}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public RoleRepresentation getRole(final @PathParam("role-id") String id) {
-        RoleModel roleModel = getRoleModel(id);
-        auth.requireView();
-        return getRole(roleModel);
-    }
-
-    protected RoleModel getRoleModel(String id) {
-        RoleModel roleModel = realm.getRoleById(id);
-        if (roleModel == null) {
-            throw new NotFoundException("Could not find role with id: " + id);
-        }
-
-        RealmAuth.Resource r = null;
-        if (roleModel.getContainer() instanceof RealmModel) {
-            r = RealmAuth.Resource.REALM;
-        } else if (roleModel.getContainer() instanceof ClientModel) {
-            r = RealmAuth.Resource.CLIENT;
-        } else if (roleModel.getContainer() instanceof UserModel) {
-            r = RealmAuth.Resource.USER;
-        }
-        auth.init(r);
-        return roleModel;
-    }
-
-    /**
-     * Delete this role
-     *
-     * @param id id of role
-     */
-    @Path("{role-id}")
-    @DELETE
-    @NoCache
-    public void deleteRole(final @PathParam("role-id") String id) {
-        RoleModel role = getRoleModel(id);
-        auth.requireManage();
-        deleteRole(role);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * Update this role
-     *
-     * @param id id of role
-     * @param rep
-     */
-    @Path("{role-id}")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
-        RoleModel role = getRoleModel(id);
-        auth.requireManage();
-        updateRole(rep, role);
-        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-    }
-
-    /**
-     * Make this role a composite role by associating some child roles to it.
-     *
-     * @param id
-     * @param roles
-     */
-    @Path("{role-id}/composites")
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
-        RoleModel role = getRoleModel(id);
-        auth.requireManage();
-        addComposites(adminEvent, uriInfo, roles, role);
-    }
-
-    /**
-     * If this role is a composite, return a set of its children
-     *
-     * @param id
-     * @return
-     */
-    @Path("{role-id}/composites")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
-
-        if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'");
-        RoleModel role = getRoleModel(id);
-        auth.requireView();
-        return getRoleComposites(role);
-    }
-
-    /**
-     * Return a set of realm-level roles that are in the role's composite
-     *
-     * @param id
-     * @return
-     */
-    @Path("{role-id}/composites/realm")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
-        RoleModel role = getRoleModel(id);
-        auth.requireView();
-        return getRealmRoleComposites(role);
-    }
-
-    /**
-     * Return a set of client-level roles for a specific client that are in the role's composite
-     *
-     * @param id
-     * @param client
-     * @return
-     */
-    @Path("{role-id}/composites/clients/{client}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-id") String id,
-                                                                final @PathParam("client") String client) {
-        RoleModel role = getRoleModel(id);
-        auth.requireView();
-        ClientModel clientModel = realm.getClientById(client);
-        if (clientModel == null) {
-            throw new NotFoundException("Could not find client: " + client);
-        }
-        return getClientRoleComposites(clientModel, role);
-    }
-
-    /**
-     * Return a set of client-level roles for a specific client that are in the role's composite
-     *
-     * @param role
-     * @param client
-     * @return
-     */
-    @Path("{role-id}/composites/clients/{client}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getClientByIdRoleComposites(final @PathParam("role-id") String role,
-                                                                final @PathParam("client") String client) {
-        RoleModel roleModel = getRoleModel(role);
-        auth.requireView();
-        ClientModel clientModel = realm.getClientById(client);
-        if (clientModel == null) {
-            throw new NotFoundException("Could not find client: " + client);
-
-        }
-        return getClientRoleComposites(clientModel, roleModel);
-    }
-
-    /**
-     * Remove the listed set of roles from this role's composite
-     *
-     * @param id
-     * @param roles
-     */
-    @Path("{role-id}/composites")
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
-        RoleModel role = getRoleModel(id);
-        auth.requireManage();
-        deleteComposites(roles, role);
-        
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
-    }
-
-}
+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;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Sometimes its easier to just interact with roles by their ID instead of container/role-name
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleByIdResource extends RoleResource {
+    protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
+    private final RealmModel realm;
+    private final RealmAuth auth;
+    private AdminEventBuilder adminEvent;
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private UriInfo uriInfo;
+
+    public RoleByIdResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+        super(realm);
+
+        this.realm = realm;
+        this.auth = auth;
+        this.adminEvent = adminEvent;
+    }
+
+    /**
+     * Get a specific role's representation
+     *
+     * @param id id of role
+     * @return
+     */
+    @Path("{role-id}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public RoleRepresentation getRole(final @PathParam("role-id") String id) {
+        RoleModel roleModel = getRoleModel(id);
+        auth.requireView();
+        return getRole(roleModel);
+    }
+
+    protected RoleModel getRoleModel(String id) {
+        RoleModel roleModel = realm.getRoleById(id);
+        if (roleModel == null) {
+            throw new NotFoundException("Could not find role with id: " + id);
+        }
+
+        RealmAuth.Resource r = null;
+        if (roleModel.getContainer() instanceof RealmModel) {
+            r = RealmAuth.Resource.REALM;
+        } else if (roleModel.getContainer() instanceof ClientModel) {
+            r = RealmAuth.Resource.CLIENT;
+        } else if (roleModel.getContainer() instanceof UserModel) {
+            r = RealmAuth.Resource.USER;
+        }
+        auth.init(r);
+        return roleModel;
+    }
+
+    /**
+     * Delete this role
+     *
+     * @param id id of role
+     */
+    @Path("{role-id}")
+    @DELETE
+    @NoCache
+    public void deleteRole(final @PathParam("role-id") String id) {
+        RoleModel role = getRoleModel(id);
+        auth.requireManage();
+        deleteRole(role);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * Update this role
+     *
+     * @param id id of role
+     * @param rep
+     */
+    @Path("{role-id}")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
+        RoleModel role = getRoleModel(id);
+        auth.requireManage();
+        updateRole(rep, role);
+        adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+    }
+
+    /**
+     * Make this role a composite role by associating some child roles to it.
+     *
+     * @param id
+     * @param roles
+     */
+    @Path("{role-id}/composites")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
+        RoleModel role = getRoleModel(id);
+        auth.requireManage();
+        addComposites(adminEvent, uriInfo, roles, role);
+    }
+
+    /**
+     * If this role is a composite, return a set of its children
+     *
+     * @param id
+     * @return
+     */
+    @Path("{role-id}/composites")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
+
+        if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'");
+        RoleModel role = getRoleModel(id);
+        auth.requireView();
+        return getRoleComposites(role);
+    }
+
+    /**
+     * Return a set of realm-level roles that are in the role's composite
+     *
+     * @param id
+     * @return
+     */
+    @Path("{role-id}/composites/realm")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
+        RoleModel role = getRoleModel(id);
+        auth.requireView();
+        return getRealmRoleComposites(role);
+    }
+
+    /**
+     * Return a set of client-level roles for a specific client that are in the role's composite
+     *
+     * @param id
+     * @param client
+     * @return
+     */
+    @Path("{role-id}/composites/clients/{client}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-id") String id,
+                                                                final @PathParam("client") String client) {
+        RoleModel role = getRoleModel(id);
+        auth.requireView();
+        ClientModel clientModel = realm.getClientById(client);
+        if (clientModel == null) {
+            throw new NotFoundException("Could not find client: " + client);
+        }
+        return getClientRoleComposites(clientModel, role);
+    }
+
+    /**
+     * Return a set of client-level roles for a specific client that are in the role's composite
+     *
+     * @param role
+     * @param client
+     * @return
+     */
+    @Path("{role-id}/composites/clients/{client}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientByIdRoleComposites(final @PathParam("role-id") String role,
+                                                                final @PathParam("client") String client) {
+        RoleModel roleModel = getRoleModel(role);
+        auth.requireView();
+        ClientModel clientModel = realm.getClientById(client);
+        if (clientModel == null) {
+            throw new NotFoundException("Could not find client: " + client);
+
+        }
+        return getClientRoleComposites(clientModel, roleModel);
+    }
+
+    /**
+     * Remove the listed set of roles from this role's composite
+     *
+     * @param id
+     * @param roles
+     */
+    @Path("{role-id}/composites")
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
+        RoleModel role = getRoleModel(id);
+        auth.requireManage();
+        deleteComposites(roles, role);
+        
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 2b225b6..3c57672 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -1,276 +1,276 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleContainerModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.services.ErrorResponse;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RoleContainerResource extends RoleResource {
-    private final RealmModel realm;
-    private final RealmAuth auth;
-    protected RoleContainerModel roleContainer;
-    private AdminEventBuilder adminEvent;
-    private UriInfo uriInfo;
-
-    public RoleContainerResource(UriInfo uriInfo, RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer, AdminEventBuilder adminEvent) {
-        super(realm);
-        this.uriInfo = uriInfo;
-        this.realm = realm;
-        this.auth = auth;
-        this.roleContainer = roleContainer;
-        this.adminEvent = adminEvent;
-    }
-
-    /**
-     * List all roles for this realm or client
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<RoleRepresentation> getRoles() {
-        auth.requireAny();
-
-        Set<RoleModel> roleModels = roleContainer.getRoles();
-        List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roleModels) {
-            roles.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return roles;
-    }
-
-    /**
-     * Create a new role for this realm or client
-     *
-     * @param rep
-     * @return
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createRole(final RoleRepresentation rep) {
-        auth.requireManage();
-
-        try {
-            RoleModel role = roleContainer.addRole(rep.getName());
-            role.setDescription(rep.getDescription());
-
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(rep).success();
-
-            return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
-        }
-    }
-
-    /**
-     * Get a role by name
-     *
-     * @param roleName role's name (not id!)
-     * @return
-     */
-    @Path("{role-name}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public RoleRepresentation getRole(final @PathParam("role-name") String roleName) {
-        auth.requireView();
-
-        RoleModel roleModel = roleContainer.getRole(roleName);
-        if (roleModel == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-
-        return getRole(roleModel);
-    }
-
-    /**
-     * Delete a role by name
-     *
-     * @param roleName role's name (not id!)
-     */
-    @Path("{role-name}")
-    @DELETE
-    @NoCache
-    public void deleteRole(final @PathParam("role-name") String roleName) {
-        auth.requireManage();
-
-        RoleRepresentation rep = getRole(roleName);
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        deleteRole(role);
-
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-
-    }
-
-    /**
-     * Update a role by name
-     *
-     * @param roleName role's name (not id!)
-     * @param rep
-     * @return
-     */
-    @Path("{role-name}")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        try {
-            updateRole(rep, role);
-
-            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-
-            return Response.noContent().build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
-        }
-    }
-
-    /**
-     * Add a composite to this role
-     *
-     * @param roleName role's name (not id!)
-     * @param roles
-     */
-    @Path("{role-name}/composites")
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        addComposites(adminEvent, uriInfo, roles, role);
-    }
-
-    /**
-     * List composites of this role
-     *
-     * @param roleName role's name (not id!)
-     * @return
-     */
-    @Path("{role-name}/composites")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        return getRoleComposites(role);
-    }
-
-    /**
-     * Get realm-level roles of this role's composite
-     *
-     * @param roleName role's name (not id!)
-     * @return
-     */
-    @Path("{role-name}/composites/realm")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-name") String roleName) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        return getRealmRoleComposites(role);
-    }
-
-    /**
-     * An app-level roles for a specific app for this role's composite
-     *
-     * @param roleName role's name (not id!)
-     * @param client
-     * @return
-     */
-    @Path("{role-name}/composites/clients/{client}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Set<RoleRepresentation> getClientRoleComposites(@Context final UriInfo uriInfo,
-                                                                final @PathParam("role-name") String roleName,
-                                                                final @PathParam("client") String client) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        ClientModel clientModel = realm.getClientById(client);
-        if (client == null) {
-            throw new NotFoundException("Could not find client: " + client);
-
-        }
-        return getClientRoleComposites(clientModel, role);
-    }
-
-
-    /**
-     * Remove roles from this role's composite
-     *
-     * @param roleName role's name (not id!)
-     * @param roles roles to remove
-     */
-    @Path("{role-name}/composites")
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteComposites(
-                                   final @PathParam("role-name") String roleName,
-                                   List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        RoleModel role = roleContainer.getRole(roleName);
-        if (role == null) {
-            throw new NotFoundException("Could not find role: " + roleName);
-        }
-        deleteComposites(roles, role);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.ErrorResponse;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleContainerResource extends RoleResource {
+    private final RealmModel realm;
+    private final RealmAuth auth;
+    protected RoleContainerModel roleContainer;
+    private AdminEventBuilder adminEvent;
+    private UriInfo uriInfo;
+
+    public RoleContainerResource(UriInfo uriInfo, RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer, AdminEventBuilder adminEvent) {
+        super(realm);
+        this.uriInfo = uriInfo;
+        this.realm = realm;
+        this.auth = auth;
+        this.roleContainer = roleContainer;
+        this.adminEvent = adminEvent;
+    }
+
+    /**
+     * List all roles for this realm or client
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<RoleRepresentation> getRoles() {
+        auth.requireAny();
+
+        Set<RoleModel> roleModels = roleContainer.getRoles();
+        List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roleModels) {
+            roles.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return roles;
+    }
+
+    /**
+     * Create a new role for this realm or client
+     *
+     * @param rep
+     * @return
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createRole(final RoleRepresentation rep) {
+        auth.requireManage();
+
+        try {
+            RoleModel role = roleContainer.addRole(rep.getName());
+            role.setDescription(rep.getDescription());
+
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(rep).success();
+
+            return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
+        }
+    }
+
+    /**
+     * Get a role by name
+     *
+     * @param roleName role's name (not id!)
+     * @return
+     */
+    @Path("{role-name}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public RoleRepresentation getRole(final @PathParam("role-name") String roleName) {
+        auth.requireView();
+
+        RoleModel roleModel = roleContainer.getRole(roleName);
+        if (roleModel == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+
+        return getRole(roleModel);
+    }
+
+    /**
+     * Delete a role by name
+     *
+     * @param roleName role's name (not id!)
+     */
+    @Path("{role-name}")
+    @DELETE
+    @NoCache
+    public void deleteRole(final @PathParam("role-name") String roleName) {
+        auth.requireManage();
+
+        RoleRepresentation rep = getRole(roleName);
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        deleteRole(role);
+
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+
+    }
+
+    /**
+     * Update a role by name
+     *
+     * @param roleName role's name (not id!)
+     * @param rep
+     * @return
+     */
+    @Path("{role-name}")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        try {
+            updateRole(rep, role);
+
+            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+
+            return Response.noContent().build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
+        }
+    }
+
+    /**
+     * Add a composite to this role
+     *
+     * @param roleName role's name (not id!)
+     * @param roles
+     */
+    @Path("{role-name}/composites")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        addComposites(adminEvent, uriInfo, roles, role);
+    }
+
+    /**
+     * List composites of this role
+     *
+     * @param roleName role's name (not id!)
+     * @return
+     */
+    @Path("{role-name}/composites")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        return getRoleComposites(role);
+    }
+
+    /**
+     * Get realm-level roles of this role's composite
+     *
+     * @param roleName role's name (not id!)
+     * @return
+     */
+    @Path("{role-name}/composites/realm")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-name") String roleName) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        return getRealmRoleComposites(role);
+    }
+
+    /**
+     * An app-level roles for a specific app for this role's composite
+     *
+     * @param roleName role's name (not id!)
+     * @param client
+     * @return
+     */
+    @Path("{role-name}/composites/clients/{client}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientRoleComposites(@Context final UriInfo uriInfo,
+                                                                final @PathParam("role-name") String roleName,
+                                                                final @PathParam("client") String client) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        ClientModel clientModel = realm.getClientById(client);
+        if (client == null) {
+            throw new NotFoundException("Could not find client: " + client);
+
+        }
+        return getClientRoleComposites(clientModel, role);
+    }
+
+
+    /**
+     * Remove roles from this role's composite
+     *
+     * @param roleName role's name (not id!)
+     * @param roles roles to remove
+     */
+    @Path("{role-name}/composites")
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteComposites(
+                                   final @PathParam("role-name") String roleName,
+                                   List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        RoleModel role = roleContainer.getRole(roleName);
+        if (role == null) {
+            throw new NotFoundException("Could not find role: " + roleName);
+        }
+        deleteComposites(roles, role);
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
index ee6c73a..ded9193 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
@@ -1,96 +1,96 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-
-import javax.ws.rs.core.UriInfo;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class RoleResource {
-    protected RealmModel realm;
-
-    public RoleResource(RealmModel realm) {
-        this.realm = realm;
-    }
-
-    protected RoleRepresentation getRole(RoleModel roleModel) {
-        return ModelToRepresentation.toRepresentation(roleModel);
-    }
-
-    protected void deleteRole(RoleModel role) {
-        if (!role.getContainer().removeRole(role)) {
-            throw new NotFoundException("Role not found");
-        }
-    }
-
-    protected void updateRole(RoleRepresentation rep, RoleModel role) {
-        role.setName(rep.getName());
-        role.setDescription(rep.getDescription());
-    }
-
-    protected void addComposites(AdminEventBuilder adminEvent, UriInfo uriInfo, List<RoleRepresentation> roles, RoleModel role) {
-        for (RoleRepresentation rep : roles) {
-            RoleModel composite = realm.getRoleById(rep.getId());
-            if (composite == null) {
-                throw new NotFoundException("Could not find composite role: " + rep.getName());
-            }
-            role.addCompositeRole(composite);
-
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, rep.getId()).representation(roles).success();
-        }
-    }
-
-    protected Set<RoleRepresentation> getRoleComposites(RoleModel role) {
-        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
-
-        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
-        for (RoleModel composite : role.getComposites()) {
-            composites.add(ModelToRepresentation.toRepresentation(composite));
-        }
-        return composites;
-    }
-
-    protected Set<RoleRepresentation> getRealmRoleComposites(RoleModel role) {
-        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
-
-        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
-        for (RoleModel composite : role.getComposites()) {
-            if (composite.getContainer() instanceof RealmModel)
-                composites.add(ModelToRepresentation.toRepresentation(composite));
-        }
-        return composites;
-    }
-
-    protected Set<RoleRepresentation> getClientRoleComposites(ClientModel app, RoleModel role) {
-        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
-
-        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
-        for (RoleModel composite : role.getComposites()) {
-            if (composite.getContainer().equals(app))
-                composites.add(ModelToRepresentation.toRepresentation(composite));
-        }
-        return composites;
-    }
-
-    protected void deleteComposites(List<RoleRepresentation> roles, RoleModel role) {
-        for (RoleRepresentation rep : roles) {
-            RoleModel composite = realm.getRoleById(rep.getId());
-            if (composite == null) {
-                throw new NotFoundException("Could not find composite role: " + rep.getName());
-            }
-            role.removeCompositeRole(composite);
-        }
-    }
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.core.UriInfo;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class RoleResource {
+    protected RealmModel realm;
+
+    public RoleResource(RealmModel realm) {
+        this.realm = realm;
+    }
+
+    protected RoleRepresentation getRole(RoleModel roleModel) {
+        return ModelToRepresentation.toRepresentation(roleModel);
+    }
+
+    protected void deleteRole(RoleModel role) {
+        if (!role.getContainer().removeRole(role)) {
+            throw new NotFoundException("Role not found");
+        }
+    }
+
+    protected void updateRole(RoleRepresentation rep, RoleModel role) {
+        role.setName(rep.getName());
+        role.setDescription(rep.getDescription());
+    }
+
+    protected void addComposites(AdminEventBuilder adminEvent, UriInfo uriInfo, List<RoleRepresentation> roles, RoleModel role) {
+        for (RoleRepresentation rep : roles) {
+            RoleModel composite = realm.getRoleById(rep.getId());
+            if (composite == null) {
+                throw new NotFoundException("Could not find composite role: " + rep.getName());
+            }
+            role.addCompositeRole(composite);
+
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, rep.getId()).representation(roles).success();
+        }
+    }
+
+    protected Set<RoleRepresentation> getRoleComposites(RoleModel role) {
+        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
+
+        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
+        for (RoleModel composite : role.getComposites()) {
+            composites.add(ModelToRepresentation.toRepresentation(composite));
+        }
+        return composites;
+    }
+
+    protected Set<RoleRepresentation> getRealmRoleComposites(RoleModel role) {
+        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
+
+        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
+        for (RoleModel composite : role.getComposites()) {
+            if (composite.getContainer() instanceof RealmModel)
+                composites.add(ModelToRepresentation.toRepresentation(composite));
+        }
+        return composites;
+    }
+
+    protected Set<RoleRepresentation> getClientRoleComposites(ClientModel app, RoleModel role) {
+        if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
+
+        Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
+        for (RoleModel composite : role.getComposites()) {
+            if (composite.getContainer().equals(app))
+                composites.add(ModelToRepresentation.toRepresentation(composite));
+        }
+        return composites;
+    }
+
+    protected void deleteComposites(List<RoleRepresentation> roles, RoleModel role) {
+        for (RoleRepresentation rep : roles) {
+            RoleModel composite = realm.getRoleById(rep.getId());
+            if (composite == null) {
+                throw new NotFoundException("Could not find composite role: " + rep.getName());
+            }
+            role.removeCompositeRole(composite);
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
index 6a5c6a4..c087197 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
@@ -1,144 +1,144 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ScopeMappedClientResource {
-    protected RealmModel realm;
-    private RealmAuth auth;
-    protected ClientModel client;
-    protected KeycloakSession session;
-    protected ClientModel scopedClient;
-    protected AdminEventBuilder adminEvent;
-    
-    public ScopeMappedClientResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, ClientModel scopedClient, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.auth = auth;
-        this.client = client;
-        this.session = session;
-        this.scopedClient = scopedClient;
-        this.adminEvent = adminEvent;
-    }
-
-    /**
-     * Get the roles associated with a client's scope for a specific client.
-     *
-     * @return
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getClientScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> mappings = scopedClient.getClientScopeMappings(client);
-        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : mappings) {
-            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return mapRep;
-    }
-
-    /**
-     * The available client-level roles that can be associated with the client's scope
-     *
-     * @return
-     */
-    @Path("available")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getAvailableClientScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> roles = scopedClient.getRoles();
-        return ScopeMappedResource.getAvailable(client, roles);
-    }
-
-    /**
-     * Get effective client roles that are associated with the client's scope for a specific client.
-     *
-     * @return
-     */
-    @Path("composite")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getCompositeClientScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> roles = scopedClient.getRoles();
-        return ScopeMappedResource.getComposite(client, roles);
-    }
-
-    /**
-     * Add client-level roles to the client's scope
-     *
-     * @param roles
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addClientScopeMapping(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        for (RoleRepresentation role : roles) {
-            RoleModel roleModel = scopedClient.getRole(role.getName());
-            if (roleModel == null) {
-                throw new NotFoundException("Role not found");
-            }
-            client.addScopeMapping(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
-        }
-    }
-
-    /**
-     * Remove client-level roles from the client's scope.
-     *
-     * @param roles
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteClientScopeMapping(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        if (roles == null) {
-            Set<RoleModel> roleModels = scopedClient.getClientScopeMappings(client);
-            for (RoleModel roleModel : roleModels) {
-                client.deleteScopeMapping(roleModel);
-            }
-            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
-        } else {
-            for (RoleRepresentation role : roles) {
-                RoleModel roleModel = scopedClient.getRole(role.getName());
-                if (roleModel == null) {
-                    throw new NotFoundException("Role not found");
-                }
-                client.deleteScopeMapping(roleModel);
-                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
-            }
-        }
-    }
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ScopeMappedClientResource {
+    protected RealmModel realm;
+    private RealmAuth auth;
+    protected ClientModel client;
+    protected KeycloakSession session;
+    protected ClientModel scopedClient;
+    protected AdminEventBuilder adminEvent;
+    
+    public ScopeMappedClientResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, ClientModel scopedClient, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.auth = auth;
+        this.client = client;
+        this.session = session;
+        this.scopedClient = scopedClient;
+        this.adminEvent = adminEvent;
+    }
+
+    /**
+     * Get the roles associated with a client's scope for a specific client.
+     *
+     * @return
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getClientScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> mappings = scopedClient.getClientScopeMappings(client);
+        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : mappings) {
+            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return mapRep;
+    }
+
+    /**
+     * The available client-level roles that can be associated with the client's scope
+     *
+     * @return
+     */
+    @Path("available")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getAvailableClientScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> roles = scopedClient.getRoles();
+        return ScopeMappedResource.getAvailable(client, roles);
+    }
+
+    /**
+     * Get effective client roles that are associated with the client's scope for a specific client.
+     *
+     * @return
+     */
+    @Path("composite")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getCompositeClientScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> roles = scopedClient.getRoles();
+        return ScopeMappedResource.getComposite(client, roles);
+    }
+
+    /**
+     * Add client-level roles to the client's scope
+     *
+     * @param roles
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addClientScopeMapping(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = scopedClient.getRole(role.getName());
+            if (roleModel == null) {
+                throw new NotFoundException("Role not found");
+            }
+            client.addScopeMapping(roleModel);
+            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
+        }
+    }
+
+    /**
+     * Remove client-level roles from the client's scope.
+     *
+     * @param roles
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteClientScopeMapping(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        if (roles == null) {
+            Set<RoleModel> roleModels = scopedClient.getClientScopeMappings(client);
+            for (RoleModel roleModel : roleModels) {
+                client.deleteScopeMapping(roleModel);
+            }
+            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
+        } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = scopedClient.getRole(role.getName());
+                if (roleModel == null) {
+                    throw new NotFoundException("Role not found");
+                }
+                client.deleteScopeMapping(roleModel);
+                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
+            }
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
index d443a43..4075944 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
@@ -1,226 +1,226 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.ClientMappingsRepresentation;
-import org.keycloak.representations.idm.MappingsRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Base class for managing the scope mappings of a specific client.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ScopeMappedResource {
-    protected RealmModel realm;
-    private RealmAuth auth;
-    protected ClientModel client;
-    protected KeycloakSession session;
-    protected AdminEventBuilder adminEvent;
-
-    public ScopeMappedResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, AdminEventBuilder adminEvent) {
-        this.realm = realm;
-        this.auth = auth;
-        this.client = client;
-        this.session = session;
-        this.adminEvent = adminEvent;
-    }
-
-    /**
-     * Get all scope mappings for this client
-     *
-     * @return
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public MappingsRepresentation getScopeMappings() {
-        auth.requireView();
-
-        MappingsRepresentation all = new MappingsRepresentation();
-        Set<RoleModel> realmMappings = client.getRealmScopeMappings();
-        if (realmMappings.size() > 0) {
-            List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
-            for (RoleModel roleModel : realmMappings) {
-                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
-            }
-            all.setRealmMappings(realmRep);
-        }
-
-        List<ClientModel> clients = realm.getClients();
-        if (clients.size() > 0) {
-            Map<String, ClientMappingsRepresentation> clientMappings = new HashMap<String, ClientMappingsRepresentation>();
-            for (ClientModel client : clients) {
-                Set<RoleModel> roleMappings = client.getClientScopeMappings(this.client);
-                if (roleMappings.size() > 0) {
-                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
-                    mappings.setId(client.getId());
-                    mappings.setClient(client.getClientId());
-                    List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
-                    mappings.setMappings(roles);
-                    for (RoleModel role : roleMappings) {
-                        roles.add(ModelToRepresentation.toRepresentation(role));
-                    }
-                    clientMappings.put(client.getClientId(), mappings);
-                    all.setClientMappings(clientMappings);
-                }
-            }
-        }
-        return all;
-    }
-
-    /**
-     * Get list of realm-level roles associated with this client's scope.
-     *
-     * @return
-     */
-    @Path("realm")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getRealmScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> realmMappings = client.getRealmScopeMappings();
-        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : realmMappings) {
-            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return realmMappingsRep;
-    }
-
-    /**
-     * Get list of realm-level roles that are available to attach to this client's scope.
-     *
-     * @return
-     */
-    @Path("realm/available")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getAvailableRealmScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> roles = realm.getRoles();
-        return getAvailable(client, roles);
-    }
-
-    public static List<RoleRepresentation> getAvailable(ClientModel client, Set<RoleModel> roles) {
-        List<RoleRepresentation> available = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roles) {
-            if (client.hasScope(roleModel)) continue;
-            available.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return available;
-    }
-
-    /**
-     * Get all effective realm-level roles that are associated with this client's scope.  What this does is recurse
-     * any composite roles associated with the client's scope and adds the roles to this lists.  The method is really
-     * to show a comprehensive total view of realm-level roles associated with the client.
-     *
-     * @return
-     */
-    @Path("realm/composite")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getCompositeRealmScopeMappings() {
-        auth.requireView();
-
-        Set<RoleModel> roles = realm.getRoles();
-        return getComposite(client, roles);
-    }
-
-    public static List<RoleRepresentation> getComposite(ClientModel client, Set<RoleModel> roles) {
-        List<RoleRepresentation> composite = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roles) {
-            if (client.hasScope(roleModel)) composite.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return composite;
-    }
-
-    /**
-     * Add a set of realm-level roles to the client's scope
-     *
-     * @param roles
-     */
-    @Path("realm")
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addRealmScopeMappings(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        for (RoleRepresentation role : roles) {
-            RoleModel roleModel = realm.getRoleById(role.getId());
-            if (roleModel == null) {
-                throw new NotFoundException("Role not found");
-            }
-            client.addScopeMapping(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), role.getId()).representation(roles).success();
-        }
-    }
-
-    /**
-     * Remove a set of realm-level roles from the client's scope
-     *
-     * @param roles
-     */
-    @Path("realm")
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        if (roles == null) {
-            Set<RoleModel> roleModels = client.getRealmScopeMappings();
-            for (RoleModel roleModel : roleModels) {
-                client.deleteScopeMapping(roleModel);
-            }
-            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
-       } else {
-            for (RoleRepresentation role : roles) {
-                RoleModel roleModel = realm.getRoleById(role.getId());
-                if (roleModel == null) {
-                    throw new NotFoundException("Client not found");
-                }
-                client.deleteScopeMapping(roleModel);
-                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
-            }
-        }
-
-    }
-
-    @Path("clients/{client}")
-    public ScopeMappedClientResource getClientByIdScopeMappings(@PathParam("client") String client) {
-        ClientModel clientModel = realm.getClientById(client);
-        if (clientModel == null) {
-            throw new NotFoundException("Client not found");
-        }
-        return new ScopeMappedClientResource(realm, auth, this.client, session, clientModel, adminEvent);
-    }
-}
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.ClientMappingsRepresentation;
+import org.keycloak.representations.idm.MappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Base class for managing the scope mappings of a specific client.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ScopeMappedResource {
+    protected RealmModel realm;
+    private RealmAuth auth;
+    protected ClientModel client;
+    protected KeycloakSession session;
+    protected AdminEventBuilder adminEvent;
+
+    public ScopeMappedResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, AdminEventBuilder adminEvent) {
+        this.realm = realm;
+        this.auth = auth;
+        this.client = client;
+        this.session = session;
+        this.adminEvent = adminEvent;
+    }
+
+    /**
+     * Get all scope mappings for this client
+     *
+     * @return
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public MappingsRepresentation getScopeMappings() {
+        auth.requireView();
+
+        MappingsRepresentation all = new MappingsRepresentation();
+        Set<RoleModel> realmMappings = client.getRealmScopeMappings();
+        if (realmMappings.size() > 0) {
+            List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
+            for (RoleModel roleModel : realmMappings) {
+                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
+            }
+            all.setRealmMappings(realmRep);
+        }
+
+        List<ClientModel> clients = realm.getClients();
+        if (clients.size() > 0) {
+            Map<String, ClientMappingsRepresentation> clientMappings = new HashMap<String, ClientMappingsRepresentation>();
+            for (ClientModel client : clients) {
+                Set<RoleModel> roleMappings = client.getClientScopeMappings(this.client);
+                if (roleMappings.size() > 0) {
+                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
+                    mappings.setId(client.getId());
+                    mappings.setClient(client.getClientId());
+                    List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+                    mappings.setMappings(roles);
+                    for (RoleModel role : roleMappings) {
+                        roles.add(ModelToRepresentation.toRepresentation(role));
+                    }
+                    clientMappings.put(client.getClientId(), mappings);
+                    all.setClientMappings(clientMappings);
+                }
+            }
+        }
+        return all;
+    }
+
+    /**
+     * Get list of realm-level roles associated with this client's scope.
+     *
+     * @return
+     */
+    @Path("realm")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getRealmScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> realmMappings = client.getRealmScopeMappings();
+        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : realmMappings) {
+            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return realmMappingsRep;
+    }
+
+    /**
+     * Get list of realm-level roles that are available to attach to this client's scope.
+     *
+     * @return
+     */
+    @Path("realm/available")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getAvailableRealmScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> roles = realm.getRoles();
+        return getAvailable(client, roles);
+    }
+
+    public static List<RoleRepresentation> getAvailable(ClientModel client, Set<RoleModel> roles) {
+        List<RoleRepresentation> available = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roles) {
+            if (client.hasScope(roleModel)) continue;
+            available.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return available;
+    }
+
+    /**
+     * Get all effective realm-level roles that are associated with this client's scope.  What this does is recurse
+     * any composite roles associated with the client's scope and adds the roles to this lists.  The method is really
+     * to show a comprehensive total view of realm-level roles associated with the client.
+     *
+     * @return
+     */
+    @Path("realm/composite")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getCompositeRealmScopeMappings() {
+        auth.requireView();
+
+        Set<RoleModel> roles = realm.getRoles();
+        return getComposite(client, roles);
+    }
+
+    public static List<RoleRepresentation> getComposite(ClientModel client, Set<RoleModel> roles) {
+        List<RoleRepresentation> composite = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roles) {
+            if (client.hasScope(roleModel)) composite.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return composite;
+    }
+
+    /**
+     * Add a set of realm-level roles to the client's scope
+     *
+     * @param roles
+     */
+    @Path("realm")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addRealmScopeMappings(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = realm.getRoleById(role.getId());
+            if (roleModel == null) {
+                throw new NotFoundException("Role not found");
+            }
+            client.addScopeMapping(roleModel);
+            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), role.getId()).representation(roles).success();
+        }
+    }
+
+    /**
+     * Remove a set of realm-level roles from the client's scope
+     *
+     * @param roles
+     */
+    @Path("realm")
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        if (roles == null) {
+            Set<RoleModel> roleModels = client.getRealmScopeMappings();
+            for (RoleModel roleModel : roleModels) {
+                client.deleteScopeMapping(roleModel);
+            }
+            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
+       } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = realm.getRoleById(role.getId());
+                if (roleModel == null) {
+                    throw new NotFoundException("Client not found");
+                }
+                client.deleteScopeMapping(roleModel);
+                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
+            }
+        }
+
+    }
+
+    @Path("clients/{client}")
+    public ScopeMappedClientResource getClientByIdScopeMappings(@PathParam("client") String client) {
+        ClientModel clientModel = realm.getClientById(client);
+        if (clientModel == null) {
+            throw new NotFoundException("Client not found");
+        }
+        return new ScopeMappedClientResource(realm, auth, this.client, session, clientModel, adminEvent);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java
index 34aafb7..228ebbd 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserClientRoleMappingsResource.java
@@ -1,174 +1,174 @@
-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;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserClientRoleMappingsResource {
-    protected static final Logger logger = Logger.getLogger(UserClientRoleMappingsResource.class);
-
-    protected RealmModel realm;
-    protected RealmAuth auth;
-    protected UserModel user;
-    protected ClientModel client;
-    protected AdminEventBuilder adminEvent;
-    private UriInfo uriInfo;
-
-    public UserClientRoleMappingsResource(UriInfo uriInfo, RealmModel realm, RealmAuth auth, UserModel user, ClientModel client, AdminEventBuilder adminEvent) {
-        this.uriInfo = uriInfo;
-        this.realm = realm;
-        this.auth = auth;
-        this.user = user;
-        this.client = client;
-        this.adminEvent = adminEvent;
-    }
-
-    /**
-     * Get client-level role mappings for this user for a specific app
-     *
-     * @return
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getClientRoleMappings() {
-        auth.requireView();
-
-        Set<RoleModel> mappings = user.getClientRoleMappings(client);
-        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : mappings) {
-            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return mapRep;
-    }
-
-    /**
-     * Get effective client-level role mappings.  This recurses any composite roles
-     *
-     * @return
-     */
-    @Path("composite")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getCompositeClientRoleMappings() {
-        auth.requireView();
-
-        Set<RoleModel> roles = client.getRoles();
-        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roles) {
-            if (user.hasRole(roleModel)) mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return mapRep;
-    }
-
-    /**
-     * Get available client-level roles that can be mapped to the user
-     *
-     * @return
-     */
-    @Path("available")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getAvailableClientRoleMappings() {
-        auth.requireView();
-
-        Set<RoleModel> available = client.getRoles();
-        return getAvailableRoles(user, available);
-    }
-
-    public static List<RoleRepresentation> getAvailableRoles(UserModel user, Set<RoleModel> available) {
-        Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (RoleModel roleModel : available) {
-            if (user.hasRole(roleModel)) continue;
-            roles.add(roleModel);
-        }
-
-        List<RoleRepresentation> mappings = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roles) {
-            mappings.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return mappings;
-    }
-
-    /**
-     * Add client-level roles to the user role mapping.
-     *
-      * @param roles
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addClientRoleMapping(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        for (RoleRepresentation role : roles) {
-            RoleModel roleModel = client.getRole(role.getName());
-            if (roleModel == null || !roleModel.getId().equals(role.getId())) {
-                throw new NotFoundException("Role not found");
-            }
-            user.grantRole(roleModel);
-        }
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
-
-    }
-
-    /**
-     * Delete client-level roles from user role mapping.
-     *
-     * @param roles
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteClientRoleMapping(List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        if (roles == null) {
-            Set<RoleModel> roleModels = user.getClientRoleMappings(client);
-            for (RoleModel roleModel : roleModels) {
-                if (!(roleModel.getContainer() instanceof ClientModel)) {
-                    ClientModel client = (ClientModel) roleModel.getContainer();
-                    if (!client.getId().equals(this.client.getId())) continue;
-                }
-                user.deleteRoleMapping(roleModel);
-            }
-
-        } else {
-            for (RoleRepresentation role : roles) {
-                RoleModel roleModel = client.getRole(role.getName());
-                if (roleModel == null || !roleModel.getId().equals(role.getId())) {
-                    throw new NotFoundException("Role not found");
-                }
-                user.deleteRoleMapping(roleModel);
-            }
-        }
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
-    }
-}
+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;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserClientRoleMappingsResource {
+    protected static final Logger logger = Logger.getLogger(UserClientRoleMappingsResource.class);
+
+    protected RealmModel realm;
+    protected RealmAuth auth;
+    protected UserModel user;
+    protected ClientModel client;
+    protected AdminEventBuilder adminEvent;
+    private UriInfo uriInfo;
+
+    public UserClientRoleMappingsResource(UriInfo uriInfo, RealmModel realm, RealmAuth auth, UserModel user, ClientModel client, AdminEventBuilder adminEvent) {
+        this.uriInfo = uriInfo;
+        this.realm = realm;
+        this.auth = auth;
+        this.user = user;
+        this.client = client;
+        this.adminEvent = adminEvent;
+    }
+
+    /**
+     * Get client-level role mappings for this user for a specific app
+     *
+     * @return
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getClientRoleMappings() {
+        auth.requireView();
+
+        Set<RoleModel> mappings = user.getClientRoleMappings(client);
+        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : mappings) {
+            mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return mapRep;
+    }
+
+    /**
+     * Get effective client-level role mappings.  This recurses any composite roles
+     *
+     * @return
+     */
+    @Path("composite")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getCompositeClientRoleMappings() {
+        auth.requireView();
+
+        Set<RoleModel> roles = client.getRoles();
+        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roles) {
+            if (user.hasRole(roleModel)) mapRep.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return mapRep;
+    }
+
+    /**
+     * Get available client-level roles that can be mapped to the user
+     *
+     * @return
+     */
+    @Path("available")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getAvailableClientRoleMappings() {
+        auth.requireView();
+
+        Set<RoleModel> available = client.getRoles();
+        return getAvailableRoles(user, available);
+    }
+
+    public static List<RoleRepresentation> getAvailableRoles(UserModel user, Set<RoleModel> available) {
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (RoleModel roleModel : available) {
+            if (user.hasRole(roleModel)) continue;
+            roles.add(roleModel);
+        }
+
+        List<RoleRepresentation> mappings = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roles) {
+            mappings.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return mappings;
+    }
+
+    /**
+     * Add client-level roles to the user role mapping.
+     *
+      * @param roles
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addClientRoleMapping(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = client.getRole(role.getName());
+            if (roleModel == null || !roleModel.getId().equals(role.getId())) {
+                throw new NotFoundException("Role not found");
+            }
+            user.grantRole(roleModel);
+        }
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
+
+    }
+
+    /**
+     * Delete client-level roles from user role mapping.
+     *
+     * @param roles
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteClientRoleMapping(List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        if (roles == null) {
+            Set<RoleModel> roleModels = user.getClientRoleMappings(client);
+            for (RoleModel roleModel : roleModels) {
+                if (!(roleModel.getContainer() instanceof ClientModel)) {
+                    ClientModel client = (ClientModel) roleModel.getContainer();
+                    if (!client.getId().equals(this.client.getId())) continue;
+                }
+                user.deleteRoleMapping(roleModel);
+            }
+
+        } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = client.getRole(role.getName());
+                if (roleModel == null || !roleModel.getId().equals(role.getId())) {
+                    throw new NotFoundException("Role not found");
+                }
+                user.deleteRoleMapping(roleModel);
+            }
+        }
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
+    }
+}
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 a3bd867..59b9dc4 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
@@ -1,172 +1,172 @@
-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;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
-import org.keycloak.representations.idm.UserFederationProviderRepresentation;
-import org.keycloak.services.managers.UsersSyncManager;
-import org.keycloak.timer.TimerProvider;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Base resource for managing users
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UserFederationProvidersResource {
-    protected static final Logger logger = Logger.getLogger(UserFederationProvidersResource.class);
-
-    protected RealmModel realm;
-
-    protected  RealmAuth auth;
-    
-    protected AdminEventBuilder adminEvent;
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected KeycloakSession session;
-
-    public UserFederationProvidersResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
-        this.auth = auth;
-        this.realm = realm;
-        this.adminEvent = adminEvent;
-        
-        auth.init(RealmAuth.Resource.USER);
-    }
-
-    /**
-     * Get List of available provider factories
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Path("providers")
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<UserFederationProviderFactoryRepresentation> getProviders() {
-        auth.requireView();
-        List<UserFederationProviderFactoryRepresentation> providers = new LinkedList<UserFederationProviderFactoryRepresentation>();
-        for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
-            UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
-            rep.setId(factory.getId());
-            rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
-            providers.add(rep);
-        }
-        return providers;
-    }
-
-    /**
-     * Get factory with given ID
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Path("providers/{id}")
-    @Produces(MediaType.APPLICATION_JSON)
-    public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) {
-        auth.requireView();
-        for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
-            if (!factory.getId().equals(id)) {
-                continue;
-            }
-            UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
-            rep.setId(factory.getId());
-            rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
-
-
-            return rep;
-        }
-        throw new NotFoundException("Could not find provider");
-    }
-
-    /**
-     * Create a provider
-     *
-     * @param rep
-     * @return
-     */
-    @POST
-    @Path("instances")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createProviderInstance(UserFederationProviderRepresentation rep) {
-        auth.requireManage();
-        String displayName = rep.getDisplayName();
-        if (displayName != null && displayName.trim().equals("")) {
-            displayName = null;
-        }
-        UserFederationProviderModel model = realm.addUserFederationProvider(rep.getProviderName(), rep.getConfig(), rep.getPriority(), displayName,
-                rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
-        new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
-        boolean kerberosCredsAdded = KeycloakModelUtils.checkKerberosCredential(realm, model);
-        if (kerberosCredsAdded) {
-            logger.info("Added 'kerberos' to required realm credentials");
-        }
-
-        
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
-
-        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
-    }
-
-    /**
-     * list configured providers
-     *
-     * @return
-     */
-    @GET
-    @Path("instances")
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<UserFederationProviderRepresentation> getUserFederationInstances() {
-        auth.requireManage();
-        List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
-        for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
-            UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
-            reps.add(rep);
-        }
-        return reps;
-    }
-
-    @Path("instances/{id}")
-    public UserFederationProviderResource getUserFederationInstance(@PathParam("id") String id) {
-        this.auth.requireView();
-
-        UserFederationProviderModel model = KeycloakModelUtils.findUserFederationProviderById(id, realm);
-        if (model == null) {
-            throw new NotFoundException("Could not find federation provider with id: " + id);
-        }
-
-        UserFederationProviderResource instanceResource = new UserFederationProviderResource(session, realm, this.auth, model, adminEvent);
-        ResteasyProviderFactory.getInstance().injectProperties(instanceResource);
-        return instanceResource;
-    }
-
-}
+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;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderFactory;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.services.managers.UsersSyncManager;
+import org.keycloak.timer.TimerProvider;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Base resource for managing users
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserFederationProvidersResource {
+    protected static final Logger logger = Logger.getLogger(UserFederationProvidersResource.class);
+
+    protected RealmModel realm;
+
+    protected  RealmAuth auth;
+    
+    protected AdminEventBuilder adminEvent;
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected KeycloakSession session;
+
+    public UserFederationProvidersResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+        this.auth = auth;
+        this.realm = realm;
+        this.adminEvent = adminEvent;
+        
+        auth.init(RealmAuth.Resource.USER);
+    }
+
+    /**
+     * Get List of available provider factories
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Path("providers")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<UserFederationProviderFactoryRepresentation> getProviders() {
+        auth.requireView();
+        List<UserFederationProviderFactoryRepresentation> providers = new LinkedList<UserFederationProviderFactoryRepresentation>();
+        for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
+            UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
+            rep.setId(factory.getId());
+            rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
+            providers.add(rep);
+        }
+        return providers;
+    }
+
+    /**
+     * Get factory with given ID
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Path("providers/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) {
+        auth.requireView();
+        for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
+            if (!factory.getId().equals(id)) {
+                continue;
+            }
+            UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
+            rep.setId(factory.getId());
+            rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
+
+
+            return rep;
+        }
+        throw new NotFoundException("Could not find provider");
+    }
+
+    /**
+     * Create a provider
+     *
+     * @param rep
+     * @return
+     */
+    @POST
+    @Path("instances")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createProviderInstance(UserFederationProviderRepresentation rep) {
+        auth.requireManage();
+        String displayName = rep.getDisplayName();
+        if (displayName != null && displayName.trim().equals("")) {
+            displayName = null;
+        }
+        UserFederationProviderModel model = realm.addUserFederationProvider(rep.getProviderName(), rep.getConfig(), rep.getPriority(), displayName,
+                rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
+        new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
+        boolean kerberosCredsAdded = KeycloakModelUtils.checkKerberosCredential(realm, model);
+        if (kerberosCredsAdded) {
+            logger.info("Added 'kerberos' to required realm credentials");
+        }
+
+        
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
+
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+    }
+
+    /**
+     * list configured providers
+     *
+     * @return
+     */
+    @GET
+    @Path("instances")
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<UserFederationProviderRepresentation> getUserFederationInstances() {
+        auth.requireManage();
+        List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
+        for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
+            UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
+            reps.add(rep);
+        }
+        return reps;
+    }
+
+    @Path("instances/{id}")
+    public UserFederationProviderResource getUserFederationInstance(@PathParam("id") String id) {
+        this.auth.requireView();
+
+        UserFederationProviderModel model = KeycloakModelUtils.findUserFederationProviderById(id, realm);
+        if (model == null) {
+            throw new NotFoundException("Could not find federation provider with id: " + id);
+        }
+
+        UserFederationProviderResource instanceResource = new UserFederationProviderResource(session, realm, this.auth, model, adminEvent);
+        ResteasyProviderFactory.getInstance().injectProperties(instanceResource);
+        return instanceResource;
+    }
+
+}
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 43f50e1..8348037 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
@@ -1,971 +1,971 @@
-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;
-import org.keycloak.ClientConnection;
-import org.keycloak.authentication.RequiredActionProvider;
-import org.keycloak.email.EmailException;
-import org.keycloak.email.EmailProvider;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelReadOnlyException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.protocol.oidc.utils.RedirectUtils;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.representations.idm.ClientMappingsRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.FederatedIdentityRepresentation;
-import org.keycloak.representations.idm.MappingsRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.UserConsentRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.representations.idm.UserSessionRepresentation;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.managers.UserManager;
-import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.Urls;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.WebApplicationException;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.services.resources.AccountService;
-
-/**
- * Base resource for managing users
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class UsersResource {
-    protected static final Logger logger = Logger.getLogger(UsersResource.class);
-
-    protected RealmModel realm;
-
-    private RealmAuth auth;
-
-    private AdminEventBuilder adminEvent;
-
-    @Context
-    protected ClientConnection clientConnection;
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected KeycloakSession session;
-
-    @Context
-    protected HttpHeaders headers;
-
-    @Context
-    protected BruteForceProtector protector;
-
-    public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager, AdminEventBuilder adminEvent) {
-        this.auth = auth;
-        this.realm = realm;
-        this.adminEvent = adminEvent;
-
-        auth.init(RealmAuth.Resource.USER);
-    }
-
-    /**
-     * Update the user
-     *
-     * @param id
-     * @param rep
-     * @return
-     */
-    @Path("{id}")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response updateUser(final @PathParam("id") String id, final UserRepresentation rep) {
-        auth.requireManage();
-
-        try {
-            UserModel user = session.users().getUserById(id, realm);
-            if (user == null) {
-                throw new NotFoundException("User not found");
-            }
-
-            Set<String> attrsToRemove;
-            if (rep.getAttributes() != null) {
-                attrsToRemove = new HashSet<>(user.getAttributes().keySet());
-                attrsToRemove.removeAll(rep.getAttributes().keySet());
-            } else {
-                attrsToRemove = Collections.emptySet();
-            }
-
-            if (rep.isEnabled()) {
-                UsernameLoginFailureModel failureModel = session.sessions().getUserLoginFailure(realm, rep.getUsername());
-                if (failureModel != null) {
-                    failureModel.clearFailures();
-                }
-            }
-
-            updateUserFromRep(user, rep, attrsToRemove);
-            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
-
-            if (session.getTransaction().isActive()) {
-                session.getTransaction().commit();
-            }
-            return Response.noContent().build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("User exists with same username or email");
-        } catch (ModelReadOnlyException re) {
-            return ErrorResponse.exists("User is read only!");
-        }
-    }
-
-    /**
-     * Create a new user.  Must be a unique username!
-     *
-     * @param uriInfo
-     * @param rep
-     * @return
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
-        auth.requireManage();
-
-        // Double-check duplicated username and email here due to federation
-        if (session.users().getUserByUsername(rep.getUsername(), realm) != null) {
-            return ErrorResponse.exists("User exists with same username");
-        }
-        if (rep.getEmail() != null && session.users().getUserByEmail(rep.getEmail(), realm) != null) {
-            return ErrorResponse.exists("User exists with same email");
-        }
-
-        try {
-            UserModel user = session.users().addUser(realm, rep.getUsername());
-            Set<String> emptySet = Collections.emptySet();
-            updateUserFromRep(user, rep, emptySet);
-
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, user.getId()).representation(rep).success();
-
-            if (session.getTransaction().isActive()) {
-                session.getTransaction().commit();
-            }
-
-            return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getId()).build()).build();
-        } catch (ModelDuplicateException e) {
-            if (session.getTransaction().isActive()) {
-                session.getTransaction().setRollbackOnly();
-            }
-            return ErrorResponse.exists("User exists with same username or email");
-        }
-    }
-
-    private void updateUserFromRep(UserModel user, UserRepresentation rep, Set<String> attrsToRemove) {
-        if (realm.isEditUsernameAllowed()) {
-            user.setUsername(rep.getUsername());
-        }
-        user.setEmail(rep.getEmail());
-        user.setFirstName(rep.getFirstName());
-        user.setLastName(rep.getLastName());
-
-        user.setEnabled(rep.isEnabled());
-        user.setTotp(rep.isTotp());
-        user.setEmailVerified(rep.isEmailVerified());
-
-        List<String> reqActions = rep.getRequiredActions();
-
-        if (reqActions != null) {
-            Set<String> allActions = new HashSet<>();
-            for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class)) {
-                allActions.add(factory.getId());
-            }
-            for (String action : allActions) {
-                if (reqActions.contains(action)) {
-                    user.addRequiredAction(action);
-                } else {
-                    user.removeRequiredAction(action);
-                }
-            }
-        }
-
-        if (rep.getAttributesAsListValues() != null) {
-            for (Map.Entry<String, List<String>> attr : rep.getAttributesAsListValues().entrySet()) {
-                user.setAttribute(attr.getKey(), attr.getValue());
-            }
-
-            for (String attr : attrsToRemove) {
-                user.removeAttribute(attr);
-            }
-        }
-    }
-
-    /**
-     * Get represenation of the user
-     *
-     * @param id user id
-     * @return
-     */
-    @Path("{id}")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public UserRepresentation getUser(final @PathParam("id") String id) {
-        auth.requireView();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        UserRepresentation rep = ModelToRepresentation.toRepresentation(user);
-
-        if (realm.isIdentityFederationEnabled()) {
-            List<FederatedIdentityRepresentation> reps = getFederatedIdentities(user);
-            rep.setFederatedIdentities(reps);
-        }
-
-        if ((protector != null) && protector.isTemporarilyDisabled(session, realm, rep.getUsername())) {
-            rep.setEnabled(false);
-        }
-
-        return rep;
-    }
-
-    @Path("{id}/impersonation")
-    @POST
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Map<String, Object> impersonate(final @PathParam("id") String id) {
-        auth.init(RealmAuth.Resource.IMPERSONATION);
-        auth.requireManage();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        RealmModel authenticatedRealm = auth.getAuth().getRealm();
-        // if same realm logout before impersonation
-        boolean sameRealm = false;
-        if (authenticatedRealm.getId().equals(realm.getId())) {
-            sameRealm = true;
-            UserSessionModel userSession = session.sessions().getUserSession(authenticatedRealm, auth.getAuth().getToken().getSessionState());
-            AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
-            AuthenticationManager.expireRememberMeCookie(realm, uriInfo, clientConnection);
-            AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, uriInfo, clientConnection, headers, true);
-        }
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-
-        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "impersonate", false, null, null);
-        AuthenticationManager.createLoginCookie(realm, userSession.getUser(), userSession, uriInfo, clientConnection);
-        URI redirect = AccountService.accountServiceApplicationPage(uriInfo).build(realm.getName());
-        Map<String, Object> result = new HashMap<>();
-        result.put("sameRealm", sameRealm);
-        result.put("redirect", redirect.toString());
-        event.event(EventType.IMPERSONATE)
-             .session(userSession)
-             .user(user)
-             .detail(Details.IMPERSONATOR_REALM,authenticatedRealm.getName())
-             .detail(Details.IMPERSONATOR, auth.getAuth().getUser().getUsername()).success();
-
-        return result;
-    }
-
-
-    /**
-     * List set of sessions associated with this user.
-     *
-     * @param id
-     * @return
-     */
-    @Path("{id}/sessions")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id) {
-        auth.requireView();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
-        List<UserSessionRepresentation> reps = new ArrayList<UserSessionRepresentation>();
-        for (UserSessionModel session : sessions) {
-            UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
-            reps.add(rep);
-        }
-        return reps;
-    }
-
-    /**
-     * List set of social logins associated with this user.
-     *
-     * @param id
-     * @return
-     */
-    @Path("{id}/federated-identity")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<FederatedIdentityRepresentation> getFederatedIdentity(final @PathParam("id") String id) {
-        auth.requireView();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        return getFederatedIdentities(user);
-    }
-
-    private List<FederatedIdentityRepresentation> getFederatedIdentities(UserModel user) {
-        Set<FederatedIdentityModel> identities = session.users().getFederatedIdentities(user, realm);
-        List<FederatedIdentityRepresentation> result = new ArrayList<FederatedIdentityRepresentation>();
-
-        for (FederatedIdentityModel identity : identities) {
-            for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) {
-                if (identityProviderModel.getAlias().equals(identity.getIdentityProvider())) {
-                    FederatedIdentityRepresentation rep = ModelToRepresentation.toRepresentation(identity);
-                    result.add(rep);
-                }
-            }
-        }
-        return result;
-    }
-
-    @Path("{id}/federated-identity/{provider}")
-    @POST
-    @NoCache
-    public Response addFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider, FederatedIdentityRepresentation rep) {
-        auth.requireManage();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        if (session.users().getFederatedIdentity(user, provider, realm) != null) {
-            return ErrorResponse.exists("User is already linked with provider");
-        }
-
-        FederatedIdentityModel socialLink = new FederatedIdentityModel(provider, rep.getUserId(), rep.getUserName());
-        session.users().addFederatedIdentity(realm, user, socialLink);
-        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
-        return Response.noContent().build();
-    }
-
-    @Path("{id}/federated-identity/{provider}")
-    @DELETE
-    @NoCache
-    public void removeFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider) {
-        auth.requireManage();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        if (!session.users().removeFederatedIdentity(realm, user, provider)) {
-            throw new NotFoundException("Link not found");
-        }
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * List set of consents granted by this user.
-     *
-     * @param id
-     * @return
-     */
-    @Path("{id}/consents")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<UserConsentRepresentation> getConsents(final @PathParam("id") String id) {
-        auth.requireView();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        List<UserConsentModel> consents = user.getConsents();
-        List<UserConsentRepresentation> result = new ArrayList<UserConsentRepresentation>();
-
-        for (UserConsentModel consent : consents) {
-            UserConsentRepresentation rep = ModelToRepresentation.toRepresentation(consent);
-            result.add(rep);
-        }
-        return result;
-    }
-
-    /**
-     * Revoke consent for particular client
-     *
-     * @param id
-     * @param clientId
-     */
-    @Path("{id}/consents/{client}")
-    @DELETE
-    @NoCache
-    public void revokeConsent(final @PathParam("id") String id, final @PathParam("client") String clientId) {
-        auth.requireManage();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        ClientModel client = realm.getClientByClientId(clientId);
-        boolean revoked = user.revokeConsentForClient(client.getId());
-        if (revoked) {
-            // Logout clientSessions for this user and client
-            AuthenticationManager.backchannelUserFromClient(session, realm, user, client, uriInfo, headers);
-        } else {
-            throw new NotFoundException("Consent not found for user " + id + " and client " + clientId);
-        }
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * Remove all user sessions associated with this user.  And, for all client that have an admin URL, tell
-     * them to invalidate the sessions for this particular user.
-     *
-     * @param id user id
-     */
-    @Path("{id}/logout")
-    @POST
-    public void logout(final @PathParam("id") String id) {
-        auth.requireManage();
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
-        for (UserSessionModel userSession : userSessions) {
-            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
-        }
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * delete this user
-     *
-     * @param id user id
-     */
-    @Path("{id}")
-    @DELETE
-    @NoCache
-    public Response deleteUser(final @PathParam("id") String id) {
-        auth.requireManage();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        boolean removed = new UserManager(session).removeUser(realm, user);
-        if (removed) {
-            adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
-            return Response.noContent().build();
-        } else {
-            return ErrorResponse.error("User couldn't be deleted", Response.Status.BAD_REQUEST);
-        }
-    }
-
-    /**
-     * Query list of users.  May pass in query criteria
-     *
-     * @param search string contained in username, first or last name, or email
-     * @param last
-     * @param first
-     * @param email
-     * @param username
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public List<UserRepresentation> getUsers(@QueryParam("search") String search,
-                                             @QueryParam("lastName") String last,
-                                             @QueryParam("firstName") String first,
-                                             @QueryParam("email") String email,
-                                             @QueryParam("username") String username,
-                                             @QueryParam("first") Integer firstResult,
-                                             @QueryParam("max") Integer maxResults) {
-        auth.requireView();
-
-        firstResult = firstResult != null ? firstResult : -1;
-        maxResults = maxResults != null ? maxResults : -1;
-
-        List<UserRepresentation> results = new ArrayList<UserRepresentation>();
-        List<UserModel> userModels;
-        if (search != null) {
-            userModels = session.users().searchForUser(search.trim(), realm, firstResult, maxResults);
-        } else if (last != null || first != null || email != null || username != null) {
-            Map<String, String> attributes = new HashMap<String, String>();
-            if (last != null) {
-                attributes.put(UserModel.LAST_NAME, last);
-            }
-            if (first != null) {
-                attributes.put(UserModel.FIRST_NAME, first);
-            }
-            if (email != null) {
-                attributes.put(UserModel.EMAIL, email);
-            }
-            if (username != null) {
-                attributes.put(UserModel.USERNAME, username);
-            }
-            userModels = session.users().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
-        } else {
-            userModels = session.users().getUsers(realm, firstResult, maxResults);
-        }
-
-        for (UserModel user : userModels) {
-            results.add(ModelToRepresentation.toRepresentation(user));
-        }
-        return results;
-    }
-
-    /**
-     * Get role mappings for this user
-     *
-     * @param id user id
-     * @return
-     */
-    @Path("{id}/role-mappings")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public MappingsRepresentation getRoleMappings(@PathParam("id") String id) {
-        auth.requireView();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        MappingsRepresentation all = new MappingsRepresentation();
-        Set<RoleModel> realmMappings = user.getRoleMappings();
-        RealmManager manager = new RealmManager(session);
-        if (realmMappings.size() > 0) {
-            List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
-            for (RoleModel roleModel : realmMappings) {
-                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
-            }
-            all.setRealmMappings(realmRep);
-        }
-
-        List<ClientModel> clients = realm.getClients();
-        if (clients.size() > 0) {
-            Map<String, ClientMappingsRepresentation> appMappings = new HashMap<String, ClientMappingsRepresentation>();
-            for (ClientModel client : clients) {
-                Set<RoleModel> roleMappings = user.getClientRoleMappings(client);
-                if (roleMappings.size() > 0) {
-                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
-                    mappings.setId(client.getId());
-                    mappings.setClient(client.getClientId());
-                    List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
-                    mappings.setMappings(roles);
-                    for (RoleModel role : roleMappings) {
-                        roles.add(ModelToRepresentation.toRepresentation(role));
-                    }
-                    appMappings.put(client.getClientId(), mappings);
-                    all.setClientMappings(appMappings);
-                }
-            }
-        }
-        return all;
-    }
-
-    /**
-     * Get realm-level role mappings for this user
-     *
-     * @param id user id
-     * @return
-     */
-    @Path("{id}/role-mappings/realm")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getRealmRoleMappings(@PathParam("id") String id) {
-        auth.requireView();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        Set<RoleModel> realmMappings = user.getRealmRoleMappings();
-        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : realmMappings) {
-            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
-        }
-        return realmMappingsRep;
-    }
-
-    /**
-     * Effective realm-level role mappings for this user.  Will recurse all composite roles to get this list.
-     *
-     * @param id user id
-     * @return
-     */
-    @Path("{id}/role-mappings/realm/composite")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getCompositeRealmRoleMappings(@PathParam("id") String id) {
-        auth.requireView();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        Set<RoleModel> roles = realm.getRoles();
-        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
-        for (RoleModel roleModel : roles) {
-            if (user.hasRole(roleModel)) {
-               realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
-            }
-        }
-        return realmMappingsRep;
-    }
-
-    /**
-     * Realm-level roles that can be mapped to this user
-     *
-     * @param id
-     * @return
-     */
-    @Path("{id}/role-mappings/realm/available")
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @NoCache
-    public List<RoleRepresentation> getAvailableRealmRoleMappings(@PathParam("id") String id) {
-        auth.requireView();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        Set<RoleModel> available = realm.getRoles();
-        return UserClientRoleMappingsResource.getAvailableRoles(user, available);
-    }
-
-    /**
-     * Add realm-level role mappings
-     *
-     * @param id
-     * @param roles
-     */
-    @Path("{id}/role-mappings/realm")
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void addRealmRoleMappings(@PathParam("id") String id, List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        logger.debugv("** addRealmRoleMappings: {0}", roles);
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        for (RoleRepresentation role : roles) {
-            RoleModel roleModel = realm.getRole(role.getName());
-            if (roleModel == null || !roleModel.getId().equals(role.getId())) {
-                throw new NotFoundException("Role not found");
-            }
-            user.grantRole(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(roles).success();
-        }
-    }
-
-    /**
-     * Delete realm-level role mappings
-     *
-     * @param id user id
-     * @param roles
-     */
-    @Path("{id}/role-mappings/realm")
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void deleteRealmRoleMappings(@PathParam("id") String id, List<RoleRepresentation> roles) {
-        auth.requireManage();
-
-        logger.debug("deleteRealmRoleMappings");
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        if (roles == null) {
-            Set<RoleModel> roleModels = user.getRealmRoleMappings();
-            for (RoleModel roleModel : roleModels) {
-                user.deleteRoleMapping(roleModel);
-            }
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
-        } else {
-            for (RoleRepresentation role : roles) {
-                RoleModel roleModel = realm.getRole(role.getName());
-                if (roleModel == null || !roleModel.getId().equals(role.getId())) {
-                    throw new NotFoundException("Role not found");
-                }
-                user.deleteRoleMapping(roleModel);
-
-                adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo, role.getId()).representation(roles).success();
-            }
-        }
-
-    }
-
-    @Path("{id}/role-mappings/clients/{client}")
-    public UserClientRoleMappingsResource getUserClientRoleMappingsResource(@PathParam("id") String id, @PathParam("client") String client) {
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        ClientModel clientModel = realm.getClientById(client);
-        if (client == null) {
-            throw new NotFoundException("Client not found");
-        }
-
-        return new UserClientRoleMappingsResource(uriInfo, realm, auth, user, clientModel, adminEvent);
-
-    }
-    /**
-     *  Set up a temporary password for this user.  User will have to reset this temporary password when they log
-     *  in next.
-     *
-     * @param id
-     * @param pass temporary password
-     */
-    @Path("{id}/reset-password")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void resetPassword(@PathParam("id") String id, CredentialRepresentation pass) {
-        auth.requireManage();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-        if (pass == null || pass.getValue() == null || !CredentialRepresentation.PASSWORD.equals(pass.getType())) {
-            throw new BadRequestException("No password provided");
-        }
-
-        UserCredentialModel cred = RepresentationToModel.convertCredential(pass);
-        try {
-            session.users().updateCredential(realm, user, cred);
-        } catch (IllegalStateException ise) {
-            throw new BadRequestException("Resetting to N old passwords is not allowed.");
-        } catch (ModelReadOnlyException mre) {
-            throw new BadRequestException("Can't reset password as account is read only");
-        }
-        if (pass.isTemporary()) user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-    }
-
-    /**
-     *
-     *
-     * @param id
-     */
-    @Path("{id}/remove-totp")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void removeTotp(@PathParam("id") String id) {
-        auth.requireManage();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            throw new NotFoundException("User not found");
-        }
-
-        user.setTotp(false);
-        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-    }
-
-    /**
-     * Send an email to the user with a link they can click to reset their password.
-     * The redirectUri and clientId parameters are optional. The default for the
-     * redirect is the account client.
-     *
-     * @param id
-     * @param redirectUri redirect uri
-     * @param clientId client id
-     * @return
-     */
-    @Path("{id}/reset-password-email")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response resetPasswordEmail(@PathParam("id") String id, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
-        auth.requireManage();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
-        }
-
-        if (user.getEmail() == null) {
-            return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
-        }
-
-        ClientSessionModel clientSession = createClientSession(user, redirectUri, clientId);
-        ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
-        accessCode.setAction(ClientSessionModel.Action.RECOVER_PASSWORD.name());
-
-        try {
-            UriBuilder builder = Urls.loginPasswordResetBuilder(uriInfo.getBaseUri());
-            builder.queryParam("key", accessCode.getCode());
-
-            String link = builder.build(realm.getName()).toString();
-            long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
-
-            this.session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendPasswordReset(link, expiration);
-
-            //audit.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
-
-            adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-
-            return Response.ok().build();
-        } catch (EmailException e) {
-            logger.error("Failed to send password reset email", e);
-            return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
-        }
-    }
-
-    /**
-     * Send an email to the user with a link they can click to verify their email address.
-     * The redirectUri and clientId parameters are optional. The default for the
-     * redirect is the account client.
-     *
-     * @param id
-     * @param redirectUri redirect uri
-     * @param clientId client id
-     * @return
-     */
-    @Path("{id}/send-verify-email")
-    @PUT
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response sendVerifyEmail(@PathParam("id") String id, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
-        auth.requireManage();
-
-        UserModel user = session.users().getUserById(id, realm);
-        if (user == null) {
-            return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
-        }
-
-        if (user.getEmail() == null) {
-            return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
-        }
-
-        ClientSessionModel clientSession = createClientSession(user, redirectUri, clientId);
-        ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
-
-        accessCode.setAction(ClientSessionModel.Action.VERIFY_EMAIL.name());
-
-        try {
-            UriBuilder builder = Urls.loginActionEmailVerificationBuilder(uriInfo.getBaseUri());
-            builder.queryParam("key", accessCode.getCode());
-
-            String link = builder.build(realm.getName()).toString();
-            long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
-
-            this.session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendVerifyEmail(link, expiration);
-
-            //audit.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
-
-            adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
-
-            return Response.ok().build();
-        } catch (EmailException e) {
-            logger.error("Failed to send verification email", e);
-            return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
-        }
-    }
-
-    private ClientSessionModel createClientSession(UserModel user, String redirectUri, String clientId) {
-
-        if (!user.isEnabled()) {
-            throw new WebApplicationException(
-                ErrorResponse.error("User is disabled", Response.Status.BAD_REQUEST));
-        }
-
-        if (redirectUri != null && clientId == null) {
-            throw new WebApplicationException(
-                ErrorResponse.error("Client id missing", Response.Status.BAD_REQUEST));
-        }
-
-        if (clientId == null) {
-            clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
-        }
-
-        ClientModel client = realm.getClientByClientId(clientId);
-        if (client == null || !client.isEnabled()) {
-            throw new WebApplicationException(
-                ErrorResponse.error(clientId + " not enabled", Response.Status.BAD_REQUEST));
-        }
-
-        String redirect;
-        if (redirectUri != null) {
-            redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
-            if (redirect == null) {
-                throw new WebApplicationException(
-                    ErrorResponse.error("Invalid redirect uri.", Response.Status.BAD_REQUEST));
-            }
-        } else {
-            redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
-        }
-
-
-        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "form", false, null, null);
-        //audit.session(userSession);
-        ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
-        clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
-        clientSession.setRedirectUri(redirect);
-        clientSession.setUserSession(userSession);
-
-        return clientSession;
-    }
-
-}
+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;
+import org.keycloak.ClientConnection;
+import org.keycloak.authentication.RequiredActionProvider;
+import org.keycloak.email.EmailException;
+import org.keycloak.email.EmailProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelReadOnlyException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.protocol.oidc.utils.RedirectUtils;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.idm.ClientMappingsRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.FederatedIdentityRepresentation;
+import org.keycloak.representations.idm.MappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserConsentRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.UserManager;
+import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.Urls;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.WebApplicationException;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.resources.AccountService;
+
+/**
+ * Base resource for managing users
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UsersResource {
+    protected static final Logger logger = Logger.getLogger(UsersResource.class);
+
+    protected RealmModel realm;
+
+    private RealmAuth auth;
+
+    private AdminEventBuilder adminEvent;
+
+    @Context
+    protected ClientConnection clientConnection;
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected KeycloakSession session;
+
+    @Context
+    protected HttpHeaders headers;
+
+    @Context
+    protected BruteForceProtector protector;
+
+    public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager, AdminEventBuilder adminEvent) {
+        this.auth = auth;
+        this.realm = realm;
+        this.adminEvent = adminEvent;
+
+        auth.init(RealmAuth.Resource.USER);
+    }
+
+    /**
+     * Update the user
+     *
+     * @param id
+     * @param rep
+     * @return
+     */
+    @Path("{id}")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response updateUser(final @PathParam("id") String id, final UserRepresentation rep) {
+        auth.requireManage();
+
+        try {
+            UserModel user = session.users().getUserById(id, realm);
+            if (user == null) {
+                throw new NotFoundException("User not found");
+            }
+
+            Set<String> attrsToRemove;
+            if (rep.getAttributes() != null) {
+                attrsToRemove = new HashSet<>(user.getAttributes().keySet());
+                attrsToRemove.removeAll(rep.getAttributes().keySet());
+            } else {
+                attrsToRemove = Collections.emptySet();
+            }
+
+            if (rep.isEnabled()) {
+                UsernameLoginFailureModel failureModel = session.sessions().getUserLoginFailure(realm, rep.getUsername());
+                if (failureModel != null) {
+                    failureModel.clearFailures();
+                }
+            }
+
+            updateUserFromRep(user, rep, attrsToRemove);
+            adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
+
+            if (session.getTransaction().isActive()) {
+                session.getTransaction().commit();
+            }
+            return Response.noContent().build();
+        } catch (ModelDuplicateException e) {
+            return ErrorResponse.exists("User exists with same username or email");
+        } catch (ModelReadOnlyException re) {
+            return ErrorResponse.exists("User is read only!");
+        }
+    }
+
+    /**
+     * Create a new user.  Must be a unique username!
+     *
+     * @param uriInfo
+     * @param rep
+     * @return
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
+        auth.requireManage();
+
+        // Double-check duplicated username and email here due to federation
+        if (session.users().getUserByUsername(rep.getUsername(), realm) != null) {
+            return ErrorResponse.exists("User exists with same username");
+        }
+        if (rep.getEmail() != null && session.users().getUserByEmail(rep.getEmail(), realm) != null) {
+            return ErrorResponse.exists("User exists with same email");
+        }
+
+        try {
+            UserModel user = session.users().addUser(realm, rep.getUsername());
+            Set<String> emptySet = Collections.emptySet();
+            updateUserFromRep(user, rep, emptySet);
+
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, user.getId()).representation(rep).success();
+
+            if (session.getTransaction().isActive()) {
+                session.getTransaction().commit();
+            }
+
+            return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getId()).build()).build();
+        } catch (ModelDuplicateException e) {
+            if (session.getTransaction().isActive()) {
+                session.getTransaction().setRollbackOnly();
+            }
+            return ErrorResponse.exists("User exists with same username or email");
+        }
+    }
+
+    private void updateUserFromRep(UserModel user, UserRepresentation rep, Set<String> attrsToRemove) {
+        if (realm.isEditUsernameAllowed()) {
+            user.setUsername(rep.getUsername());
+        }
+        user.setEmail(rep.getEmail());
+        user.setFirstName(rep.getFirstName());
+        user.setLastName(rep.getLastName());
+
+        user.setEnabled(rep.isEnabled());
+        user.setTotp(rep.isTotp());
+        user.setEmailVerified(rep.isEmailVerified());
+
+        List<String> reqActions = rep.getRequiredActions();
+
+        if (reqActions != null) {
+            Set<String> allActions = new HashSet<>();
+            for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class)) {
+                allActions.add(factory.getId());
+            }
+            for (String action : allActions) {
+                if (reqActions.contains(action)) {
+                    user.addRequiredAction(action);
+                } else {
+                    user.removeRequiredAction(action);
+                }
+            }
+        }
+
+        if (rep.getAttributesAsListValues() != null) {
+            for (Map.Entry<String, List<String>> attr : rep.getAttributesAsListValues().entrySet()) {
+                user.setAttribute(attr.getKey(), attr.getValue());
+            }
+
+            for (String attr : attrsToRemove) {
+                user.removeAttribute(attr);
+            }
+        }
+    }
+
+    /**
+     * Get represenation of the user
+     *
+     * @param id user id
+     * @return
+     */
+    @Path("{id}")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public UserRepresentation getUser(final @PathParam("id") String id) {
+        auth.requireView();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        UserRepresentation rep = ModelToRepresentation.toRepresentation(user);
+
+        if (realm.isIdentityFederationEnabled()) {
+            List<FederatedIdentityRepresentation> reps = getFederatedIdentities(user);
+            rep.setFederatedIdentities(reps);
+        }
+
+        if ((protector != null) && protector.isTemporarilyDisabled(session, realm, rep.getUsername())) {
+            rep.setEnabled(false);
+        }
+
+        return rep;
+    }
+
+    @Path("{id}/impersonation")
+    @POST
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Map<String, Object> impersonate(final @PathParam("id") String id) {
+        auth.init(RealmAuth.Resource.IMPERSONATION);
+        auth.requireManage();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        RealmModel authenticatedRealm = auth.getAuth().getRealm();
+        // if same realm logout before impersonation
+        boolean sameRealm = false;
+        if (authenticatedRealm.getId().equals(realm.getId())) {
+            sameRealm = true;
+            UserSessionModel userSession = session.sessions().getUserSession(authenticatedRealm, auth.getAuth().getToken().getSessionState());
+            AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
+            AuthenticationManager.expireRememberMeCookie(realm, uriInfo, clientConnection);
+            AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, uriInfo, clientConnection, headers, true);
+        }
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+
+        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "impersonate", false, null, null);
+        AuthenticationManager.createLoginCookie(realm, userSession.getUser(), userSession, uriInfo, clientConnection);
+        URI redirect = AccountService.accountServiceApplicationPage(uriInfo).build(realm.getName());
+        Map<String, Object> result = new HashMap<>();
+        result.put("sameRealm", sameRealm);
+        result.put("redirect", redirect.toString());
+        event.event(EventType.IMPERSONATE)
+             .session(userSession)
+             .user(user)
+             .detail(Details.IMPERSONATOR_REALM,authenticatedRealm.getName())
+             .detail(Details.IMPERSONATOR, auth.getAuth().getUser().getUsername()).success();
+
+        return result;
+    }
+
+
+    /**
+     * List set of sessions associated with this user.
+     *
+     * @param id
+     * @return
+     */
+    @Path("{id}/sessions")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id) {
+        auth.requireView();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
+        List<UserSessionRepresentation> reps = new ArrayList<UserSessionRepresentation>();
+        for (UserSessionModel session : sessions) {
+            UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
+            reps.add(rep);
+        }
+        return reps;
+    }
+
+    /**
+     * List set of social logins associated with this user.
+     *
+     * @param id
+     * @return
+     */
+    @Path("{id}/federated-identity")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<FederatedIdentityRepresentation> getFederatedIdentity(final @PathParam("id") String id) {
+        auth.requireView();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        return getFederatedIdentities(user);
+    }
+
+    private List<FederatedIdentityRepresentation> getFederatedIdentities(UserModel user) {
+        Set<FederatedIdentityModel> identities = session.users().getFederatedIdentities(user, realm);
+        List<FederatedIdentityRepresentation> result = new ArrayList<FederatedIdentityRepresentation>();
+
+        for (FederatedIdentityModel identity : identities) {
+            for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) {
+                if (identityProviderModel.getAlias().equals(identity.getIdentityProvider())) {
+                    FederatedIdentityRepresentation rep = ModelToRepresentation.toRepresentation(identity);
+                    result.add(rep);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Path("{id}/federated-identity/{provider}")
+    @POST
+    @NoCache
+    public Response addFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider, FederatedIdentityRepresentation rep) {
+        auth.requireManage();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        if (session.users().getFederatedIdentity(user, provider, realm) != null) {
+            return ErrorResponse.exists("User is already linked with provider");
+        }
+
+        FederatedIdentityModel socialLink = new FederatedIdentityModel(provider, rep.getUserId(), rep.getUserName());
+        session.users().addFederatedIdentity(realm, user, socialLink);
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
+        return Response.noContent().build();
+    }
+
+    @Path("{id}/federated-identity/{provider}")
+    @DELETE
+    @NoCache
+    public void removeFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider) {
+        auth.requireManage();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        if (!session.users().removeFederatedIdentity(realm, user, provider)) {
+            throw new NotFoundException("Link not found");
+        }
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * List set of consents granted by this user.
+     *
+     * @param id
+     * @return
+     */
+    @Path("{id}/consents")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<UserConsentRepresentation> getConsents(final @PathParam("id") String id) {
+        auth.requireView();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        List<UserConsentModel> consents = user.getConsents();
+        List<UserConsentRepresentation> result = new ArrayList<UserConsentRepresentation>();
+
+        for (UserConsentModel consent : consents) {
+            UserConsentRepresentation rep = ModelToRepresentation.toRepresentation(consent);
+            result.add(rep);
+        }
+        return result;
+    }
+
+    /**
+     * Revoke consent for particular client
+     *
+     * @param id
+     * @param clientId
+     */
+    @Path("{id}/consents/{client}")
+    @DELETE
+    @NoCache
+    public void revokeConsent(final @PathParam("id") String id, final @PathParam("client") String clientId) {
+        auth.requireManage();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        ClientModel client = realm.getClientByClientId(clientId);
+        boolean revoked = user.revokeConsentForClient(client.getId());
+        if (revoked) {
+            // Logout clientSessions for this user and client
+            AuthenticationManager.backchannelUserFromClient(session, realm, user, client, uriInfo, headers);
+        } else {
+            throw new NotFoundException("Consent not found for user " + id + " and client " + clientId);
+        }
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * Remove all user sessions associated with this user.  And, for all client that have an admin URL, tell
+     * them to invalidate the sessions for this particular user.
+     *
+     * @param id user id
+     */
+    @Path("{id}/logout")
+    @POST
+    public void logout(final @PathParam("id") String id) {
+        auth.requireManage();
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
+        for (UserSessionModel userSession : userSessions) {
+            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
+        }
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * delete this user
+     *
+     * @param id user id
+     */
+    @Path("{id}")
+    @DELETE
+    @NoCache
+    public Response deleteUser(final @PathParam("id") String id) {
+        auth.requireManage();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        boolean removed = new UserManager(session).removeUser(realm, user);
+        if (removed) {
+            adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+            return Response.noContent().build();
+        } else {
+            return ErrorResponse.error("User couldn't be deleted", Response.Status.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Query list of users.  May pass in query criteria
+     *
+     * @param search string contained in username, first or last name, or email
+     * @param last
+     * @param first
+     * @param email
+     * @param username
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<UserRepresentation> getUsers(@QueryParam("search") String search,
+                                             @QueryParam("lastName") String last,
+                                             @QueryParam("firstName") String first,
+                                             @QueryParam("email") String email,
+                                             @QueryParam("username") String username,
+                                             @QueryParam("first") Integer firstResult,
+                                             @QueryParam("max") Integer maxResults) {
+        auth.requireView();
+
+        firstResult = firstResult != null ? firstResult : -1;
+        maxResults = maxResults != null ? maxResults : -1;
+
+        List<UserRepresentation> results = new ArrayList<UserRepresentation>();
+        List<UserModel> userModels;
+        if (search != null) {
+            userModels = session.users().searchForUser(search.trim(), realm, firstResult, maxResults);
+        } else if (last != null || first != null || email != null || username != null) {
+            Map<String, String> attributes = new HashMap<String, String>();
+            if (last != null) {
+                attributes.put(UserModel.LAST_NAME, last);
+            }
+            if (first != null) {
+                attributes.put(UserModel.FIRST_NAME, first);
+            }
+            if (email != null) {
+                attributes.put(UserModel.EMAIL, email);
+            }
+            if (username != null) {
+                attributes.put(UserModel.USERNAME, username);
+            }
+            userModels = session.users().searchForUserByAttributes(attributes, realm, firstResult, maxResults);
+        } else {
+            userModels = session.users().getUsers(realm, firstResult, maxResults);
+        }
+
+        for (UserModel user : userModels) {
+            results.add(ModelToRepresentation.toRepresentation(user));
+        }
+        return results;
+    }
+
+    /**
+     * Get role mappings for this user
+     *
+     * @param id user id
+     * @return
+     */
+    @Path("{id}/role-mappings")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public MappingsRepresentation getRoleMappings(@PathParam("id") String id) {
+        auth.requireView();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        MappingsRepresentation all = new MappingsRepresentation();
+        Set<RoleModel> realmMappings = user.getRoleMappings();
+        RealmManager manager = new RealmManager(session);
+        if (realmMappings.size() > 0) {
+            List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
+            for (RoleModel roleModel : realmMappings) {
+                realmRep.add(ModelToRepresentation.toRepresentation(roleModel));
+            }
+            all.setRealmMappings(realmRep);
+        }
+
+        List<ClientModel> clients = realm.getClients();
+        if (clients.size() > 0) {
+            Map<String, ClientMappingsRepresentation> appMappings = new HashMap<String, ClientMappingsRepresentation>();
+            for (ClientModel client : clients) {
+                Set<RoleModel> roleMappings = user.getClientRoleMappings(client);
+                if (roleMappings.size() > 0) {
+                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
+                    mappings.setId(client.getId());
+                    mappings.setClient(client.getClientId());
+                    List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+                    mappings.setMappings(roles);
+                    for (RoleModel role : roleMappings) {
+                        roles.add(ModelToRepresentation.toRepresentation(role));
+                    }
+                    appMappings.put(client.getClientId(), mappings);
+                    all.setClientMappings(appMappings);
+                }
+            }
+        }
+        return all;
+    }
+
+    /**
+     * Get realm-level role mappings for this user
+     *
+     * @param id user id
+     * @return
+     */
+    @Path("{id}/role-mappings/realm")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getRealmRoleMappings(@PathParam("id") String id) {
+        auth.requireView();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        Set<RoleModel> realmMappings = user.getRealmRoleMappings();
+        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : realmMappings) {
+            realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
+        }
+        return realmMappingsRep;
+    }
+
+    /**
+     * Effective realm-level role mappings for this user.  Will recurse all composite roles to get this list.
+     *
+     * @param id user id
+     * @return
+     */
+    @Path("{id}/role-mappings/realm/composite")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getCompositeRealmRoleMappings(@PathParam("id") String id) {
+        auth.requireView();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        Set<RoleModel> roles = realm.getRoles();
+        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
+        for (RoleModel roleModel : roles) {
+            if (user.hasRole(roleModel)) {
+               realmMappingsRep.add(ModelToRepresentation.toRepresentation(roleModel));
+            }
+        }
+        return realmMappingsRep;
+    }
+
+    /**
+     * Realm-level roles that can be mapped to this user
+     *
+     * @param id
+     * @return
+     */
+    @Path("{id}/role-mappings/realm/available")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public List<RoleRepresentation> getAvailableRealmRoleMappings(@PathParam("id") String id) {
+        auth.requireView();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        Set<RoleModel> available = realm.getRoles();
+        return UserClientRoleMappingsResource.getAvailableRoles(user, available);
+    }
+
+    /**
+     * Add realm-level role mappings
+     *
+     * @param id
+     * @param roles
+     */
+    @Path("{id}/role-mappings/realm")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void addRealmRoleMappings(@PathParam("id") String id, List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        logger.debugv("** addRealmRoleMappings: {0}", roles);
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        for (RoleRepresentation role : roles) {
+            RoleModel roleModel = realm.getRole(role.getName());
+            if (roleModel == null || !roleModel.getId().equals(role.getId())) {
+                throw new NotFoundException("Role not found");
+            }
+            user.grantRole(roleModel);
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(roles).success();
+        }
+    }
+
+    /**
+     * Delete realm-level role mappings
+     *
+     * @param id user id
+     * @param roles
+     */
+    @Path("{id}/role-mappings/realm")
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void deleteRealmRoleMappings(@PathParam("id") String id, List<RoleRepresentation> roles) {
+        auth.requireManage();
+
+        logger.debug("deleteRealmRoleMappings");
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        if (roles == null) {
+            Set<RoleModel> roleModels = user.getRealmRoleMappings();
+            for (RoleModel roleModel : roleModels) {
+                user.deleteRoleMapping(roleModel);
+            }
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
+        } else {
+            for (RoleRepresentation role : roles) {
+                RoleModel roleModel = realm.getRole(role.getName());
+                if (roleModel == null || !roleModel.getId().equals(role.getId())) {
+                    throw new NotFoundException("Role not found");
+                }
+                user.deleteRoleMapping(roleModel);
+
+                adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo, role.getId()).representation(roles).success();
+            }
+        }
+
+    }
+
+    @Path("{id}/role-mappings/clients/{client}")
+    public UserClientRoleMappingsResource getUserClientRoleMappingsResource(@PathParam("id") String id, @PathParam("client") String client) {
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        ClientModel clientModel = realm.getClientById(client);
+        if (client == null) {
+            throw new NotFoundException("Client not found");
+        }
+
+        return new UserClientRoleMappingsResource(uriInfo, realm, auth, user, clientModel, adminEvent);
+
+    }
+    /**
+     *  Set up a temporary password for this user.  User will have to reset this temporary password when they log
+     *  in next.
+     *
+     * @param id
+     * @param pass temporary password
+     */
+    @Path("{id}/reset-password")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void resetPassword(@PathParam("id") String id, CredentialRepresentation pass) {
+        auth.requireManage();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+        if (pass == null || pass.getValue() == null || !CredentialRepresentation.PASSWORD.equals(pass.getType())) {
+            throw new BadRequestException("No password provided");
+        }
+
+        UserCredentialModel cred = RepresentationToModel.convertCredential(pass);
+        try {
+            session.users().updateCredential(realm, user, cred);
+        } catch (IllegalStateException ise) {
+            throw new BadRequestException("Resetting to N old passwords is not allowed.");
+        } catch (ModelReadOnlyException mre) {
+            throw new BadRequestException("Can't reset password as account is read only");
+        }
+        if (pass.isTemporary()) user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+    }
+
+    /**
+     *
+     *
+     * @param id
+     */
+    @Path("{id}/remove-totp")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void removeTotp(@PathParam("id") String id) {
+        auth.requireManage();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            throw new NotFoundException("User not found");
+        }
+
+        user.setTotp(false);
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+    }
+
+    /**
+     * Send an email to the user with a link they can click to reset their password.
+     * The redirectUri and clientId parameters are optional. The default for the
+     * redirect is the account client.
+     *
+     * @param id
+     * @param redirectUri redirect uri
+     * @param clientId client id
+     * @return
+     */
+    @Path("{id}/reset-password-email")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response resetPasswordEmail(@PathParam("id") String id, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
+        auth.requireManage();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
+        }
+
+        if (user.getEmail() == null) {
+            return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
+        }
+
+        ClientSessionModel clientSession = createClientSession(user, redirectUri, clientId);
+        ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
+        accessCode.setAction(ClientSessionModel.Action.RECOVER_PASSWORD.name());
+
+        try {
+            UriBuilder builder = Urls.loginPasswordResetBuilder(uriInfo.getBaseUri());
+            builder.queryParam("key", accessCode.getCode());
+
+            String link = builder.build(realm.getName()).toString();
+            long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
+
+            this.session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendPasswordReset(link, expiration);
+
+            //audit.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
+
+            adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+
+            return Response.ok().build();
+        } catch (EmailException e) {
+            logger.error("Failed to send password reset email", e);
+            return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * Send an email to the user with a link they can click to verify their email address.
+     * The redirectUri and clientId parameters are optional. The default for the
+     * redirect is the account client.
+     *
+     * @param id
+     * @param redirectUri redirect uri
+     * @param clientId client id
+     * @return
+     */
+    @Path("{id}/send-verify-email")
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response sendVerifyEmail(@PathParam("id") String id, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
+        auth.requireManage();
+
+        UserModel user = session.users().getUserById(id, realm);
+        if (user == null) {
+            return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
+        }
+
+        if (user.getEmail() == null) {
+            return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
+        }
+
+        ClientSessionModel clientSession = createClientSession(user, redirectUri, clientId);
+        ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
+
+        accessCode.setAction(ClientSessionModel.Action.VERIFY_EMAIL.name());
+
+        try {
+            UriBuilder builder = Urls.loginActionEmailVerificationBuilder(uriInfo.getBaseUri());
+            builder.queryParam("key", accessCode.getCode());
+
+            String link = builder.build(realm.getName()).toString();
+            long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
+
+            this.session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendVerifyEmail(link, expiration);
+
+            //audit.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
+
+            adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+
+            return Response.ok().build();
+        } catch (EmailException e) {
+            logger.error("Failed to send verification email", e);
+            return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    private ClientSessionModel createClientSession(UserModel user, String redirectUri, String clientId) {
+
+        if (!user.isEnabled()) {
+            throw new WebApplicationException(
+                ErrorResponse.error("User is disabled", Response.Status.BAD_REQUEST));
+        }
+
+        if (redirectUri != null && clientId == null) {
+            throw new WebApplicationException(
+                ErrorResponse.error("Client id missing", Response.Status.BAD_REQUEST));
+        }
+
+        if (clientId == null) {
+            clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
+        }
+
+        ClientModel client = realm.getClientByClientId(clientId);
+        if (client == null || !client.isEnabled()) {
+            throw new WebApplicationException(
+                ErrorResponse.error(clientId + " not enabled", Response.Status.BAD_REQUEST));
+        }
+
+        String redirect;
+        if (redirectUri != null) {
+            redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
+            if (redirect == null) {
+                throw new WebApplicationException(
+                    ErrorResponse.error("Invalid redirect uri.", Response.Status.BAD_REQUEST));
+            }
+        } else {
+            redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
+        }
+
+
+        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "form", false, null, null);
+        //audit.session(userSession);
+        ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+        clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        clientSession.setRedirectUri(redirect);
+        clientSession.setUserSession(userSession);
+
+        return clientSession;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java b/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java
index 10ce8db..c9ec4c3 100755
--- a/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java
+++ b/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java
@@ -1,49 +1,49 @@
-package org.keycloak.services.resources;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-
-import javax.ws.rs.core.MultivaluedMap;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class AttributeFormDataProcessor {
-    /**
-     * Looks for "user.attributes." keys in the form data and sets the appropriate UserModel.attribute from it.
-     *
-     * @param formData
-     * @param realm
-     * @param user
-     */
-    public static void process(MultivaluedMap<String, String> formData, RealmModel realm, UserModel user) {
-        for (String key : formData.keySet()) {
-            if (!key.startsWith("user.attributes.")) continue;
-            String attribute = key.substring("user.attributes.".length());
-
-            // Need to handle case when attribute has multiple values, but in UI was displayed just first value
-            List<String> modelValue = new ArrayList<>(user.getAttribute(attribute));
-
-            int index = 0;
-            for (String value : formData.get(key)) {
-                addOrSetValue(modelValue, index, value);
-                index++;
-            }
-
-            user.setAttribute(attribute, modelValue);
-        }
-
-    }
-
-    private static void addOrSetValue(List<String> list, int index, String value) {
-        if (list.size() > index) {
-            list.set(index, value);
-        } else {
-            list.add(value);
-        }
-    }
-}
+package org.keycloak.services.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class AttributeFormDataProcessor {
+    /**
+     * Looks for "user.attributes." keys in the form data and sets the appropriate UserModel.attribute from it.
+     *
+     * @param formData
+     * @param realm
+     * @param user
+     */
+    public static void process(MultivaluedMap<String, String> formData, RealmModel realm, UserModel user) {
+        for (String key : formData.keySet()) {
+            if (!key.startsWith("user.attributes.")) continue;
+            String attribute = key.substring("user.attributes.".length());
+
+            // Need to handle case when attribute has multiple values, but in UI was displayed just first value
+            List<String> modelValue = new ArrayList<>(user.getAttribute(attribute));
+
+            int index = 0;
+            for (String value : formData.get(key)) {
+                addOrSetValue(modelValue, index, value);
+                index++;
+            }
+
+            user.setAttribute(attribute, modelValue);
+        }
+
+    }
+
+    private static void addOrSetValue(List<String> list, int index, String value) {
+        if (list.size() > index) {
+            list.set(index, value);
+        } else {
+            list.add(value);
+        }
+    }
+}
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 bedb150..dc53a5b 100755
--- a/services/src/main/java/org/keycloak/services/resources/Cors.java
+++ b/services/src/main/java/org/keycloak/services/resources/Cors.java
@@ -1,190 +1,190 @@
-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.models.ClientModel;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.util.CollectionUtil;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class Cors {
-    protected 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";
-    public static final String DEFAULT_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers";
-
-    public static final String ORIGIN_HEADER = "Origin";
-    public static final String AUTHORIZATION_HEADER = "Authorization";
-
-    public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
-    public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
-    public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
-    public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
-    public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
-    public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
-
-    public static final String ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD = "*";
-
-    private HttpRequest request;
-    private ResponseBuilder builder;
-    private Set<String> allowedOrigins;
-    private Set<String> allowedMethods;
-    private Set<String> exposedHeaders;
-
-    private boolean preflight;
-    private boolean auth;
-
-    public Cors(HttpRequest request, ResponseBuilder response) {
-        this.request = request;
-        this.builder = response;
-    }
-
-    public Cors(HttpRequest request) {
-        this.request = request;
-    }
-
-    public static Cors add(HttpRequest request, ResponseBuilder response) {
-        return new Cors(request, response);
-    }
-
-    public static Cors add(HttpRequest request) {
-        return new Cors(request);
-    }
-
-    public Cors preflight() {
-        preflight = true;
-        return this;
-    }
-
-    public Cors auth() {
-        auth = true;
-        return this;
-    }
-
-    public Cors allowedOrigins(ClientModel client) {
-        if (client != null) {
-            allowedOrigins = client.getWebOrigins();
-        }
-        return this;
-    }
-
-    public Cors allowedOrigins(AccessToken token) {
-        if (token != null) {
-            allowedOrigins = token.getAllowedOrigins();
-        }
-        return this;
-    }
-
-    public Cors allowedOrigins(String... allowedOrigins) {
-        if (allowedOrigins != null && allowedOrigins.length > 0) {
-            this.allowedOrigins = new HashSet<String>(Arrays.asList(allowedOrigins));
-        }
-        return this;
-    }
-
-    public Cors allowedMethods(String... allowedMethods) {
-        this.allowedMethods = new HashSet<String>(Arrays.asList(allowedMethods));
-        return this;
-    }
-
-    public Cors exposedHeaders(String... exposedHeaders) {
-        this.exposedHeaders = new HashSet<String>(Arrays.asList(exposedHeaders));
-        return this;
-    }
-
-    public Response build() {
-        String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
-        if (origin == null) {
-            return builder.build();
-        }
-
-        if (!preflight && (allowedOrigins == null || (!allowedOrigins.contains(origin) && !allowedOrigins.contains(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD)))) {
-            return builder.build();
-        }
-
-        builder.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
-
-        if (preflight) {
-            if (allowedMethods != null) {
-                builder.header(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
-            } else {
-                builder.header(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
-            }
-        }
-
-        if (!preflight && exposedHeaders != null) {
-            builder.header(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
-        }
-
-        builder.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
-
-        if (preflight) {
-            if (auth) {
-                builder.header(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
-            } else {
-                builder.header(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
-            }
-        }
-
-        if (preflight) {
-            builder.header(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
-        }
-
-        return builder.build();
-    }
-
-    public void build(HttpResponse response) {
-        String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
-        if (origin == null) {
-            logger.debug("No origin returning");
-            return;
-        }
-
-        if (!preflight && (allowedOrigins == null || (!allowedOrigins.contains(origin) && !allowedOrigins.contains(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD)))) {
-            logger.debug("!preflight and no origin");
-            return;
-        }
-
-        logger.debug("build CORS headers and return");
-
-        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
-
-        if (preflight) {
-            if (allowedMethods != null) {
-                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
-            } else {
-                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
-            }
-        }
-
-        if (!preflight && exposedHeaders != null) {
-            response.getOutputHeaders().add(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
-        }
-
-        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
-
-        if (preflight) {
-            if (auth) {
-                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
-            } else {
-                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
-            }
-        }
-
-        if (preflight) {
-            response.getOutputHeaders().add(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
-        }
-    }
-
-}
+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.models.ClientModel;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.util.CollectionUtil;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class Cors {
+    protected 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";
+    public static final String DEFAULT_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers";
+
+    public static final String ORIGIN_HEADER = "Origin";
+    public static final String AUTHORIZATION_HEADER = "Authorization";
+
+    public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
+    public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
+    public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
+    public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
+    public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
+    public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
+
+    public static final String ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD = "*";
+
+    private HttpRequest request;
+    private ResponseBuilder builder;
+    private Set<String> allowedOrigins;
+    private Set<String> allowedMethods;
+    private Set<String> exposedHeaders;
+
+    private boolean preflight;
+    private boolean auth;
+
+    public Cors(HttpRequest request, ResponseBuilder response) {
+        this.request = request;
+        this.builder = response;
+    }
+
+    public Cors(HttpRequest request) {
+        this.request = request;
+    }
+
+    public static Cors add(HttpRequest request, ResponseBuilder response) {
+        return new Cors(request, response);
+    }
+
+    public static Cors add(HttpRequest request) {
+        return new Cors(request);
+    }
+
+    public Cors preflight() {
+        preflight = true;
+        return this;
+    }
+
+    public Cors auth() {
+        auth = true;
+        return this;
+    }
+
+    public Cors allowedOrigins(ClientModel client) {
+        if (client != null) {
+            allowedOrigins = client.getWebOrigins();
+        }
+        return this;
+    }
+
+    public Cors allowedOrigins(AccessToken token) {
+        if (token != null) {
+            allowedOrigins = token.getAllowedOrigins();
+        }
+        return this;
+    }
+
+    public Cors allowedOrigins(String... allowedOrigins) {
+        if (allowedOrigins != null && allowedOrigins.length > 0) {
+            this.allowedOrigins = new HashSet<String>(Arrays.asList(allowedOrigins));
+        }
+        return this;
+    }
+
+    public Cors allowedMethods(String... allowedMethods) {
+        this.allowedMethods = new HashSet<String>(Arrays.asList(allowedMethods));
+        return this;
+    }
+
+    public Cors exposedHeaders(String... exposedHeaders) {
+        this.exposedHeaders = new HashSet<String>(Arrays.asList(exposedHeaders));
+        return this;
+    }
+
+    public Response build() {
+        String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
+        if (origin == null) {
+            return builder.build();
+        }
+
+        if (!preflight && (allowedOrigins == null || (!allowedOrigins.contains(origin) && !allowedOrigins.contains(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD)))) {
+            return builder.build();
+        }
+
+        builder.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+
+        if (preflight) {
+            if (allowedMethods != null) {
+                builder.header(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
+            } else {
+                builder.header(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
+            }
+        }
+
+        if (!preflight && exposedHeaders != null) {
+            builder.header(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
+        }
+
+        builder.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
+
+        if (preflight) {
+            if (auth) {
+                builder.header(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+            } else {
+                builder.header(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
+            }
+        }
+
+        if (preflight) {
+            builder.header(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
+        }
+
+        return builder.build();
+    }
+
+    public void build(HttpResponse response) {
+        String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
+        if (origin == null) {
+            logger.debug("No origin returning");
+            return;
+        }
+
+        if (!preflight && (allowedOrigins == null || (!allowedOrigins.contains(origin) && !allowedOrigins.contains(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD)))) {
+            logger.debug("!preflight and no origin");
+            return;
+        }
+
+        logger.debug("build CORS headers and return");
+
+        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+
+        if (preflight) {
+            if (allowedMethods != null) {
+                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
+            } else {
+                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
+            }
+        }
+
+        if (!preflight && exposedHeaders != null) {
+            response.getOutputHeaders().add(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
+        }
+
+        response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
+
+        if (preflight) {
+            if (auth) {
+                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+            } else {
+                response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
+            }
+        }
+
+        if (preflight) {
+            response.getOutputHeaders().add(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
+        }
+    }
+
+}
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 875511e..ab55ef3 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -1,266 +1,266 @@
-package org.keycloak.services.resources;
-
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.core.Dispatcher;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.Config;
-import org.keycloak.SkeletonKeyContextResolver;
-import org.keycloak.exportimport.ExportImportManager;
-import org.keycloak.migration.MigrationModelManager;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.DefaultKeycloakSessionFactory;
-import org.keycloak.services.managers.ApplianceBootstrap;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.managers.UsersSyncManager;
-import org.keycloak.services.resources.admin.AdminRoot;
-import org.keycloak.services.scheduled.ClearExpiredEvents;
-import org.keycloak.services.scheduled.ClearExpiredUserSessions;
-import org.keycloak.services.scheduled.ScheduledTaskRunner;
-import org.keycloak.services.util.JsonConfigProvider;
-import org.keycloak.timer.TimerProvider;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.SystemEnvProperties;
-
-import javax.servlet.ServletContext;
-import javax.ws.rs.core.Application;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.UriInfo;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import org.keycloak.offlineconfig.AdminRecovery;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class KeycloakApplication extends Application {
-
-    private static final Logger log = Logger.getLogger(KeycloakApplication.class);
-
-    protected Set<Object> singletons = new HashSet<Object>();
-    protected Set<Class<?>> classes = new HashSet<Class<?>>();
-
-    protected KeycloakSessionFactory sessionFactory;
-    protected String contextPath;
-
-    public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
-        loadConfig();
-
-        this.contextPath = context.getContextPath();
-        this.sessionFactory = createSessionFactory();
-
-        dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
-        BruteForceProtector protector = new BruteForceProtector(sessionFactory);
-        dispatcher.getDefaultContextObjects().put(BruteForceProtector.class, protector);
-        ResteasyProviderFactory.pushContext(BruteForceProtector.class, protector); // for injection
-        ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
-        protector.start();
-        context.setAttribute(BruteForceProtector.class.getName(), protector);
-        context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
-
-        singletons.add(new ServerVersionResource());
-        singletons.add(new RealmsResource());
-        singletons.add(new AdminRoot());
-        singletons.add(new ModelExceptionMapper());
-        classes.add(SkeletonKeyContextResolver.class);
-        classes.add(QRCodeResource.class);
-        classes.add(ThemeResource.class);
-        classes.add(JsResource.class);
-        classes.add(WelcomeResource.class);
-
-        new ExportImportManager().checkExportImport(this.sessionFactory, context.getContextPath());
-
-        setupDefaultRealm(context.getContextPath());
-
-        importRealms(context);
-        migrateModel();
-
-        AdminRecovery.recover(sessionFactory);
-
-        setupScheduledTasks(sessionFactory);
-    }
-
-    protected void migrateModel() {
-        KeycloakSession session = sessionFactory.create();
-        try {
-            session.getTransaction().begin();
-            MigrationModelManager.migrate(session);
-            session.getTransaction().commit();
-        } catch (Exception e) {
-            session.getTransaction().rollback();
-            log.error("Failed to migrate datamodel", e);
-        } finally {
-            session.close();
-        }
-    }
-
-    public String getContextPath() {
-        return contextPath;
-    }
-
-    /**
-     * Get base URI of WAR distribution, not JAX-RS
-     *
-     * @param uriInfo
-     * @return
-     */
-    public URI getBaseUri(UriInfo uriInfo) {
-        return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
-    }
-
-    public static void loadConfig() {
-        try {
-            JsonNode node = null;
-
-            String configDir = System.getProperty("jboss.server.config.dir");
-            if (configDir != null) {
-                File f = new File(configDir + File.separator + "keycloak-server.json");
-                if (f.isFile()) {
-                    log.info("Load config from " + f.getAbsolutePath());
-                    node = new ObjectMapper().readTree(f);
-                }
-            }
-
-            if (node == null) {
-                URL resource = Thread.currentThread().getContextClassLoader().getResource("META-INF/keycloak-server.json");
-                log.info("Load config from " + resource);
-                node = new ObjectMapper().readTree(resource);
-            }
-
-            if (node != null) {
-                Properties properties = new SystemEnvProperties();
-                Config.init(new JsonConfigProvider(node, properties));
-                return;
-            } else {
-                log.warn("Config 'keycloak-server.json' not found");
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to load config", e);
-        }
-    }
-
-    protected void setupDefaultRealm(String contextPath) {
-        new ApplianceBootstrap().bootstrap(sessionFactory, contextPath);
-    }
-
-    public static KeycloakSessionFactory createSessionFactory() {
-        DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
-        factory.init();
-        return factory;
-    }
-
-    public static void setupScheduledTasks(final KeycloakSessionFactory sessionFactory) {
-        long interval = Config.scope("scheduled").getLong("interval", 60L) * 1000;
-
-        TimerProvider timer = sessionFactory.create().getProvider(TimerProvider.class);
-        timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredEvents()), interval, "ClearExpiredEvents");
-        timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredUserSessions()), interval, "ClearExpiredUserSessions");
-        new UsersSyncManager().bootstrapPeriodic(sessionFactory, timer);
-    }
-
-    public KeycloakSessionFactory getSessionFactory() {
-        return sessionFactory;
-    }
-
-    @Override
-    public Set<Class<?>> getClasses() {
-        return classes;
-    }
-
-    @Override
-    public Set<Object> getSingletons() {
-        return singletons;
-    }
-
-    public void importRealms(ServletContext context) {
-        importRealmFile();
-        importRealmResources(context);
-    }
-
-    public void importRealmResources(ServletContext context) {
-        String resources = context.getInitParameter("keycloak.import.realm.resources");
-        if (resources != null) {
-            StringTokenizer tokenizer = new StringTokenizer(resources, ",");
-            while (tokenizer.hasMoreTokens()) {
-                String resource = tokenizer.nextToken().trim();
-                InputStream is = context.getResourceAsStream(resource);
-                if (is == null) {
-                    log.warn("Could not find realm resource to import: " + resource);
-                }
-                RealmRepresentation rep = loadJson(is, RealmRepresentation.class);
-                importRealm(rep, "resource " + resource);
-            }
-        }
-    }
-
-    public void importRealmFile() {
-        String files = System.getProperty("keycloak.import");
-        if (files != null) {
-            StringTokenizer tokenizer = new StringTokenizer(files, ",");
-            while (tokenizer.hasMoreTokens()) {
-                String file = tokenizer.nextToken().trim();
-                RealmRepresentation rep = null;
-                try {
-                    rep = loadJson(new FileInputStream(file), RealmRepresentation.class);
-                } catch (FileNotFoundException e) {
-                    throw new RuntimeException(e);
-                }
-                importRealm(rep, "file " + file);
-            }
-        }
-    }
-
-    public void importRealm(RealmRepresentation rep, String from) {
-        KeycloakSession session = sessionFactory.create();
-        try {
-            session.getTransaction().begin();
-            RealmManager manager = new RealmManager(session);
-            manager.setContextPath(getContextPath());
-
-            if (rep.getId() != null && manager.getRealm(rep.getId()) != null) {
-                log.info("Not importing realm " + rep.getRealm() + " from " + from + ".  It already exists.");
-                return;
-            }
-
-            if (manager.getRealmByName(rep.getRealm()) != null) {
-                log.info("Not importing realm " + rep.getRealm() + " from " + from + ".  It already exists.");
-                return;
-            }
-
-            try {
-                RealmModel realm = manager.importRealm(rep);
-                session.getTransaction().commit();
-                log.info("Imported realm " + realm.getName() + " from " + from);
-            } catch (Throwable t) {
-                session.getTransaction().rollback();
-                log.warn("Unable to import realm " + rep.getRealm() + " from " + from + ". Cause: " + t.getMessage());
-            }
-        } finally {
-            session.close();
-        }
-    }
-
-    private static <T> T loadJson(InputStream is, Class<T> type) {
-        try {
-            return JsonSerialization.readValue(is, type);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse json", e);
-        }
-    }
-
-}
+package org.keycloak.services.resources;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.core.Dispatcher;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.Config;
+import org.keycloak.SkeletonKeyContextResolver;
+import org.keycloak.exportimport.ExportImportManager;
+import org.keycloak.migration.MigrationModelManager;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.DefaultKeycloakSessionFactory;
+import org.keycloak.services.managers.ApplianceBootstrap;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.UsersSyncManager;
+import org.keycloak.services.resources.admin.AdminRoot;
+import org.keycloak.services.scheduled.ClearExpiredEvents;
+import org.keycloak.services.scheduled.ClearExpiredUserSessions;
+import org.keycloak.services.scheduled.ScheduledTaskRunner;
+import org.keycloak.services.util.JsonConfigProvider;
+import org.keycloak.timer.TimerProvider;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.SystemEnvProperties;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import org.keycloak.offlineconfig.AdminRecovery;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class KeycloakApplication extends Application {
+
+    private static final Logger log = Logger.getLogger(KeycloakApplication.class);
+
+    protected Set<Object> singletons = new HashSet<Object>();
+    protected Set<Class<?>> classes = new HashSet<Class<?>>();
+
+    protected KeycloakSessionFactory sessionFactory;
+    protected String contextPath;
+
+    public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
+        loadConfig();
+
+        this.contextPath = context.getContextPath();
+        this.sessionFactory = createSessionFactory();
+
+        dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
+        BruteForceProtector protector = new BruteForceProtector(sessionFactory);
+        dispatcher.getDefaultContextObjects().put(BruteForceProtector.class, protector);
+        ResteasyProviderFactory.pushContext(BruteForceProtector.class, protector); // for injection
+        ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
+        protector.start();
+        context.setAttribute(BruteForceProtector.class.getName(), protector);
+        context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
+
+        singletons.add(new ServerVersionResource());
+        singletons.add(new RealmsResource());
+        singletons.add(new AdminRoot());
+        singletons.add(new ModelExceptionMapper());
+        classes.add(SkeletonKeyContextResolver.class);
+        classes.add(QRCodeResource.class);
+        classes.add(ThemeResource.class);
+        classes.add(JsResource.class);
+        classes.add(WelcomeResource.class);
+
+        new ExportImportManager().checkExportImport(this.sessionFactory, context.getContextPath());
+
+        setupDefaultRealm(context.getContextPath());
+
+        importRealms(context);
+        migrateModel();
+
+        AdminRecovery.recover(sessionFactory);
+
+        setupScheduledTasks(sessionFactory);
+    }
+
+    protected void migrateModel() {
+        KeycloakSession session = sessionFactory.create();
+        try {
+            session.getTransaction().begin();
+            MigrationModelManager.migrate(session);
+            session.getTransaction().commit();
+        } catch (Exception e) {
+            session.getTransaction().rollback();
+            log.error("Failed to migrate datamodel", e);
+        } finally {
+            session.close();
+        }
+    }
+
+    public String getContextPath() {
+        return contextPath;
+    }
+
+    /**
+     * Get base URI of WAR distribution, not JAX-RS
+     *
+     * @param uriInfo
+     * @return
+     */
+    public URI getBaseUri(UriInfo uriInfo) {
+        return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
+    }
+
+    public static void loadConfig() {
+        try {
+            JsonNode node = null;
+
+            String configDir = System.getProperty("jboss.server.config.dir");
+            if (configDir != null) {
+                File f = new File(configDir + File.separator + "keycloak-server.json");
+                if (f.isFile()) {
+                    log.info("Load config from " + f.getAbsolutePath());
+                    node = new ObjectMapper().readTree(f);
+                }
+            }
+
+            if (node == null) {
+                URL resource = Thread.currentThread().getContextClassLoader().getResource("META-INF/keycloak-server.json");
+                log.info("Load config from " + resource);
+                node = new ObjectMapper().readTree(resource);
+            }
+
+            if (node != null) {
+                Properties properties = new SystemEnvProperties();
+                Config.init(new JsonConfigProvider(node, properties));
+                return;
+            } else {
+                log.warn("Config 'keycloak-server.json' not found");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to load config", e);
+        }
+    }
+
+    protected void setupDefaultRealm(String contextPath) {
+        new ApplianceBootstrap().bootstrap(sessionFactory, contextPath);
+    }
+
+    public static KeycloakSessionFactory createSessionFactory() {
+        DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
+        factory.init();
+        return factory;
+    }
+
+    public static void setupScheduledTasks(final KeycloakSessionFactory sessionFactory) {
+        long interval = Config.scope("scheduled").getLong("interval", 60L) * 1000;
+
+        TimerProvider timer = sessionFactory.create().getProvider(TimerProvider.class);
+        timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredEvents()), interval, "ClearExpiredEvents");
+        timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredUserSessions()), interval, "ClearExpiredUserSessions");
+        new UsersSyncManager().bootstrapPeriodic(sessionFactory, timer);
+    }
+
+    public KeycloakSessionFactory getSessionFactory() {
+        return sessionFactory;
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return classes;
+    }
+
+    @Override
+    public Set<Object> getSingletons() {
+        return singletons;
+    }
+
+    public void importRealms(ServletContext context) {
+        importRealmFile();
+        importRealmResources(context);
+    }
+
+    public void importRealmResources(ServletContext context) {
+        String resources = context.getInitParameter("keycloak.import.realm.resources");
+        if (resources != null) {
+            StringTokenizer tokenizer = new StringTokenizer(resources, ",");
+            while (tokenizer.hasMoreTokens()) {
+                String resource = tokenizer.nextToken().trim();
+                InputStream is = context.getResourceAsStream(resource);
+                if (is == null) {
+                    log.warn("Could not find realm resource to import: " + resource);
+                }
+                RealmRepresentation rep = loadJson(is, RealmRepresentation.class);
+                importRealm(rep, "resource " + resource);
+            }
+        }
+    }
+
+    public void importRealmFile() {
+        String files = System.getProperty("keycloak.import");
+        if (files != null) {
+            StringTokenizer tokenizer = new StringTokenizer(files, ",");
+            while (tokenizer.hasMoreTokens()) {
+                String file = tokenizer.nextToken().trim();
+                RealmRepresentation rep = null;
+                try {
+                    rep = loadJson(new FileInputStream(file), RealmRepresentation.class);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+                importRealm(rep, "file " + file);
+            }
+        }
+    }
+
+    public void importRealm(RealmRepresentation rep, String from) {
+        KeycloakSession session = sessionFactory.create();
+        try {
+            session.getTransaction().begin();
+            RealmManager manager = new RealmManager(session);
+            manager.setContextPath(getContextPath());
+
+            if (rep.getId() != null && manager.getRealm(rep.getId()) != null) {
+                log.info("Not importing realm " + rep.getRealm() + " from " + from + ".  It already exists.");
+                return;
+            }
+
+            if (manager.getRealmByName(rep.getRealm()) != null) {
+                log.info("Not importing realm " + rep.getRealm() + " from " + from + ".  It already exists.");
+                return;
+            }
+
+            try {
+                RealmModel realm = manager.importRealm(rep);
+                session.getTransaction().commit();
+                log.info("Imported realm " + realm.getName() + " from " + from);
+            } catch (Throwable t) {
+                session.getTransaction().rollback();
+                log.warn("Unable to import realm " + rep.getRealm() + " from " + from + ". Cause: " + t.getMessage());
+            }
+        } finally {
+            session.close();
+        }
+    }
+
+    private static <T> T loadJson(InputStream is, Class<T> type) {
+        try {
+            return JsonSerialization.readValue(is, type);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to parse json", e);
+        }
+    }
+
+}
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 25beaa5..6758af9 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -1,81 +1,81 @@
-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.models.RealmModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.representations.idm.PublishedRealmRepresentation;
-import org.keycloak.services.resources.admin.AdminRoot;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * Resource class for public realm information
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class PublicRealmResource {
-    protected static final  Logger logger = Logger.getLogger(PublicRealmResource.class);
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected HttpRequest request;
-
-    @Context
-    protected HttpResponse response;
-
-    protected RealmModel realm;
-
-    public PublicRealmResource(RealmModel realm) {
-        this.realm = realm;
-    }
-
-    /**
-     * CORS preflight
-     *
-     * @return
-     */
-    @Path("/")
-    @OPTIONS
-    public Response accountPreflight() {
-        return Cors.add(request, Response.ok()).auth().preflight().build();
-    }
-
-    /**
-     * Public information about the realm.
-     *
-     * @return
-     */
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public PublishedRealmRepresentation getRealm() {
-        Cors.add(request).allowedOrigins(Cors.ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD).auth().build(response);
-        return realmRep(realm, uriInfo);
-    }
-
-    public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
-        PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
-        rep.setRealm(realm.getName());
-        rep.setTokenServiceUrl(OIDCLoginProtocolService.tokenServiceBaseUrl(uriInfo).build(realm.getName()).toString());
-        rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getName()).toString());
-        rep.setAdminApiUrl(uriInfo.getBaseUriBuilder().path(AdminRoot.class).build().toString());
-        rep.setPublicKeyPem(realm.getPublicKeyPem());
-        rep.setNotBefore(realm.getNotBefore());
-        return rep;
-    }
-
-
-}
+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.models.RealmModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.representations.idm.PublishedRealmRepresentation;
+import org.keycloak.services.resources.admin.AdminRoot;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Resource class for public realm information
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class PublicRealmResource {
+    protected static final  Logger logger = Logger.getLogger(PublicRealmResource.class);
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected HttpRequest request;
+
+    @Context
+    protected HttpResponse response;
+
+    protected RealmModel realm;
+
+    public PublicRealmResource(RealmModel realm) {
+        this.realm = realm;
+    }
+
+    /**
+     * CORS preflight
+     *
+     * @return
+     */
+    @Path("/")
+    @OPTIONS
+    public Response accountPreflight() {
+        return Cors.add(request, Response.ok()).auth().preflight().build();
+    }
+
+    /**
+     * Public information about the realm.
+     *
+     * @return
+     */
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public PublishedRealmRepresentation getRealm() {
+        Cors.add(request).allowedOrigins(Cors.ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD).auth().build(response);
+        return realmRep(realm, uriInfo);
+    }
+
+    public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
+        PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
+        rep.setRealm(realm.getName());
+        rep.setTokenServiceUrl(OIDCLoginProtocolService.tokenServiceBaseUrl(uriInfo).build(realm.getName()).toString());
+        rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getName()).toString());
+        rep.setAdminApiUrl(uriInfo.getBaseUriBuilder().path(AdminRoot.class).build().toString());
+        rep.setPublicKeyPem(realm.getPublicKeyPem());
+        rep.setNotBefore(realm.getNotBefore());
+        return rep;
+    }
+
+
+}
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 ee91b43..083eb9a 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -1,182 +1,182 @@
-package org.keycloak.services.resources;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.ClientConnection;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.LoginProtocolFactory;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.wellknown.WellKnownProvider;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Path("/realms")
-public class RealmsResource {
-    protected static Logger logger = Logger.getLogger(RealmsResource.class);
-
-    @Context
-    protected KeycloakSession session;
-
-    @Context
-    protected ClientConnection clientConnection;
-
-    @Context
-    protected BruteForceProtector protector;
-
-    public static UriBuilder realmBaseUrl(UriInfo uriInfo) {
-        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
-    }
-
-    public static UriBuilder accountUrl(UriBuilder base) {
-        return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
-    }
-
-    public static UriBuilder protocolUrl(UriInfo uriInfo) {
-        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
-    }
-
-    public static UriBuilder brokerUrl(UriInfo uriInfo) {
-        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getBrokerService");
-    }
-
-    @Path("{realm}/login-status-iframe.html")
-    @Deprecated
-    public Object getLoginStatusIframe(final @PathParam("realm") String name,
-                                       @QueryParam("client_id") String client_id,
-                                       @QueryParam("origin") String origin) {
-        RealmModel realm = init(name);
-
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        AuthenticationManager authManager = new AuthenticationManager(protector);
-
-        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OIDCLoginProtocol.LOGIN_PROTOCOL);
-        OIDCLoginProtocolService endpoint = (OIDCLoginProtocolService)factory.createProtocolEndpoint(realm, event, authManager);
-
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint.getLoginStatusIframe();
-
-    }
-
-    @Path("{realm}/protocol/{protocol}")
-    public Object getProtocol(final @PathParam("realm") String name,
-                                            final @PathParam("protocol") String protocol) {
-        RealmModel realm = init(name);
-
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        AuthenticationManager authManager = new AuthenticationManager(protector);
-
-        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, protocol);
-        Object endpoint = factory.createProtocolEndpoint(realm, event, authManager);
-
-        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
-        return endpoint;
-    }
-
-    @Path("{realm}/tokens")
-    @Deprecated
-    public Object getTokenService(final @PathParam("realm") String name) {
-        // for backward compatibility.
-        return getProtocol(name, "openid-connect");
-    }
-
-    @Path("{realm}/login-actions")
-    public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        AuthenticationManager authManager = new AuthenticationManager(protector);
-        LoginActionsService service = new LoginActionsService(realm, authManager, event);
-        ResteasyProviderFactory.getInstance().injectProperties(service);
-        return service;
-    }
-
-    @Path("{realm}/clients-managements")
-    public ClientsManagementService getClientsManagementService(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        ClientsManagementService service = new ClientsManagementService(realm, event);
-        ResteasyProviderFactory.getInstance().injectProperties(service);
-        return service;
-    }
-
-    private RealmModel init(String realmName) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(realmName);
-        if (realm == null) {
-            throw new NotFoundException("Realm does not exist");
-        }
-        session.getContext().setRealm(realm);
-        return realm;
-    }
-
-    @Path("{realm}/account")
-    public AccountService getAccountService(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-
-        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-        if (client == null || !client.isEnabled()) {
-            logger.debug("account management not enabled");
-            throw new NotFoundException("account management not enabled");
-        }
-
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        AccountService accountService = new AccountService(realm, client, event);
-        ResteasyProviderFactory.getInstance().injectProperties(accountService);
-        accountService.init();
-        return accountService;
-    }
-
-    @Path("{realm}")
-    public PublicRealmResource getRealmResource(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-        PublicRealmResource realmResource = new PublicRealmResource(realm);
-        ResteasyProviderFactory.getInstance().injectProperties(realmResource);
-        return realmResource;
-    }
-
-    @Path("{realm}/broker")
-    public IdentityBrokerService getBrokerService(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-
-        IdentityBrokerService brokerService = new IdentityBrokerService(realm, protector);
-        ResteasyProviderFactory.getInstance().injectProperties(brokerService);
-
-        brokerService.init();
-
-        return brokerService;
-    }
-
-    @GET
-    @Path("{realm}/.well-known/{provider}")
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getWellKnown(final @PathParam("realm") String name,
-                              final @PathParam("provider") String providerName) {
-        init(name);
-
-        WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, providerName);
-        return Response.ok(wellKnown.getConfig()).build();
-    }
-
-}
+package org.keycloak.services.resources;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.LoginProtocolFactory;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.wellknown.WellKnownProvider;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Path("/realms")
+public class RealmsResource {
+    protected static Logger logger = Logger.getLogger(RealmsResource.class);
+
+    @Context
+    protected KeycloakSession session;
+
+    @Context
+    protected ClientConnection clientConnection;
+
+    @Context
+    protected BruteForceProtector protector;
+
+    public static UriBuilder realmBaseUrl(UriInfo uriInfo) {
+        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
+    }
+
+    public static UriBuilder accountUrl(UriBuilder base) {
+        return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
+    }
+
+    public static UriBuilder protocolUrl(UriInfo uriInfo) {
+        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
+    }
+
+    public static UriBuilder brokerUrl(UriInfo uriInfo) {
+        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getBrokerService");
+    }
+
+    @Path("{realm}/login-status-iframe.html")
+    @Deprecated
+    public Object getLoginStatusIframe(final @PathParam("realm") String name,
+                                       @QueryParam("client_id") String client_id,
+                                       @QueryParam("origin") String origin) {
+        RealmModel realm = init(name);
+
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+        AuthenticationManager authManager = new AuthenticationManager(protector);
+
+        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OIDCLoginProtocol.LOGIN_PROTOCOL);
+        OIDCLoginProtocolService endpoint = (OIDCLoginProtocolService)factory.createProtocolEndpoint(realm, event, authManager);
+
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint.getLoginStatusIframe();
+
+    }
+
+    @Path("{realm}/protocol/{protocol}")
+    public Object getProtocol(final @PathParam("realm") String name,
+                                            final @PathParam("protocol") String protocol) {
+        RealmModel realm = init(name);
+
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+        AuthenticationManager authManager = new AuthenticationManager(protector);
+
+        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, protocol);
+        Object endpoint = factory.createProtocolEndpoint(realm, event, authManager);
+
+        ResteasyProviderFactory.getInstance().injectProperties(endpoint);
+        return endpoint;
+    }
+
+    @Path("{realm}/tokens")
+    @Deprecated
+    public Object getTokenService(final @PathParam("realm") String name) {
+        // for backward compatibility.
+        return getProtocol(name, "openid-connect");
+    }
+
+    @Path("{realm}/login-actions")
+    public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
+        RealmModel realm = init(name);
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+        AuthenticationManager authManager = new AuthenticationManager(protector);
+        LoginActionsService service = new LoginActionsService(realm, authManager, event);
+        ResteasyProviderFactory.getInstance().injectProperties(service);
+        return service;
+    }
+
+    @Path("{realm}/clients-managements")
+    public ClientsManagementService getClientsManagementService(final @PathParam("realm") String name) {
+        RealmModel realm = init(name);
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+        ClientsManagementService service = new ClientsManagementService(realm, event);
+        ResteasyProviderFactory.getInstance().injectProperties(service);
+        return service;
+    }
+
+    private RealmModel init(String realmName) {
+        RealmManager realmManager = new RealmManager(session);
+        RealmModel realm = realmManager.getRealmByName(realmName);
+        if (realm == null) {
+            throw new NotFoundException("Realm does not exist");
+        }
+        session.getContext().setRealm(realm);
+        return realm;
+    }
+
+    @Path("{realm}/account")
+    public AccountService getAccountService(final @PathParam("realm") String name) {
+        RealmModel realm = init(name);
+
+        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        if (client == null || !client.isEnabled()) {
+            logger.debug("account management not enabled");
+            throw new NotFoundException("account management not enabled");
+        }
+
+        EventBuilder event = new EventBuilder(realm, session, clientConnection);
+        AccountService accountService = new AccountService(realm, client, event);
+        ResteasyProviderFactory.getInstance().injectProperties(accountService);
+        accountService.init();
+        return accountService;
+    }
+
+    @Path("{realm}")
+    public PublicRealmResource getRealmResource(final @PathParam("realm") String name) {
+        RealmModel realm = init(name);
+        PublicRealmResource realmResource = new PublicRealmResource(realm);
+        ResteasyProviderFactory.getInstance().injectProperties(realmResource);
+        return realmResource;
+    }
+
+    @Path("{realm}/broker")
+    public IdentityBrokerService getBrokerService(final @PathParam("realm") String name) {
+        RealmModel realm = init(name);
+
+        IdentityBrokerService brokerService = new IdentityBrokerService(realm, protector);
+        ResteasyProviderFactory.getInstance().injectProperties(brokerService);
+
+        brokerService.init();
+
+        return brokerService;
+    }
+
+    @GET
+    @Path("{realm}/.well-known/{provider}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getWellKnown(final @PathParam("realm") String name,
+                              final @PathParam("provider") String providerName) {
+        init(name);
+
+        WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, providerName);
+        return Response.ok(wellKnown.getConfig()).build();
+    }
+
+}
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 4bf4b2f..346d1e4 100755
--- a/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java
@@ -1,47 +1,47 @@
-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.Version;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@Path("/version")
-public class ServerVersionResource {
-
-    protected static final Logger logger = Logger.getLogger(ServerVersionResource.class);
-
-    @Context
-    protected HttpRequest request;
-
-    @Context
-    protected HttpResponse response;
-
-    @OPTIONS
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getVersionPreflight() {
-        logger.debugv("cors request from: {0}", request.getHttpHeaders().getRequestHeaders().getFirst("Origin"));
-        return Cors.add(request, Response.ok()).allowedMethods("GET").auth().preflight().build();
-    }
-
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Version getVersion() {
-        Cors.add(request).allowedOrigins("*").allowedMethods("GET").auth().build(response);
-        return Version.SINGLETON;
-    }
-}
+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.Version;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@Path("/version")
+public class ServerVersionResource {
+
+    protected static final Logger logger = Logger.getLogger(ServerVersionResource.class);
+
+    @Context
+    protected HttpRequest request;
+
+    @Context
+    protected HttpResponse response;
+
+    @OPTIONS
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getVersionPreflight() {
+        logger.debugv("cors request from: {0}", request.getHttpHeaders().getRequestHeaders().getFirst("Origin"));
+        return Cors.add(request, Response.ok()).allowedMethods("GET").auth().preflight().build();
+    }
+
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Version getVersion() {
+        Cors.add(request).allowedOrigins("*").allowedMethods("GET").auth().build(response);
+        return Version.SINGLETON;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/util/CookieHelper.java b/services/src/main/java/org/keycloak/services/util/CookieHelper.java
index 00d5156..04fcb1d 100755
--- a/services/src/main/java/org/keycloak/services/util/CookieHelper.java
+++ b/services/src/main/java/org/keycloak/services/util/CookieHelper.java
@@ -1,36 +1,36 @@
-package org.keycloak.services.util;
-
-import org.jboss.resteasy.spi.HttpResponse;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.util.ServerCookie;
-
-import javax.ws.rs.core.HttpHeaders;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CookieHelper {
-
-    /**
-     * Set a response cookie.  This solely exists because JAX-RS 1.1 does not support setting HttpOnly cookies
-     *
-     * @param name
-     * @param value
-     * @param path
-     * @param domain
-     * @param comment
-     * @param maxAge
-     * @param secure
-     * @param httpOnly
-     */
-    public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
-        HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
-        StringBuffer cookieBuf = new StringBuffer();
-        ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly);
-        String cookie = cookieBuf.toString();
-        response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
-    }
-
-
-}
+package org.keycloak.services.util;
+
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.util.ServerCookie;
+
+import javax.ws.rs.core.HttpHeaders;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CookieHelper {
+
+    /**
+     * Set a response cookie.  This solely exists because JAX-RS 1.1 does not support setting HttpOnly cookies
+     *
+     * @param name
+     * @param value
+     * @param path
+     * @param domain
+     * @param comment
+     * @param maxAge
+     * @param secure
+     * @param httpOnly
+     */
+    public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
+        HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
+        StringBuffer cookieBuf = new StringBuffer();
+        ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly);
+        String cookie = cookieBuf.toString();
+        response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/util/HttpClientBuilder.java b/services/src/main/java/org/keycloak/services/util/HttpClientBuilder.java
index 374131f..23b874e 100755
--- a/services/src/main/java/org/keycloak/services/util/HttpClientBuilder.java
+++ b/services/src/main/java/org/keycloak/services/util/HttpClientBuilder.java
@@ -1,314 +1,314 @@
-package org.keycloak.services.util;
-
-import org.apache.http.client.HttpClient;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.SingleClientConnManager;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.keycloak.util.EnvUtil;
-import org.keycloak.util.KeystoreUtil;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Abstraction for creating HttpClients. Allows SSL configuration.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class HttpClientBuilder {
-    public static enum HostnameVerificationPolicy {
-        /**
-         * Hostname verification is not done on the server's certificate
-         */
-        ANY,
-        /**
-         * Allows wildcards in subdomain names i.e. *.foo.com
-         */
-        WILDCARD,
-        /**
-         * CN must match hostname connecting to
-         */
-        STRICT
-    }
-
-
-    /**
-     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
-     * @version $Revision: 1 $
-     */
-    private static class PassthroughTrustManager implements X509TrustManager {
-        public void checkClientTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public void checkServerTrusted(X509Certificate[] chain,
-                                       String authType) throws CertificateException {
-        }
-
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
-    }
-
-    protected KeyStore truststore;
-    protected KeyStore clientKeyStore;
-    protected String clientPrivateKeyPassword;
-    protected boolean disableTrustManager;
-    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
-    protected SSLContext sslContext;
-    protected int connectionPoolSize = 100;
-    protected int maxPooledPerRoute = 0;
-    protected long connectionTTL = -1;
-    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
-    protected HostnameVerifier verifier = null;
-    protected long socketTimeout = -1;
-    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
-    protected long establishConnectionTimeout = -1;
-    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
-
-
-    /**
-     * Socket inactivity timeout
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
-    {
-        this.socketTimeout = timeout;
-        this.socketTimeoutUnits = unit;
-        return this;
-    }
-
-    /**
-     * When trying to make an initial socket connection, what is the timeout?
-     *
-     * @param timeout
-     * @param unit
-     * @return
-     */
-    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
-    {
-        this.establishConnectionTimeout = timeout;
-        this.establishConnectionTimeoutUnits = unit;
-        return this;
-    }
-
-    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
-        this.connectionTTL = ttl;
-        this.connectionTTLUnit = unit;
-        return this;
-    }
-
-    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
-        this.maxPooledPerRoute = maxPooledPerRoute;
-        return this;
-    }
-
-    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
-        this.connectionPoolSize = connectionPoolSize;
-        return this;
-    }
-
-    /**
-     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
-     * hole, so only set this option if you cannot or do not want to verify the identity of the
-     * host you are communicating with.
-     */
-    public HttpClientBuilder disableTrustManager() {
-        this.disableTrustManager = true;
-        return this;
-    }
-
-    /**
-     * SSL policy used to verify hostnames
-     *
-     * @param policy
-     * @return
-     */
-    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
-        this.policy = policy;
-        return this;
-    }
-
-
-    public HttpClientBuilder sslContext(SSLContext sslContext) {
-        this.sslContext = sslContext;
-        return this;
-    }
-
-    public HttpClientBuilder trustStore(KeyStore truststore) {
-        this.truststore = truststore;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = password;
-        return this;
-    }
-
-    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
-        this.clientKeyStore = keyStore;
-        this.clientPrivateKeyPassword = new String(password);
-        return this;
-    }
-
-
-    static class VerifierWrapper implements X509HostnameVerifier {
-        protected HostnameVerifier verifier;
-
-        VerifierWrapper(HostnameVerifier verifier) {
-            this.verifier = verifier;
-        }
-
-        @Override
-        public void verify(String host, SSLSocket ssl) throws IOException {
-            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
-        }
-
-        @Override
-        public void verify(String host, X509Certificate cert) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
-            throw new SSLException("This verification path not implemented");
-        }
-
-        @Override
-        public boolean verify(String s, SSLSession sslSession) {
-            return verifier.verify(s, sslSession);
-        }
-    }
-
-    public HttpClient build() {
-        X509HostnameVerifier verifier = null;
-        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
-        else {
-            switch (policy) {
-                case ANY:
-                    verifier = new AllowAllHostnameVerifier();
-                    break;
-                case WILDCARD:
-                    verifier = new BrowserCompatHostnameVerifier();
-                    break;
-                case STRICT:
-                    verifier = new StrictHostnameVerifier();
-                    break;
-            }
-        }
-        try {
-            SSLSocketFactory sslsf = null;
-            SSLContext theContext = sslContext;
-            if (disableTrustManager) {
-                theContext = SSLContext.getInstance("SSL");
-                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
-                        new SecureRandom());
-                verifier = new AllowAllHostnameVerifier();
-                sslsf = new SSLSocketFactory(theContext, verifier);
-            } else if (theContext != null) {
-                sslsf = new SSLSocketFactory(theContext, verifier);
-            } else if (clientKeyStore != null || truststore != null) {
-                sslsf = new SSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
-            } else {
-                final SSLContext tlsContext = SSLContext.getInstance(SSLSocketFactory.TLS);
-                tlsContext.init(null, null, null);
-                sslsf = new SSLSocketFactory(tlsContext, verifier);
-            }
-            SchemeRegistry registry = new SchemeRegistry();
-            registry.register(
-                    new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
-            Scheme httpsScheme = new Scheme("https", 443, sslsf);
-            registry.register(httpsScheme);
-            ClientConnectionManager cm = null;
-            if (connectionPoolSize > 0) {
-                ThreadSafeClientConnManager tcm = new ThreadSafeClientConnManager(registry, connectionTTL, connectionTTLUnit);
-                tcm.setMaxTotal(connectionPoolSize);
-                if (maxPooledPerRoute == 0) maxPooledPerRoute = connectionPoolSize;
-                tcm.setDefaultMaxPerRoute(maxPooledPerRoute);
-                cm = tcm;
-
-            } else {
-                cm = new SingleClientConnManager(registry);
-            }
-            BasicHttpParams params = new BasicHttpParams();
-            if (socketTimeout > -1)
-            {
-                HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
-
-            }
-            if (establishConnectionTimeout > -1)
-            {
-                HttpConnectionParams.setConnectionTimeout(params, (int)establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
-            }
-            return new DefaultHttpClient(cm, params);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public HttpClient build(AdapterConfig adapterConfig) {
-        String truststorePath = adapterConfig.getTruststore();
-        if (truststorePath != null) {
-            truststorePath = EnvUtil.replace(truststorePath);
-            String truststorePassword = adapterConfig.getTruststorePassword();
-            try {
-                this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);
-            } catch (Exception e) {
-                throw new RuntimeException("Failed to load truststore", e);
-            }
-        }
-        String clientKeystore = adapterConfig.getClientKeystore();
-        if (clientKeystore != null) {
-            clientKeystore = EnvUtil.replace(clientKeystore);
-            String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
-            try {
-                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
-                keyStore(clientCertKeystore, clientKeystorePassword);
-            } catch (Exception e) {
-                throw new RuntimeException("Failed to load keystore", e);
-            }
-        }
-        int size = 10;
-        if (adapterConfig.getConnectionPoolSize() > 0)
-            size = adapterConfig.getConnectionPoolSize();
-        HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;
-        if (adapterConfig.isAllowAnyHostname())
-            policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;
-        connectionPoolSize(size);
-        hostnameVerification(policy);
-        if (adapterConfig.isDisableTrustManager()) {
-            disableTrustManager();
-        } else {
-            trustStore(truststore);
-        }
-        return build();
-    }
+package org.keycloak.services.util;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.SingleClientConnManager;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.util.EnvUtil;
+import org.keycloak.util.KeystoreUtil;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Abstraction for creating HttpClients. Allows SSL configuration.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HttpClientBuilder {
+    public static enum HostnameVerificationPolicy {
+        /**
+         * Hostname verification is not done on the server's certificate
+         */
+        ANY,
+        /**
+         * Allows wildcards in subdomain names i.e. *.foo.com
+         */
+        WILDCARD,
+        /**
+         * CN must match hostname connecting to
+         */
+        STRICT
+    }
+
+
+    /**
+     * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+     * @version $Revision: 1 $
+     */
+    private static class PassthroughTrustManager implements X509TrustManager {
+        public void checkClientTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain,
+                                       String authType) throws CertificateException {
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+
+    protected KeyStore truststore;
+    protected KeyStore clientKeyStore;
+    protected String clientPrivateKeyPassword;
+    protected boolean disableTrustManager;
+    protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
+    protected SSLContext sslContext;
+    protected int connectionPoolSize = 100;
+    protected int maxPooledPerRoute = 0;
+    protected long connectionTTL = -1;
+    protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
+    protected HostnameVerifier verifier = null;
+    protected long socketTimeout = -1;
+    protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
+    protected long establishConnectionTimeout = -1;
+    protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
+
+
+    /**
+     * Socket inactivity timeout
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
+    {
+        this.socketTimeout = timeout;
+        this.socketTimeoutUnits = unit;
+        return this;
+    }
+
+    /**
+     * When trying to make an initial socket connection, what is the timeout?
+     *
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
+    {
+        this.establishConnectionTimeout = timeout;
+        this.establishConnectionTimeoutUnits = unit;
+        return this;
+    }
+
+    public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
+        this.connectionTTL = ttl;
+        this.connectionTTLUnit = unit;
+        return this;
+    }
+
+    public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
+        this.maxPooledPerRoute = maxPooledPerRoute;
+        return this;
+    }
+
+    public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
+        this.connectionPoolSize = connectionPoolSize;
+        return this;
+    }
+
+    /**
+     * Disable trust management and hostname verification. <i>NOTE</i> this is a security
+     * hole, so only set this option if you cannot or do not want to verify the identity of the
+     * host you are communicating with.
+     */
+    public HttpClientBuilder disableTrustManager() {
+        this.disableTrustManager = true;
+        return this;
+    }
+
+    /**
+     * SSL policy used to verify hostnames
+     *
+     * @param policy
+     * @return
+     */
+    public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
+        this.policy = policy;
+        return this;
+    }
+
+
+    public HttpClientBuilder sslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+        return this;
+    }
+
+    public HttpClientBuilder trustStore(KeyStore truststore) {
+        this.truststore = truststore;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = password;
+        return this;
+    }
+
+    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
+        this.clientKeyStore = keyStore;
+        this.clientPrivateKeyPassword = new String(password);
+        return this;
+    }
+
+
+    static class VerifierWrapper implements X509HostnameVerifier {
+        protected HostnameVerifier verifier;
+
+        VerifierWrapper(HostnameVerifier verifier) {
+            this.verifier = verifier;
+        }
+
+        @Override
+        public void verify(String host, SSLSocket ssl) throws IOException {
+            if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
+        }
+
+        @Override
+        public void verify(String host, X509Certificate cert) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
+            throw new SSLException("This verification path not implemented");
+        }
+
+        @Override
+        public boolean verify(String s, SSLSession sslSession) {
+            return verifier.verify(s, sslSession);
+        }
+    }
+
+    public HttpClient build() {
+        X509HostnameVerifier verifier = null;
+        if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
+        else {
+            switch (policy) {
+                case ANY:
+                    verifier = new AllowAllHostnameVerifier();
+                    break;
+                case WILDCARD:
+                    verifier = new BrowserCompatHostnameVerifier();
+                    break;
+                case STRICT:
+                    verifier = new StrictHostnameVerifier();
+                    break;
+            }
+        }
+        try {
+            SSLSocketFactory sslsf = null;
+            SSLContext theContext = sslContext;
+            if (disableTrustManager) {
+                theContext = SSLContext.getInstance("SSL");
+                theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
+                        new SecureRandom());
+                verifier = new AllowAllHostnameVerifier();
+                sslsf = new SSLSocketFactory(theContext, verifier);
+            } else if (theContext != null) {
+                sslsf = new SSLSocketFactory(theContext, verifier);
+            } else if (clientKeyStore != null || truststore != null) {
+                sslsf = new SSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
+            } else {
+                final SSLContext tlsContext = SSLContext.getInstance(SSLSocketFactory.TLS);
+                tlsContext.init(null, null, null);
+                sslsf = new SSLSocketFactory(tlsContext, verifier);
+            }
+            SchemeRegistry registry = new SchemeRegistry();
+            registry.register(
+                    new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+            Scheme httpsScheme = new Scheme("https", 443, sslsf);
+            registry.register(httpsScheme);
+            ClientConnectionManager cm = null;
+            if (connectionPoolSize > 0) {
+                ThreadSafeClientConnManager tcm = new ThreadSafeClientConnManager(registry, connectionTTL, connectionTTLUnit);
+                tcm.setMaxTotal(connectionPoolSize);
+                if (maxPooledPerRoute == 0) maxPooledPerRoute = connectionPoolSize;
+                tcm.setDefaultMaxPerRoute(maxPooledPerRoute);
+                cm = tcm;
+
+            } else {
+                cm = new SingleClientConnManager(registry);
+            }
+            BasicHttpParams params = new BasicHttpParams();
+            if (socketTimeout > -1)
+            {
+                HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
+
+            }
+            if (establishConnectionTimeout > -1)
+            {
+                HttpConnectionParams.setConnectionTimeout(params, (int)establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
+            }
+            return new DefaultHttpClient(cm, params);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public HttpClient build(AdapterConfig adapterConfig) {
+        String truststorePath = adapterConfig.getTruststore();
+        if (truststorePath != null) {
+            truststorePath = EnvUtil.replace(truststorePath);
+            String truststorePassword = adapterConfig.getTruststorePassword();
+            try {
+                this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load truststore", e);
+            }
+        }
+        String clientKeystore = adapterConfig.getClientKeystore();
+        if (clientKeystore != null) {
+            clientKeystore = EnvUtil.replace(clientKeystore);
+            String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
+            try {
+                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
+                keyStore(clientCertKeystore, clientKeystorePassword);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to load keystore", e);
+            }
+        }
+        int size = 10;
+        if (adapterConfig.getConnectionPoolSize() > 0)
+            size = adapterConfig.getConnectionPoolSize();
+        HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;
+        if (adapterConfig.isAllowAnyHostname())
+            policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;
+        connectionPoolSize(size);
+        hostnameVerification(policy);
+        if (adapterConfig.isDisableTrustManager()) {
+            disableTrustManager();
+        } else {
+            trustStore(truststore);
+        }
+        return build();
+    }
 }
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/util/ResolveRelative.java b/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
index 7833f21..0954f73 100755
--- a/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
+++ b/services/src/main/java/org/keycloak/services/util/ResolveRelative.java
@@ -1,20 +1,20 @@
-package org.keycloak.services.util;
-
-import javax.ws.rs.core.UriBuilder;
-import java.net.URI;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ResolveRelative {
-    public static String resolveRelativeUri(URI requestUri, String url) {
-        if (url == null || !url.startsWith("/")) return url;
-        UriBuilder builder = UriBuilder.fromPath(url).host(requestUri.getHost());
-        builder.scheme(requestUri.getScheme());
-        if (requestUri.getPort() != -1) {
-            builder.port(requestUri.getPort());
-        }
-        return builder.build().toString();
-    }
-}
+package org.keycloak.services.util;
+
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ResolveRelative {
+    public static String resolveRelativeUri(URI requestUri, String url) {
+        if (url == null || !url.startsWith("/")) return url;
+        UriBuilder builder = UriBuilder.fromPath(url).host(requestUri.getHost());
+        builder.scheme(requestUri.getScheme());
+        if (requestUri.getPort() != -1) {
+            builder.port(requestUri.getPort());
+        }
+        return builder.build().toString();
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/validation/Validation.java b/services/src/main/java/org/keycloak/services/validation/Validation.java
index 40e667d..d3abc4d 100755
--- a/services/src/main/java/org/keycloak/services/validation/Validation.java
+++ b/services/src/main/java/org/keycloak/services/validation/Validation.java
@@ -1,134 +1,134 @@
-package org.keycloak.services.validation;
-
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.FormMessage;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.messages.Messages;
-
-import javax.ws.rs.core.MultivaluedMap;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
-
-public class Validation {
-
-    public static final String FIELD_PASSWORD_CONFIRM = "password-confirm";
-    public static final String FIELD_EMAIL = "email";
-    public static final String FIELD_LAST_NAME = "lastName";
-    public static final String FIELD_FIRST_NAME = "firstName";
-    public static final String FIELD_PASSWORD = "password";
-    public static final String FIELD_USERNAME = "username";
-    
-    // Actually allow same emails like angular. See ValidationTest.testEmailValidation()
-    private static final Pattern EMAIL_PATTERN = Pattern.compile("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*");
-
-    public static List<FormMessage> validateRegistrationForm(RealmModel realm, MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes, PasswordPolicy policy) {
-        List<FormMessage> errors = new ArrayList<>();
-
-        if (!realm.isRegistrationEmailAsUsername() && isBlank(formData.getFirst(FIELD_USERNAME))) {
-            addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
-            addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
-            addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_EMAIL))) {
-            addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
-        } else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
-            addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
-        }
-
-        if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) {
-            if (isBlank(formData.getFirst(FIELD_PASSWORD))) {
-                addError(errors, FIELD_PASSWORD, Messages.MISSING_PASSWORD);
-            } else if (!formData.getFirst(FIELD_PASSWORD).equals(formData.getFirst(FIELD_PASSWORD_CONFIRM))) {
-                addError(errors, FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM);
-            }
-        }
-
-        if (formData.getFirst(FIELD_PASSWORD) != null) {
-            PasswordPolicy.Error err = policy.validate(realm.isRegistrationEmailAsUsername()?formData.getFirst(FIELD_EMAIL):formData.getFirst(FIELD_USERNAME), formData.getFirst(FIELD_PASSWORD));
-            if (err != null)
-                errors.add(new FormMessage(FIELD_PASSWORD, err.getMessage(), err.getParameters()));
-        }
-        
-        return errors;
-    }
-    
-    private static void addError(List<FormMessage> errors, String field, String message){
-        errors.add(new FormMessage(field, message));
-    }
-
-    public static List<FormMessage> validateUpdateProfileForm(MultivaluedMap<String, String> formData) {
-        return validateUpdateProfileForm(null, formData);
-    }
-
-    public static List<FormMessage> validateUpdateProfileForm(RealmModel realm, MultivaluedMap<String, String> formData) {
-        List<FormMessage> errors = new ArrayList<>();
-        
-        if (realm != null && realm.isEditUsernameAllowed() && isBlank(formData.getFirst(FIELD_USERNAME))) {
-            addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
-            addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
-            addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
-        }
-
-        if (isBlank(formData.getFirst(FIELD_EMAIL))) {
-            addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
-        } else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
-            addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
-        }
-
-        return errors;
-    }
-    
-    /**
-     * Validate if user object contains all mandatory fields.
-     * 
-     * @param realm user is for
-     * @param user to validate
-     * @return true if user object contains all mandatory values, false if some mandatory value is missing
-     */
-    public static boolean validateUserMandatoryFields(RealmModel realm, UserModel user){
-        return!(isBlank(user.getFirstName()) || isBlank(user.getLastName()) || isBlank(user.getEmail()));        
-    }
-
-    /**
-     * Check if string is empty (null or lenght is 0)
-     * 
-     * @param s to check
-     * @return true if string is empty
-     */
-    public static boolean isEmpty(String s) {
-        return s == null || s.length() == 0;
-    }
-    
-    /**
-     * Check if string is blank (null or lenght is 0 or contains only white characters)
-     * 
-     * @param s to check
-     * @return true if string is blank
-     */
-    public static boolean isBlank(String s) {
-        return s == null || s.trim().length() == 0;
-    }
-
-    public static boolean isEmailValid(String email) {
-        return EMAIL_PATTERN.matcher(email).matches();
-    }
-
-
-}
+package org.keycloak.services.validation;
+
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.FormMessage;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.messages.Messages;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class Validation {
+
+    public static final String FIELD_PASSWORD_CONFIRM = "password-confirm";
+    public static final String FIELD_EMAIL = "email";
+    public static final String FIELD_LAST_NAME = "lastName";
+    public static final String FIELD_FIRST_NAME = "firstName";
+    public static final String FIELD_PASSWORD = "password";
+    public static final String FIELD_USERNAME = "username";
+    
+    // Actually allow same emails like angular. See ValidationTest.testEmailValidation()
+    private static final Pattern EMAIL_PATTERN = Pattern.compile("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*");
+
+    public static List<FormMessage> validateRegistrationForm(RealmModel realm, MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes, PasswordPolicy policy) {
+        List<FormMessage> errors = new ArrayList<>();
+
+        if (!realm.isRegistrationEmailAsUsername() && isBlank(formData.getFirst(FIELD_USERNAME))) {
+            addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
+            addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
+            addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_EMAIL))) {
+            addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
+        } else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
+            addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
+        }
+
+        if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) {
+            if (isBlank(formData.getFirst(FIELD_PASSWORD))) {
+                addError(errors, FIELD_PASSWORD, Messages.MISSING_PASSWORD);
+            } else if (!formData.getFirst(FIELD_PASSWORD).equals(formData.getFirst(FIELD_PASSWORD_CONFIRM))) {
+                addError(errors, FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM);
+            }
+        }
+
+        if (formData.getFirst(FIELD_PASSWORD) != null) {
+            PasswordPolicy.Error err = policy.validate(realm.isRegistrationEmailAsUsername()?formData.getFirst(FIELD_EMAIL):formData.getFirst(FIELD_USERNAME), formData.getFirst(FIELD_PASSWORD));
+            if (err != null)
+                errors.add(new FormMessage(FIELD_PASSWORD, err.getMessage(), err.getParameters()));
+        }
+        
+        return errors;
+    }
+    
+    private static void addError(List<FormMessage> errors, String field, String message){
+        errors.add(new FormMessage(field, message));
+    }
+
+    public static List<FormMessage> validateUpdateProfileForm(MultivaluedMap<String, String> formData) {
+        return validateUpdateProfileForm(null, formData);
+    }
+
+    public static List<FormMessage> validateUpdateProfileForm(RealmModel realm, MultivaluedMap<String, String> formData) {
+        List<FormMessage> errors = new ArrayList<>();
+        
+        if (realm != null && realm.isEditUsernameAllowed() && isBlank(formData.getFirst(FIELD_USERNAME))) {
+            addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
+            addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
+            addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
+        }
+
+        if (isBlank(formData.getFirst(FIELD_EMAIL))) {
+            addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
+        } else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
+            addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
+        }
+
+        return errors;
+    }
+    
+    /**
+     * Validate if user object contains all mandatory fields.
+     * 
+     * @param realm user is for
+     * @param user to validate
+     * @return true if user object contains all mandatory values, false if some mandatory value is missing
+     */
+    public static boolean validateUserMandatoryFields(RealmModel realm, UserModel user){
+        return!(isBlank(user.getFirstName()) || isBlank(user.getLastName()) || isBlank(user.getEmail()));        
+    }
+
+    /**
+     * Check if string is empty (null or lenght is 0)
+     * 
+     * @param s to check
+     * @return true if string is empty
+     */
+    public static boolean isEmpty(String s) {
+        return s == null || s.length() == 0;
+    }
+    
+    /**
+     * Check if string is blank (null or lenght is 0 or contains only white characters)
+     * 
+     * @param s to check
+     * @return true if string is blank
+     */
+    public static boolean isBlank(String s) {
+        return s == null || s.trim().length() == 0;
+    }
+
+    public static boolean isEmailValid(String email) {
+        return EMAIL_PATTERN.matcher(email).matches();
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java b/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
index ed9021f..b9b0116 100755
--- a/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
@@ -1,12 +1,12 @@
-package org.keycloak.wellknown;
-
-import org.keycloak.provider.Provider;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public interface WellKnownProvider extends Provider {
-
-    Object getConfig();
-
-}
+package org.keycloak.wellknown;
+
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface WellKnownProvider extends Provider {
+
+    Object getConfig();
+
+}
diff --git a/services/src/main/java/org/keycloak/wellknown/WellKnownProviderFactory.java b/services/src/main/java/org/keycloak/wellknown/WellKnownProviderFactory.java
index 21d8b81..ea201f9 100755
--- a/services/src/main/java/org/keycloak/wellknown/WellKnownProviderFactory.java
+++ b/services/src/main/java/org/keycloak/wellknown/WellKnownProviderFactory.java
@@ -1,10 +1,10 @@
-package org.keycloak.wellknown;
-
-import org.keycloak.provider.ProviderFactory;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public interface WellKnownProviderFactory extends ProviderFactory<WellKnownProvider> {
-
-}
+package org.keycloak.wellknown;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface WellKnownProviderFactory extends ProviderFactory<WellKnownProvider> {
+
+}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
index d4d03d0..409e84b 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
@@ -1,4 +1,4 @@
-org.keycloak.authentication.authenticators.CookieAuthenticatorFactory
-org.keycloak.authentication.authenticators.UsernamePasswordFormFactory
-org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory
-org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory
+org.keycloak.authentication.authenticators.CookieAuthenticatorFactory
+org.keycloak.authentication.authenticators.UsernamePasswordFormFactory
+org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory
+org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.authentication.FormActionFactory b/services/src/main/resources/META-INF/services/org.keycloak.authentication.FormActionFactory
index b0240f3..03a9669 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.authentication.FormActionFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.authentication.FormActionFactory
@@ -1,4 +1,4 @@
-org.keycloak.authentication.forms.RegistrationPassword
-org.keycloak.authentication.forms.RegistrationProfile
-org.keycloak.authentication.forms.RegistrationUserCreation
+org.keycloak.authentication.forms.RegistrationPassword
+org.keycloak.authentication.forms.RegistrationProfile
+org.keycloak.authentication.forms.RegistrationUserCreation
 org.keycloak.authentication.forms.RegistrationRecaptcha
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.authentication.RequiredActionFactory b/services/src/main/resources/META-INF/services/org.keycloak.authentication.RequiredActionFactory
index a72fdd9..c5d250d 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.authentication.RequiredActionFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.authentication.RequiredActionFactory
@@ -1,5 +1,5 @@
-org.keycloak.authentication.requiredactions.UpdatePassword
-org.keycloak.authentication.requiredactions.UpdateProfile
-org.keycloak.authentication.requiredactions.UpdateTotp
-org.keycloak.authentication.requiredactions.VerifyEmail
+org.keycloak.authentication.requiredactions.UpdatePassword
+org.keycloak.authentication.requiredactions.UpdateProfile
+org.keycloak.authentication.requiredactions.UpdateTotp
+org.keycloak.authentication.requiredactions.VerifyEmail
 org.keycloak.authentication.requiredactions.TermsAndConditions
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
index 4ea322a..e7a6450 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
+++ b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -1,10 +1,10 @@
-org.keycloak.protocol.oidc.mappers.UserAttributeMapper
-org.keycloak.protocol.oidc.mappers.FullNameMapper
-org.keycloak.protocol.oidc.mappers.UserPropertyMapper
-org.keycloak.protocol.oidc.mappers.AddressMapper
-org.keycloak.protocol.oidc.mappers.HardcodedClaim
-org.keycloak.protocol.oidc.mappers.HardcodedRole
-org.keycloak.protocol.oidc.mappers.RoleNameMapper
-org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper
-
-
+org.keycloak.protocol.oidc.mappers.UserAttributeMapper
+org.keycloak.protocol.oidc.mappers.FullNameMapper
+org.keycloak.protocol.oidc.mappers.UserPropertyMapper
+org.keycloak.protocol.oidc.mappers.AddressMapper
+org.keycloak.protocol.oidc.mappers.HardcodedClaim
+org.keycloak.protocol.oidc.mappers.HardcodedRole
+org.keycloak.protocol.oidc.mappers.RoleNameMapper
+org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper
+
+
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 43d8d10..f937b4e 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,9 +1,9 @@
-org.keycloak.protocol.LoginProtocolSpi
-org.keycloak.protocol.ProtocolMapperSpi
-org.keycloak.exportimport.ClientImportSpi
-org.keycloak.wellknown.WellKnownSpi
-org.keycloak.messages.MessagesSpi
-org.keycloak.authentication.AuthenticatorSpi
-org.keycloak.authentication.RequiredActionSpi
-org.keycloak.authentication.FormAuthenticatorSpi
-org.keycloak.authentication.FormActionSpi
+org.keycloak.protocol.LoginProtocolSpi
+org.keycloak.protocol.ProtocolMapperSpi
+org.keycloak.exportimport.ClientImportSpi
+org.keycloak.wellknown.WellKnownSpi
+org.keycloak.messages.MessagesSpi
+org.keycloak.authentication.AuthenticatorSpi
+org.keycloak.authentication.RequiredActionSpi
+org.keycloak.authentication.FormAuthenticatorSpi
+org.keycloak.authentication.FormActionSpi
diff --git a/services/src/test/java/org/keycloak/test/RealmKeyGenerator.java b/services/src/test/java/org/keycloak/test/RealmKeyGenerator.java
index 0603153..c238895 100755
--- a/services/src/test/java/org/keycloak/test/RealmKeyGenerator.java
+++ b/services/src/test/java/org/keycloak/test/RealmKeyGenerator.java
@@ -1,47 +1,47 @@
-package org.keycloak.test;
-
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMWriter;
-import org.keycloak.util.PemUtils;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmKeyGenerator {
-    static {
-        if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
-    }
-    public static void main(String[] args) throws Exception {
-        KeyPair keyPair = null;
-        try {
-            keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-
-        System.out.println("privateKey : " + printKey(keyPair.getPrivate()));
-        System.out.println("publicKey : " + printKey(keyPair.getPublic()));
-    }
-
-    private static String printKey(Object key){
-        StringWriter writer = new StringWriter();
-        PEMWriter pemWriter = new PEMWriter(writer);
-        try {
-            pemWriter.writeObject(key);
-            pemWriter.flush();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        String s = writer.toString();
-        return PemUtils.removeBeginEnd(s);
-
-    }
-}
+package org.keycloak.test;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMWriter;
+import org.keycloak.util.PemUtils;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmKeyGenerator {
+    static {
+        if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
+    }
+    public static void main(String[] args) throws Exception {
+        KeyPair keyPair = null;
+        try {
+            keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+
+        System.out.println("privateKey : " + printKey(keyPair.getPrivate()));
+        System.out.println("publicKey : " + printKey(keyPair.getPublic()));
+    }
+
+    private static String printKey(Object key){
+        StringWriter writer = new StringWriter();
+        PEMWriter pemWriter = new PEMWriter(writer);
+        try {
+            pemWriter.writeObject(key);
+            pemWriter.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        String s = writer.toString();
+        return PemUtils.removeBeginEnd(s);
+
+    }
+}

social/core/pom.xml 76(+38 -38)

diff --git a/social/core/pom.xml b/social/core/pom.xml
index 0cfc94a..09e2ff3 100755
--- a/social/core/pom.xml
+++ b/social/core/pom.xml
@@ -1,38 +1,38 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-social-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-social-core</artifactId>
-    <name>Keycloak Social Core</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-social-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-social-core</artifactId>
+    <name>Keycloak Social Core</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookIdentityProvider.java b/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookIdentityProvider.java
index 2c06212..3a6b25b 100755
--- a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookIdentityProvider.java
+++ b/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookIdentityProvider.java
@@ -1,79 +1,79 @@
-package org.keycloak.social.facebook;
-
-import org.codehaus.jackson.JsonNode;
-import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
-import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
-import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
-import org.keycloak.broker.oidc.util.JsonSimpleHttp;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.broker.provider.util.SimpleHttp;
-import org.keycloak.social.SocialIdentityProvider;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class FacebookIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {
-
-	public static final String AUTH_URL = "https://graph.facebook.com/oauth/authorize";
-	public static final String TOKEN_URL = "https://graph.facebook.com/oauth/access_token";
-	public static final String PROFILE_URL = "https://graph.facebook.com/me";
-	public static final String DEFAULT_SCOPE = "email";
-
-	public FacebookIdentityProvider(OAuth2IdentityProviderConfig config) {
-		super(config);
-		config.setAuthorizationUrl(AUTH_URL);
-		config.setTokenUrl(TOKEN_URL);
-		config.setUserInfoUrl(PROFILE_URL);
-	}
-
-	protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
-		try {
-			JsonNode profile = JsonSimpleHttp.asJson(SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken));
-
-			String id = getJsonProperty(profile, "id");
-
-			BrokeredIdentityContext user = new BrokeredIdentityContext(id);
-
-			String email = getJsonProperty(profile, "email");
-
-			user.setEmail(email);
-
-			String username = getJsonProperty(profile, "username");
-
-			if (username == null) {
-				if (email != null) {
-					username = email;
-				} else {
-					username = id;
-				}
-			}
-
-			user.setUsername(username);
-
-			String firstName = getJsonProperty(profile, "first_name");
-			String lastName = getJsonProperty(profile, "last_name");
-
-			if (lastName == null) {
-				lastName = "";
-			} else {
-				lastName = " " + lastName;
-			}
-
-			user.setName(firstName + lastName);
-			user.setIdpConfig(getConfig());
-			user.setIdp(this);
-
-			AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
-
-			return user;
-		} catch (Exception e) {
-			throw new IdentityBrokerException("Could not obtain user profile from facebook.", e);
-		}
-	}
-
-	@Override
-	protected String getDefaultScopes() {
-		return DEFAULT_SCOPE;
-	}
-}
+package org.keycloak.social.facebook;
+
+import org.codehaus.jackson.JsonNode;
+import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
+import org.keycloak.broker.oidc.util.JsonSimpleHttp;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.provider.util.SimpleHttp;
+import org.keycloak.social.SocialIdentityProvider;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class FacebookIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {
+
+	public static final String AUTH_URL = "https://graph.facebook.com/oauth/authorize";
+	public static final String TOKEN_URL = "https://graph.facebook.com/oauth/access_token";
+	public static final String PROFILE_URL = "https://graph.facebook.com/me";
+	public static final String DEFAULT_SCOPE = "email";
+
+	public FacebookIdentityProvider(OAuth2IdentityProviderConfig config) {
+		super(config);
+		config.setAuthorizationUrl(AUTH_URL);
+		config.setTokenUrl(TOKEN_URL);
+		config.setUserInfoUrl(PROFILE_URL);
+	}
+
+	protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
+		try {
+			JsonNode profile = JsonSimpleHttp.asJson(SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken));
+
+			String id = getJsonProperty(profile, "id");
+
+			BrokeredIdentityContext user = new BrokeredIdentityContext(id);
+
+			String email = getJsonProperty(profile, "email");
+
+			user.setEmail(email);
+
+			String username = getJsonProperty(profile, "username");
+
+			if (username == null) {
+				if (email != null) {
+					username = email;
+				} else {
+					username = id;
+				}
+			}
+
+			user.setUsername(username);
+
+			String firstName = getJsonProperty(profile, "first_name");
+			String lastName = getJsonProperty(profile, "last_name");
+
+			if (lastName == null) {
+				lastName = "";
+			} else {
+				lastName = " " + lastName;
+			}
+
+			user.setName(firstName + lastName);
+			user.setIdpConfig(getConfig());
+			user.setIdp(this);
+
+			AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
+
+			return user;
+		} catch (Exception e) {
+			throw new IdentityBrokerException("Could not obtain user profile from facebook.", e);
+		}
+	}
+
+	@Override
+	protected String getDefaultScopes() {
+		return DEFAULT_SCOPE;
+	}
+}
diff --git a/social/github/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java b/social/github/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java
index b89d3b9..1dde106 100755
--- a/social/github/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java
+++ b/social/github/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java
@@ -1,56 +1,56 @@
-package org.keycloak.social.github;
-
-import org.codehaus.jackson.JsonNode;
-import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
-import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
-import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
-import org.keycloak.broker.oidc.util.JsonSimpleHttp;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.broker.provider.util.SimpleHttp;
-import org.keycloak.social.SocialIdentityProvider;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class GitHubIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {
-
-	public static final String AUTH_URL = "https://github.com/login/oauth/authorize";
-	public static final String TOKEN_URL = "https://github.com/login/oauth/access_token";
-	public static final String PROFILE_URL = "https://api.github.com/user";
-	public static final String DEFAULT_SCOPE = "user:email";
-
-	public GitHubIdentityProvider(OAuth2IdentityProviderConfig config) {
-		super(config);
-		config.setAuthorizationUrl(AUTH_URL);
-		config.setTokenUrl(TOKEN_URL);
-		config.setUserInfoUrl(PROFILE_URL);
-	}
-
-	@Override
-	protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
-		try {
-			JsonNode profile = JsonSimpleHttp.asJson(SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken));
-
-			BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(profile, "id"));
-
-			String username = getJsonProperty(profile, "login");
-			user.setUsername(username);
-			user.setName(getJsonProperty(profile, "name"));
-			user.setEmail(getJsonProperty(profile, "email"));
-			user.setIdpConfig(getConfig());
-			user.setIdp(this);
-
-			AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
-
-			return user;
-		} catch (Exception e) {
-			throw new IdentityBrokerException("Could not obtain user profile from github.", e);
-		}
-	}
-
-	@Override
-	protected String getDefaultScopes() {
-		return DEFAULT_SCOPE;
-	}
-}
+package org.keycloak.social.github;
+
+import org.codehaus.jackson.JsonNode;
+import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
+import org.keycloak.broker.oidc.util.JsonSimpleHttp;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.provider.util.SimpleHttp;
+import org.keycloak.social.SocialIdentityProvider;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class GitHubIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {
+
+	public static final String AUTH_URL = "https://github.com/login/oauth/authorize";
+	public static final String TOKEN_URL = "https://github.com/login/oauth/access_token";
+	public static final String PROFILE_URL = "https://api.github.com/user";
+	public static final String DEFAULT_SCOPE = "user:email";
+
+	public GitHubIdentityProvider(OAuth2IdentityProviderConfig config) {
+		super(config);
+		config.setAuthorizationUrl(AUTH_URL);
+		config.setTokenUrl(TOKEN_URL);
+		config.setUserInfoUrl(PROFILE_URL);
+	}
+
+	@Override
+	protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
+		try {
+			JsonNode profile = JsonSimpleHttp.asJson(SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken));
+
+			BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(profile, "id"));
+
+			String username = getJsonProperty(profile, "login");
+			user.setUsername(username);
+			user.setName(getJsonProperty(profile, "name"));
+			user.setEmail(getJsonProperty(profile, "email"));
+			user.setIdpConfig(getConfig());
+			user.setIdp(this);
+
+			AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
+
+			return user;
+		} catch (Exception e) {
+			throw new IdentityBrokerException("Could not obtain user profile from github.", e);
+		}
+	}
+
+	@Override
+	protected String getDefaultScopes() {
+		return DEFAULT_SCOPE;
+	}
+}

social/google/pom.xml 76(+38 -38)

diff --git a/social/google/pom.xml b/social/google/pom.xml
index 2a9f40e..04fb2c0 100755
--- a/social/google/pom.xml
+++ b/social/google/pom.xml
@@ -1,38 +1,38 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-social-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-social-google</artifactId>
-    <name>Keycloak Social Google</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-oidc</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-social-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-social-google</artifactId>
+    <name>Keycloak Social Google</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-oidc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

social/pom.xml 54(+27 -27)

diff --git a/social/pom.xml b/social/pom.xml
index ab75ead..aa95799 100755
--- a/social/pom.xml
+++ b/social/pom.xml
@@ -1,27 +1,27 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-social-parent</artifactId>
-    <name>Keycloak Social Parent</name>
-    <description/>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>core</module>
-        <module>github</module>
-        <module>google</module>
-        <module>twitter</module>
-        <module>facebook</module>
-        <module>linkedin</module>
-        <module>stackoverflow</module>
-    </modules>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-social-parent</artifactId>
+    <name>Keycloak Social Parent</name>
+    <description/>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>core</module>
+        <module>github</module>
+        <module>google</module>
+        <module>twitter</module>
+        <module>facebook</module>
+        <module>linkedin</module>
+        <module>stackoverflow</module>
+    </modules>
+
+</project>

social/twitter/pom.xml 108(+54 -54)

diff --git a/social/twitter/pom.xml b/social/twitter/pom.xml
index b2bc524..35fc5d2 100755
--- a/social/twitter/pom.xml
+++ b/social/twitter/pom.xml
@@ -1,54 +1,54 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-social-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-social-twitter</artifactId>
-    <name>Keycloak Social Twitter</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-social-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-broker-oidc</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-events-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-services</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.twitter4j</groupId>
-            <artifactId>twitter4j-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-social-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-social-twitter</artifactId>
+    <name>Keycloak Social Twitter</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-oidc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-events-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.twitter4j</groupId>
+            <artifactId>twitter4j-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index cd7c98d..7d02e50 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -1,551 +1,551 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-integration</artifactId>
-    <name>Keycloak Integration TestSuite</name>
-    <description />
-
-    <dependencies>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>async-http-servlet-3.0</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-kerberos-federation</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-undertow-adapter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jaxrs-oauth-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>federation-properties-example</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-
-        <!-- Apache DS -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-util-embedded-ldap</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-wildfly-common</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <inherited>true</inherited>
-                <extensions>true</extensions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                            <classpathScope>test</classpathScope>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                            <classpathScope>test</classpathScope>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                            <classpathScope>test</classpathScope>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>ldap</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.util.ldap.LDAPEmbeddedServer</mainClass>
-                            <classpathScope>test</classpathScope>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>kerberos</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.util.ldap.KerberosEmbeddedServer</mainClass>
-                            <classpathScope>test</classpathScope>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventsStore.provider>jpa</keycloak.eventsStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-
-                                <keycloak.liquibase.logging.level>debug</keycloak.liquibase.logging.level>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>file</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <excludes>
-                                <exclude>**/broker/***</exclude>
-                                <exclude>**/CacheTest.java</exclude>
-                            </excludes>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>file</keycloak.realm.provider>
-                                <keycloak.user.provider>file</keycloak.user.provider>
-                                <keycloak.realm.cache.provider>none</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>none</keycloak.user.cache.provider>
-                                <jboss.server.data.dir>${project.build.directory}</jboss.server.data.dir>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.eventsStore.provider>mongo</keycloak.eventsStore.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-integration</artifactId>
+    <name>Keycloak Integration TestSuite</name>
+    <description />
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>async-http-servlet-3.0</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-kerberos-federation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-undertow-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jaxrs-oauth-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>federation-properties-example</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+
+        <!-- Apache DS -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-util-embedded-ldap</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.picketlink</groupId>
+            <artifactId>picketlink-wildfly-common</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <extensions>true</extensions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                            <classpathScope>test</classpathScope>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                            <classpathScope>test</classpathScope>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                            <classpathScope>test</classpathScope>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>ldap</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.util.ldap.LDAPEmbeddedServer</mainClass>
+                            <classpathScope>test</classpathScope>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>kerberos</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.util.ldap.KerberosEmbeddedServer</mainClass>
+                            <classpathScope>test</classpathScope>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventsStore.provider>jpa</keycloak.eventsStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+
+                                <keycloak.liquibase.logging.level>debug</keycloak.liquibase.logging.level>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>file</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <excludes>
+                                <exclude>**/broker/***</exclude>
+                                <exclude>**/CacheTest.java</exclude>
+                            </excludes>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>file</keycloak.realm.provider>
+                                <keycloak.user.provider>file</keycloak.user.provider>
+                                <keycloak.realm.cache.provider>none</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>none</keycloak.user.cache.provider>
+                                <jboss.server.data.dir>${project.build.directory}</jboss.server.data.dir>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.eventsStore.provider>mongo</keycloak.eventsStore.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index 1ea081f..7faacda 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -1,683 +1,683 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.account;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.events.Details;
-import org.keycloak.events.Event;
-import org.keycloak.events.EventType;
-import org.keycloak.migration.MigrationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.TimeBasedOTP;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.AccountService;
-import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.testsuite.AssertEvents;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.AccountApplicationsPage;
-import org.keycloak.testsuite.pages.AccountLogPage;
-import org.keycloak.testsuite.pages.AccountPasswordPage;
-import org.keycloak.testsuite.pages.AccountSessionsPage;
-import org.keycloak.testsuite.pages.AccountTotpPage;
-import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
-import org.keycloak.testsuite.pages.AppPage;
-import org.keycloak.testsuite.pages.AppPage.RequestType;
-import org.keycloak.testsuite.pages.ErrorPage;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.pages.RegisterPage;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-
-import javax.ws.rs.core.UriBuilder;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class AccountTest {
-
-    @ClassRule
-    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() {
-        @Override
-        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
-
-            ClientModel accountApp = appRealm.getClientNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-
-            UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost");
-            user2.setEnabled(true);
-            user2.setEmail("test-user-no-access@localhost");
-            for (String r : accountApp.getDefaultRoles()) {
-                user2.deleteRoleMapping(accountApp.getRole(r));
-            }
-            UserCredentialModel creds = new UserCredentialModel();
-            creds.setType(CredentialRepresentation.PASSWORD);
-            creds.setValue("password");
-            user2.updateCredential(creds);
-        }
-    });
-
-    private static final UriBuilder BASE = UriBuilder.fromUri("http://localhost:8081/auth");
-    private static final String ACCOUNT_URL = RealmsResource.accountUrl(BASE.clone()).build("test").toString();
-    public static String ACCOUNT_REDIRECT = AccountService.loginRedirectUrl(BASE.clone()).build("test").toString();
-
-    @Rule
-    public AssertEvents events = new AssertEvents(keycloakRule);
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @WebResource
-    protected OAuthClient oauth;
-
-    @WebResource
-    protected AppPage appPage;
-
-    @WebResource
-    protected LoginPage loginPage;
-
-    @WebResource
-    protected RegisterPage registerPage;
-
-    @WebResource
-    protected AccountPasswordPage changePasswordPage;
-
-    @WebResource
-    protected AccountUpdateProfilePage profilePage;
-
-    @WebResource
-    protected AccountTotpPage totpPage;
-
-    @WebResource
-    protected AccountLogPage logPage;
-
-    @WebResource
-    protected AccountSessionsPage sessionsPage;
-
-    @WebResource
-    protected AccountApplicationsPage applicationsPage;
-
-    @WebResource
-    protected ErrorPage errorPage;
-
-    private TimeBasedOTP totp = new TimeBasedOTP();
-    private String userId;
-
-    @Before
-    public void before() {
-        oauth.state("mystate"); // keycloak enforces that a state param has been sent by client
-        userId = keycloakRule.getUser("test", "test-user@localhost").getId();
-    }
-
-    @After
-    public void after() {
-        keycloakRule.update(new KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
-                UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
-                user.setFirstName("Tom");
-                user.setLastName("Brady");
-                user.setEmail("test-user@localhost");
-
-                UserCredentialModel cred = new UserCredentialModel();
-                cred.setType(CredentialRepresentation.PASSWORD);
-                cred.setValue("password");
-
-                user.updateCredential(cred);
-            }
-        });
-    }
-
-    //@Test
-    public void ideTesting() throws Exception {
-        Thread.sleep(100000000);
-    }
-
-    @Test
-    public void testMigrationModel() {
-        KeycloakSession keycloakSession = keycloakRule.startSession();
-        Assert.assertEquals(keycloakSession.realms().getMigrationModel().getStoredVersion(), MigrationModel.LATEST_VERSION);
-        keycloakSession.close();
-    }
-
-
-
-    @Test
-    public void returnToAppFromQueryParam() {
-        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
-        loginPage.login("test-user@localhost", "password");
-        Assert.assertTrue(profilePage.isCurrent());
-        profilePage.backToApplication();
-
-        Assert.assertTrue(appPage.isCurrent());
-
-        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app&referrer_uri=http://localhost:8081/app?test");
-        Assert.assertTrue(profilePage.isCurrent());
-        profilePage.backToApplication();
-
-        Assert.assertTrue(appPage.isCurrent());
-        Assert.assertEquals(appPage.baseUrl + "?test", driver.getCurrentUrl());
-
-        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
-        Assert.assertTrue(profilePage.isCurrent());
-
-        driver.findElement(By.linkText("Authenticator")).click();
-        Assert.assertTrue(totpPage.isCurrent());
-
-        driver.findElement(By.linkText("Account")).click();
-        Assert.assertTrue(profilePage.isCurrent());
-
-        profilePage.backToApplication();
-
-        Assert.assertTrue(appPage.isCurrent());
-
-        events.clear();
-    }
-
-    @Test
-    public void changePassword() {
-        changePasswordPage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        Event event = events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
-        String sessionId = event.getSessionId();
-        String userId = event.getUserId();
-        changePasswordPage.changePassword("", "new-password", "new-password");
-
-        Assert.assertEquals("Please specify password.", profilePage.getError());
-
-        changePasswordPage.changePassword("password", "new-password", "new-password2");
-
-        Assert.assertEquals("Password confirmation doesn't match.", profilePage.getError());
-
-        changePasswordPage.changePassword("password", "new-password", "new-password");
-
-        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
-        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
-
-        changePasswordPage.logout();
-
-        events.expectLogout(sessionId).detail(Details.REDIRECT_URI, changePasswordPage.getPath()).assertEvent();
-
-        loginPage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        Assert.assertEquals("Invalid username or password.", loginPage.getError());
-
-        events.expectLogin().session((String) null).error("invalid_user_credentials")
-                .removeDetail(Details.CONSENT)
-                .assertEvent();
-
-        loginPage.open();
-        loginPage.login("test-user@localhost", "new-password");
-
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        events.expectLogin().assertEvent();
-    }
-
-    @Test
-    public void changePasswordWithLengthPasswordPolicy() {
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setPasswordPolicy(new PasswordPolicy("length"));
-            }
-        });
-
-        try {
-            changePasswordPage.open();
-            loginPage.login("test-user@localhost", "password");
-
-
-            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
-
-            changePasswordPage.changePassword("", "new", "new");
-
-            Assert.assertEquals("Please specify password.", profilePage.getError());
-
-            changePasswordPage.changePassword("password", "new-password", "new-password");
-
-            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
-            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
-        } finally {
-            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-                @Override
-                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.setPasswordPolicy(new PasswordPolicy(null));
-                }
-            });
-        }
-    }
-    
-    @Test
-    public void changePasswordWithPasswordHistoryPolicy() {
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setPasswordPolicy(new PasswordPolicy("passwordHistory(2)"));
-            }
-        });
-
-        try {
-            changePasswordPage.open();
-            loginPage.login("test-user@localhost", "password");
-
-            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
-
-            changePasswordPage.changePassword("password", "password", "password");
-
-            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
-
-            changePasswordPage.changePassword("password", "password1", "password1");
-
-            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-            
-            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
-            
-            changePasswordPage.changePassword("password1", "password", "password");
-
-            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
-
-            changePasswordPage.changePassword("password1", "password1", "password1");
-
-            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
-            
-            changePasswordPage.changePassword("password1", "password2", "password2");
-
-            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
-
-            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
-            
-        } finally {
-            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-                @Override
-                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.setPasswordPolicy(new PasswordPolicy(null));
-                }
-            });
-        }
-    }
-
-    @Test
-    public void changeProfile() {
-        profilePage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
-
-        Assert.assertEquals("Tom", profilePage.getFirstName());
-        Assert.assertEquals("Brady", profilePage.getLastName());
-        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
-
-        // All fields are required, so there should be an error when something is missing.
-        profilePage.updateProfile("", "New last", "new@email.com");
-
-        Assert.assertEquals("Please specify first name.", profilePage.getError());
-        Assert.assertEquals("", profilePage.getFirstName());
-        Assert.assertEquals("New last", profilePage.getLastName());
-        Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-        events.assertEmpty();
-
-        profilePage.updateProfile("New first", "", "new@email.com");
-
-        Assert.assertEquals("Please specify last name.", profilePage.getError());
-        Assert.assertEquals("New first", profilePage.getFirstName());
-        Assert.assertEquals("", profilePage.getLastName());
-        Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-        events.assertEmpty();
-
-        profilePage.updateProfile("New first", "New last", "");
-
-        Assert.assertEquals("Please specify email.", profilePage.getError());
-        Assert.assertEquals("New first", profilePage.getFirstName());
-        Assert.assertEquals("New last", profilePage.getLastName());
-        Assert.assertEquals("", profilePage.getEmail());
-
-        events.assertEmpty();
-
-        profilePage.clickCancel();
-
-        Assert.assertEquals("Tom", profilePage.getFirstName());
-        Assert.assertEquals("Brady", profilePage.getLastName());
-        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
-
-        events.assertEmpty();
-
-        profilePage.updateProfile("New first", "New last", "new@email.com");
-
-        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
-        Assert.assertEquals("New first", profilePage.getFirstName());
-        Assert.assertEquals("New last", profilePage.getLastName());
-        Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
-        events.expectAccount(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com").assertEvent();
-
-        // reset user for other tests
-        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
-        events.clear();
-    }
-
-    @Test
-    public void changeUsername() {
-        // allow to edit the username in realm
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setEditUsernameAllowed(true);
-            }
-        });
-
-        try {
-            profilePage.open();
-            loginPage.login("test-user@localhost", "password");
-
-            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
-
-            Assert.assertEquals("test-user@localhost", profilePage.getUsername());
-            Assert.assertEquals("Tom", profilePage.getFirstName());
-            Assert.assertEquals("Brady", profilePage.getLastName());
-            Assert.assertEquals("test-user@localhost", profilePage.getEmail());
-
-            // All fields are required, so there should be an error when something is missing.
-            profilePage.updateProfile("", "New first", "New last", "new@email.com");
-
-            Assert.assertEquals("Please specify username.", profilePage.getError());
-            Assert.assertEquals("", profilePage.getUsername());
-            Assert.assertEquals("New first", profilePage.getFirstName());
-            Assert.assertEquals("New last", profilePage.getLastName());
-            Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-            events.assertEmpty();
-
-            // Change to the username already occupied by other user
-            profilePage.updateProfile("test-user-no-access@localhost", "New first", "New last", "new@email.com");
-
-            Assert.assertEquals("Username already exists.", profilePage.getError());
-            Assert.assertEquals("test-user-no-access@localhost", profilePage.getUsername());
-            Assert.assertEquals("New first", profilePage.getFirstName());
-            Assert.assertEquals("New last", profilePage.getLastName());
-            Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-            events.assertEmpty();
-
-            profilePage.updateProfile("test-user-new@localhost", "New first", "New last", "new@email.com");
-
-            Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
-            Assert.assertEquals("test-user-new@localhost", profilePage.getUsername());
-            Assert.assertEquals("New first", profilePage.getFirstName());
-            Assert.assertEquals("New last", profilePage.getLastName());
-            Assert.assertEquals("new@email.com", profilePage.getEmail());
-
-        } finally {
-            // reset user for other tests
-            profilePage.updateProfile("test-user@localhost", "Tom", "Brady", "test-user@localhost");
-            events.clear();
-
-            // reset realm
-            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-                @Override
-                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.setEditUsernameAllowed(false);
-                }
-            });
-        }
-    }
-
-    // KEYCLOAK-1534
-    @Test
-    public void changeEmailToExisting() {
-        profilePage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
-
-        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
-        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
-
-        // Change to the email, which some other user has
-        profilePage.updateProfile("New first", "New last", "test-user-no-access@localhost");
-
-        profilePage.assertCurrent();
-        Assert.assertEquals("Email already exists.", profilePage.getError());
-        Assert.assertEquals("New first", profilePage.getFirstName());
-        Assert.assertEquals("New last", profilePage.getLastName());
-        Assert.assertEquals("test-user-no-access@localhost", profilePage.getEmail());
-
-        events.assertEmpty();
-
-        // Change some other things, but not email
-        profilePage.updateProfile("New first", "New last", "test-user@localhost");
-
-        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
-        Assert.assertEquals("New first", profilePage.getFirstName());
-        Assert.assertEquals("New last", profilePage.getLastName());
-        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
-
-        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
-
-        // Change email and other things to original values
-        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
-        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
-    }
-
-    @Test
-    public void setupTotp() {
-        totpPage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=totp").assertEvent();
-
-        Assert.assertTrue(totpPage.isCurrent());
-
-        Assert.assertFalse(driver.getPageSource().contains("Remove Google"));
-
-        // Error with false code
-        totpPage.configure(totp.generate(totpPage.getTotpSecret() + "123"));
-
-        Assert.assertEquals("Invalid authenticator code.", profilePage.getError());
-
-        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
-
-        Assert.assertEquals("Mobile authenticator configured.", profilePage.getSuccess());
-
-        events.expectAccount(EventType.UPDATE_TOTP).assertEvent();
-
-        Assert.assertTrue(driver.getPageSource().contains("pficon-delete"));
-
-        totpPage.removeTotp();
-
-        events.expectAccount(EventType.REMOVE_TOTP).assertEvent();
-    }
-
-    @Test
-    public void changeProfileNoAccess() throws Exception {
-        profilePage.open();
-        loginPage.login("test-user-no-access@localhost", "password");
-
-        events.expectLogin().client("account").user(keycloakRule.getUser("test", "test-user-no-access@localhost").getId())
-                .detail(Details.USERNAME, "test-user-no-access@localhost")
-                .detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
-
-        Assert.assertTrue(errorPage.isCurrent());
-        Assert.assertEquals("No access", errorPage.getError());
-    }
-
-    @Test
-    public void viewLog() {
-        keycloakRule.update(new KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setEventsEnabled(true);
-            }
-        });
-
-        try {
-            List<Event> expectedEvents = new LinkedList<Event>();
-
-            loginPage.open();
-            loginPage.clickRegister();
-
-            registerPage.register("view", "log", "view-log@localhost", "view-log", "password", "password");
-
-            expectedEvents.add(events.poll());
-            expectedEvents.add(events.poll());
-
-            profilePage.open();
-            profilePage.updateProfile("view", "log2", "view-log@localhost");
-
-            expectedEvents.add(events.poll());
-
-            logPage.open();
-
-            Assert.assertTrue(logPage.isCurrent());
-
-            List<List<String>> actualEvents = logPage.getEvents();
-
-            Assert.assertEquals(expectedEvents.size(), actualEvents.size());
-
-            for (Event e : expectedEvents) {
-                boolean match = false;
-                for (List<String> a : logPage.getEvents()) {
-                    if (e.getType().toString().replace('_', ' ').toLowerCase().equals(a.get(1)) &&
-                            e.getIpAddress().equals(a.get(2)) &&
-                            e.getClientId().equals(a.get(3))) {
-                        match = true;
-                        break;
-                    }
-                }
-                if (!match) {
-                    Assert.fail("Event not found " + e.getType());
-                }
-            }
-        } finally {
-            keycloakRule.update(new KeycloakSetup() {
-                @Override
-                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.setEventsEnabled(false);
-                }
-            });
-        }
-    }
-
-    @Test
-    public void sessions() {
-        loginPage.open();
-        loginPage.clickRegister();
-
-        registerPage.register("view", "sessions", "view-sessions@localhost", "view-sessions", "password", "password");
-
-        Event registerEvent = events.expectRegister("view-sessions", "view-sessions@localhost").assertEvent();
-        String userId = registerEvent.getUserId();
-
-        events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
-
-        sessionsPage.open();
-
-        Assert.assertTrue(sessionsPage.isCurrent());
-
-        List<List<String>> sessions = sessionsPage.getSessions();
-        Assert.assertEquals(1, sessions.size());
-        Assert.assertEquals("127.0.0.1", sessions.get(0).get(0));
-
-        // Create second session
-        WebDriver driver2 = WebRule.createWebDriver();
-        try {
-            OAuthClient oauth2 = new OAuthClient(driver2);
-            oauth2.state("mystate");
-            oauth2.doLogin("view-sessions", "password");
-
-            Event login2Event = events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
-
-            sessionsPage.open();
-            sessions = sessionsPage.getSessions();
-            Assert.assertEquals(2, sessions.size());
-
-            sessionsPage.logoutAll();
-
-            events.expectLogout(registerEvent.getSessionId());
-            events.expectLogout(login2Event.getSessionId());
-        } finally {
-            driver2.close();
-        }
-    }
-
-    // More tests (including revoke) are in OAuthGrantTest
-    @Test
-    public void applications() {
-        applicationsPage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=applications").assertEvent();
-        Assert.assertTrue(applicationsPage.isCurrent());
-
-        Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
-        Assert.assertEquals(3, apps.size());
-
-        AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
-        Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
-        Assert.assertTrue(accountEntry.getRolesAvailable().contains("Manage account in Account"));
-        Assert.assertTrue(accountEntry.getRolesAvailable().contains("View profile in Account"));
-        Assert.assertEquals(1, accountEntry.getRolesGranted().size());
-        Assert.assertTrue(accountEntry.getRolesGranted().contains("Full Access"));
-        Assert.assertEquals(1, accountEntry.getProtocolMappersGranted().size());
-        Assert.assertTrue(accountEntry.getProtocolMappersGranted().contains("Full Access"));
-
-        AccountApplicationsPage.AppEntry testAppEntry = apps.get("test-app");
-        Assert.assertEquals(4, testAppEntry.getRolesAvailable().size());
-        Assert.assertTrue(testAppEntry.getRolesGranted().contains("Full Access"));
-        Assert.assertTrue(testAppEntry.getProtocolMappersGranted().contains("Full Access"));
-
-        AccountApplicationsPage.AppEntry thirdPartyEntry = apps.get("third-party");
-        Assert.assertEquals(2, thirdPartyEntry.getRolesAvailable().size());
-        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have User privileges"));
-        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have Customer User privileges in test-app"));
-        Assert.assertEquals(0, thirdPartyEntry.getRolesGranted().size());
-        Assert.assertEquals(0, thirdPartyEntry.getProtocolMappersGranted().size());
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.account;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventType;
+import org.keycloak.migration.MigrationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.TimeBasedOTP;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.AccountService;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
+import org.keycloak.testsuite.pages.AccountLogPage;
+import org.keycloak.testsuite.pages.AccountPasswordPage;
+import org.keycloak.testsuite.pages.AccountSessionsPage;
+import org.keycloak.testsuite.pages.AccountTotpPage;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.AppPage.RequestType;
+import org.keycloak.testsuite.pages.ErrorPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.RegisterPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+
+import javax.ws.rs.core.UriBuilder;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AccountTest {
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() {
+        @Override
+        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+            UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
+
+            ClientModel accountApp = appRealm.getClientNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+
+            UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost");
+            user2.setEnabled(true);
+            user2.setEmail("test-user-no-access@localhost");
+            for (String r : accountApp.getDefaultRoles()) {
+                user2.deleteRoleMapping(accountApp.getRole(r));
+            }
+            UserCredentialModel creds = new UserCredentialModel();
+            creds.setType(CredentialRepresentation.PASSWORD);
+            creds.setValue("password");
+            user2.updateCredential(creds);
+        }
+    });
+
+    private static final UriBuilder BASE = UriBuilder.fromUri("http://localhost:8081/auth");
+    private static final String ACCOUNT_URL = RealmsResource.accountUrl(BASE.clone()).build("test").toString();
+    public static String ACCOUNT_REDIRECT = AccountService.loginRedirectUrl(BASE.clone()).build("test").toString();
+
+    @Rule
+    public AssertEvents events = new AssertEvents(keycloakRule);
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected AppPage appPage;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @WebResource
+    protected RegisterPage registerPage;
+
+    @WebResource
+    protected AccountPasswordPage changePasswordPage;
+
+    @WebResource
+    protected AccountUpdateProfilePage profilePage;
+
+    @WebResource
+    protected AccountTotpPage totpPage;
+
+    @WebResource
+    protected AccountLogPage logPage;
+
+    @WebResource
+    protected AccountSessionsPage sessionsPage;
+
+    @WebResource
+    protected AccountApplicationsPage applicationsPage;
+
+    @WebResource
+    protected ErrorPage errorPage;
+
+    private TimeBasedOTP totp = new TimeBasedOTP();
+    private String userId;
+
+    @Before
+    public void before() {
+        oauth.state("mystate"); // keycloak enforces that a state param has been sent by client
+        userId = keycloakRule.getUser("test", "test-user@localhost").getId();
+    }
+
+    @After
+    public void after() {
+        keycloakRule.update(new KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
+                UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
+                user.setFirstName("Tom");
+                user.setLastName("Brady");
+                user.setEmail("test-user@localhost");
+
+                UserCredentialModel cred = new UserCredentialModel();
+                cred.setType(CredentialRepresentation.PASSWORD);
+                cred.setValue("password");
+
+                user.updateCredential(cred);
+            }
+        });
+    }
+
+    //@Test
+    public void ideTesting() throws Exception {
+        Thread.sleep(100000000);
+    }
+
+    @Test
+    public void testMigrationModel() {
+        KeycloakSession keycloakSession = keycloakRule.startSession();
+        Assert.assertEquals(keycloakSession.realms().getMigrationModel().getStoredVersion(), MigrationModel.LATEST_VERSION);
+        keycloakSession.close();
+    }
+
+
+
+    @Test
+    public void returnToAppFromQueryParam() {
+        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
+        loginPage.login("test-user@localhost", "password");
+        Assert.assertTrue(profilePage.isCurrent());
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+
+        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app&referrer_uri=http://localhost:8081/app?test");
+        Assert.assertTrue(profilePage.isCurrent());
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+        Assert.assertEquals(appPage.baseUrl + "?test", driver.getCurrentUrl());
+
+        driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
+        Assert.assertTrue(profilePage.isCurrent());
+
+        driver.findElement(By.linkText("Authenticator")).click();
+        Assert.assertTrue(totpPage.isCurrent());
+
+        driver.findElement(By.linkText("Account")).click();
+        Assert.assertTrue(profilePage.isCurrent());
+
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+
+        events.clear();
+    }
+
+    @Test
+    public void changePassword() {
+        changePasswordPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        Event event = events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+        String sessionId = event.getSessionId();
+        String userId = event.getUserId();
+        changePasswordPage.changePassword("", "new-password", "new-password");
+
+        Assert.assertEquals("Please specify password.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "new-password", "new-password2");
+
+        Assert.assertEquals("Password confirmation doesn't match.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "new-password", "new-password");
+
+        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+
+        changePasswordPage.logout();
+
+        events.expectLogout(sessionId).detail(Details.REDIRECT_URI, changePasswordPage.getPath()).assertEvent();
+
+        loginPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        Assert.assertEquals("Invalid username or password.", loginPage.getError());
+
+        events.expectLogin().session((String) null).error("invalid_user_credentials")
+                .removeDetail(Details.CONSENT)
+                .assertEvent();
+
+        loginPage.open();
+        loginPage.login("test-user@localhost", "new-password");
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectLogin().assertEvent();
+    }
+
+    @Test
+    public void changePasswordWithLengthPasswordPolicy() {
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setPasswordPolicy(new PasswordPolicy("length"));
+            }
+        });
+
+        try {
+            changePasswordPage.open();
+            loginPage.login("test-user@localhost", "password");
+
+
+            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+
+            changePasswordPage.changePassword("", "new", "new");
+
+            Assert.assertEquals("Please specify password.", profilePage.getError());
+
+            changePasswordPage.changePassword("password", "new-password", "new-password");
+
+            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+        } finally {
+            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setPasswordPolicy(new PasswordPolicy(null));
+                }
+            });
+        }
+    }
+    
+    @Test
+    public void changePasswordWithPasswordHistoryPolicy() {
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setPasswordPolicy(new PasswordPolicy("passwordHistory(2)"));
+            }
+        });
+
+        try {
+            changePasswordPage.open();
+            loginPage.login("test-user@localhost", "password");
+
+            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+
+            changePasswordPage.changePassword("password", "password", "password");
+
+            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+
+            changePasswordPage.changePassword("password", "password1", "password1");
+
+            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+            
+            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+            
+            changePasswordPage.changePassword("password1", "password", "password");
+
+            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+
+            changePasswordPage.changePassword("password1", "password1", "password1");
+
+            Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+            
+            changePasswordPage.changePassword("password1", "password2", "password2");
+
+            Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+            events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+            
+        } finally {
+            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setPasswordPolicy(new PasswordPolicy(null));
+                }
+            });
+        }
+    }
+
+    @Test
+    public void changeProfile() {
+        profilePage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertEquals("Tom", profilePage.getFirstName());
+        Assert.assertEquals("Brady", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        // All fields are required, so there should be an error when something is missing.
+        profilePage.updateProfile("", "New last", "new@email.com");
+
+        Assert.assertEquals("Please specify first name.", profilePage.getError());
+        Assert.assertEquals("", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "", "new@email.com");
+
+        Assert.assertEquals("Please specify last name.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "New last", "");
+
+        Assert.assertEquals("Please specify email.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.clickCancel();
+
+        Assert.assertEquals("Tom", profilePage.getFirstName());
+        Assert.assertEquals("Brady", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "New last", "new@email.com");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+        events.expectAccount(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com").assertEvent();
+
+        // reset user for other tests
+        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
+        events.clear();
+    }
+
+    @Test
+    public void changeUsername() {
+        // allow to edit the username in realm
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setEditUsernameAllowed(true);
+            }
+        });
+
+        try {
+            profilePage.open();
+            loginPage.login("test-user@localhost", "password");
+
+            events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+            Assert.assertEquals("test-user@localhost", profilePage.getUsername());
+            Assert.assertEquals("Tom", profilePage.getFirstName());
+            Assert.assertEquals("Brady", profilePage.getLastName());
+            Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+            // All fields are required, so there should be an error when something is missing.
+            profilePage.updateProfile("", "New first", "New last", "new@email.com");
+
+            Assert.assertEquals("Please specify username.", profilePage.getError());
+            Assert.assertEquals("", profilePage.getUsername());
+            Assert.assertEquals("New first", profilePage.getFirstName());
+            Assert.assertEquals("New last", profilePage.getLastName());
+            Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+            events.assertEmpty();
+
+            // Change to the username already occupied by other user
+            profilePage.updateProfile("test-user-no-access@localhost", "New first", "New last", "new@email.com");
+
+            Assert.assertEquals("Username already exists.", profilePage.getError());
+            Assert.assertEquals("test-user-no-access@localhost", profilePage.getUsername());
+            Assert.assertEquals("New first", profilePage.getFirstName());
+            Assert.assertEquals("New last", profilePage.getLastName());
+            Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+            events.assertEmpty();
+
+            profilePage.updateProfile("test-user-new@localhost", "New first", "New last", "new@email.com");
+
+            Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+            Assert.assertEquals("test-user-new@localhost", profilePage.getUsername());
+            Assert.assertEquals("New first", profilePage.getFirstName());
+            Assert.assertEquals("New last", profilePage.getLastName());
+            Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        } finally {
+            // reset user for other tests
+            profilePage.updateProfile("test-user@localhost", "Tom", "Brady", "test-user@localhost");
+            events.clear();
+
+            // reset realm
+            keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setEditUsernameAllowed(false);
+                }
+            });
+        }
+    }
+
+    // KEYCLOAK-1534
+    @Test
+    public void changeEmailToExisting() {
+        profilePage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        // Change to the email, which some other user has
+        profilePage.updateProfile("New first", "New last", "test-user-no-access@localhost");
+
+        profilePage.assertCurrent();
+        Assert.assertEquals("Email already exists.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("test-user-no-access@localhost", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        // Change some other things, but not email
+        profilePage.updateProfile("New first", "New last", "test-user@localhost");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+
+        // Change email and other things to original values
+        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+    }
+
+    @Test
+    public void setupTotp() {
+        totpPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=totp").assertEvent();
+
+        Assert.assertTrue(totpPage.isCurrent());
+
+        Assert.assertFalse(driver.getPageSource().contains("Remove Google"));
+
+        // Error with false code
+        totpPage.configure(totp.generate(totpPage.getTotpSecret() + "123"));
+
+        Assert.assertEquals("Invalid authenticator code.", profilePage.getError());
+
+        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
+
+        Assert.assertEquals("Mobile authenticator configured.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_TOTP).assertEvent();
+
+        Assert.assertTrue(driver.getPageSource().contains("pficon-delete"));
+
+        totpPage.removeTotp();
+
+        events.expectAccount(EventType.REMOVE_TOTP).assertEvent();
+    }
+
+    @Test
+    public void changeProfileNoAccess() throws Exception {
+        profilePage.open();
+        loginPage.login("test-user-no-access@localhost", "password");
+
+        events.expectLogin().client("account").user(keycloakRule.getUser("test", "test-user-no-access@localhost").getId())
+                .detail(Details.USERNAME, "test-user-no-access@localhost")
+                .detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertTrue(errorPage.isCurrent());
+        Assert.assertEquals("No access", errorPage.getError());
+    }
+
+    @Test
+    public void viewLog() {
+        keycloakRule.update(new KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setEventsEnabled(true);
+            }
+        });
+
+        try {
+            List<Event> expectedEvents = new LinkedList<Event>();
+
+            loginPage.open();
+            loginPage.clickRegister();
+
+            registerPage.register("view", "log", "view-log@localhost", "view-log", "password", "password");
+
+            expectedEvents.add(events.poll());
+            expectedEvents.add(events.poll());
+
+            profilePage.open();
+            profilePage.updateProfile("view", "log2", "view-log@localhost");
+
+            expectedEvents.add(events.poll());
+
+            logPage.open();
+
+            Assert.assertTrue(logPage.isCurrent());
+
+            List<List<String>> actualEvents = logPage.getEvents();
+
+            Assert.assertEquals(expectedEvents.size(), actualEvents.size());
+
+            for (Event e : expectedEvents) {
+                boolean match = false;
+                for (List<String> a : logPage.getEvents()) {
+                    if (e.getType().toString().replace('_', ' ').toLowerCase().equals(a.get(1)) &&
+                            e.getIpAddress().equals(a.get(2)) &&
+                            e.getClientId().equals(a.get(3))) {
+                        match = true;
+                        break;
+                    }
+                }
+                if (!match) {
+                    Assert.fail("Event not found " + e.getType());
+                }
+            }
+        } finally {
+            keycloakRule.update(new KeycloakSetup() {
+                @Override
+                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                    appRealm.setEventsEnabled(false);
+                }
+            });
+        }
+    }
+
+    @Test
+    public void sessions() {
+        loginPage.open();
+        loginPage.clickRegister();
+
+        registerPage.register("view", "sessions", "view-sessions@localhost", "view-sessions", "password", "password");
+
+        Event registerEvent = events.expectRegister("view-sessions", "view-sessions@localhost").assertEvent();
+        String userId = registerEvent.getUserId();
+
+        events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
+
+        sessionsPage.open();
+
+        Assert.assertTrue(sessionsPage.isCurrent());
+
+        List<List<String>> sessions = sessionsPage.getSessions();
+        Assert.assertEquals(1, sessions.size());
+        Assert.assertEquals("127.0.0.1", sessions.get(0).get(0));
+
+        // Create second session
+        WebDriver driver2 = WebRule.createWebDriver();
+        try {
+            OAuthClient oauth2 = new OAuthClient(driver2);
+            oauth2.state("mystate");
+            oauth2.doLogin("view-sessions", "password");
+
+            Event login2Event = events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
+
+            sessionsPage.open();
+            sessions = sessionsPage.getSessions();
+            Assert.assertEquals(2, sessions.size());
+
+            sessionsPage.logoutAll();
+
+            events.expectLogout(registerEvent.getSessionId());
+            events.expectLogout(login2Event.getSessionId());
+        } finally {
+            driver2.close();
+        }
+    }
+
+    // More tests (including revoke) are in OAuthGrantTest
+    @Test
+    public void applications() {
+        applicationsPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=applications").assertEvent();
+        Assert.assertTrue(applicationsPage.isCurrent());
+
+        Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
+        Assert.assertEquals(3, apps.size());
+
+        AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
+        Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
+        Assert.assertTrue(accountEntry.getRolesAvailable().contains("Manage account in Account"));
+        Assert.assertTrue(accountEntry.getRolesAvailable().contains("View profile in Account"));
+        Assert.assertEquals(1, accountEntry.getRolesGranted().size());
+        Assert.assertTrue(accountEntry.getRolesGranted().contains("Full Access"));
+        Assert.assertEquals(1, accountEntry.getProtocolMappersGranted().size());
+        Assert.assertTrue(accountEntry.getProtocolMappersGranted().contains("Full Access"));
+
+        AccountApplicationsPage.AppEntry testAppEntry = apps.get("test-app");
+        Assert.assertEquals(4, testAppEntry.getRolesAvailable().size());
+        Assert.assertTrue(testAppEntry.getRolesGranted().contains("Full Access"));
+        Assert.assertTrue(testAppEntry.getProtocolMappersGranted().contains("Full Access"));
+
+        AccountApplicationsPage.AppEntry thirdPartyEntry = apps.get("third-party");
+        Assert.assertEquals(2, thirdPartyEntry.getRolesAvailable().size());
+        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have User privileges"));
+        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have Customer User privileges in test-app"));
+        Assert.assertEquals(0, thirdPartyEntry.getRolesGranted().size());
+        Assert.assertEquals(0, thirdPartyEntry.getProtocolMappersGranted().size());
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index 3f3e453..5d02107 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -1,204 +1,204 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.adapter;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-
-import java.net.URL;
-import java.security.PublicKey;
-
-/**
- * Tests Undertow Adapter
- *
- * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
- */
-public class AdapterTest {
-
-    public static PublicKey realmPublicKey;
-    @ClassRule
-    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            RealmModel realm = AdapterTestStrategy.baseAdapterTestInitialization(session, manager, adminRealm, getClass());
-            realmPublicKey = realm.getPublicKey();
-
-            URL url = getClass().getResource("/adapter-test/cust-app-keycloak.json");
-            createApplicationDeployment()
-                    .name("customer-portal").contextPath("/customer-portal")
-                    .servletClass(CustomerServlet.class).adapterConfigPath(url.getPath())
-                    .role("user").deployApplication();
-
-            url = getClass().getResource("/adapter-test/secure-portal-keycloak.json");
-            createApplicationDeployment()
-                    .name("secure-portal").contextPath("/secure-portal")
-                    .servletClass(CallAuthenticatedServlet.class).adapterConfigPath(url.getPath())
-                    .role("user")
-                    .isConstrained(false).deployApplication();
-
-            url = getClass().getResource("/adapter-test/customer-db-keycloak.json");
-            createApplicationDeployment()
-                    .name("customer-db").contextPath("/customer-db")
-                    .servletClass(CustomerDatabaseServlet.class).adapterConfigPath(url.getPath())
-                    .role("user")
-                    .errorPage(null).deployApplication();
-
-            createApplicationDeployment()
-                    .name("customer-db-error-page").contextPath("/customer-db-error-page")
-                    .servletClass(CustomerDatabaseServlet.class).adapterConfigPath(url.getPath())
-                    .role("user").deployApplication();
-
-            url = getClass().getResource("/adapter-test/product-keycloak.json");
-            createApplicationDeployment()
-                    .name("product-portal").contextPath("/product-portal")
-                    .servletClass(ProductServlet.class).adapterConfigPath(url.getPath())
-                    .role("user").deployApplication();
-
-            // Test that replacing system properties works for adapters
-            System.setProperty("app.server.base.url", "http://localhost:8081");
-            System.setProperty("my.host.name", "localhost");
-            url = getClass().getResource("/adapter-test/session-keycloak.json");
-            createApplicationDeployment()
-                    .name("session-portal").contextPath("/session-portal")
-                    .servletClass(SessionServlet.class).adapterConfigPath(url.getPath())
-                    .role("user").deployApplication();
-
-            url = getClass().getResource("/adapter-test/input-keycloak.json");
-            createApplicationDeployment()
-                    .name("input-portal").contextPath("/input-portal")
-                    .servletClass(InputServlet.class).adapterConfigPath(url.getPath())
-                    .role("user").constraintUrl("/secured/*").deployApplication();
-        }
-    };
-
-    @Rule
-    public AdapterTestStrategy testStrategy = new AdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
-
-    @Test
-    public void testLoginSSOAndLogout() throws Exception {
-        testStrategy.testLoginSSOAndLogout();
-    }
-
-    @Test
-    public void testSavedPostRequest() throws Exception {
-        testStrategy.testSavedPostRequest();
-    }
-
-    @Test
-    public void testServletRequestLogout() throws Exception {
-        testStrategy.testServletRequestLogout();
-    }
-
-    @Test
-    public void testLoginSSOIdle() throws Exception {
-        testStrategy.testLoginSSOIdle();
-
-    }
-
-    @Test
-    public void testLoginSSOIdleRemoveExpiredUserSessions() throws Exception {
-        testStrategy.testLoginSSOIdleRemoveExpiredUserSessions();
-    }
-
-    @Test
-    public void testLoginSSOMax() throws Exception {
-        testStrategy.testLoginSSOMax();
-    }
-
-    /**
-     * KEYCLOAK-518
-     * @throws Exception
-     */
-    @Test
-    public void testNullBearerToken() throws Exception {
-        testStrategy.testNullBearerToken();
-    }
-
-    /**
-     * KEYCLOAK-1368
-     * @throws Exception
-     */
-    @Test
-    public void testNullBearerTokenCustomErrorPage() throws Exception {
-        testStrategy.testNullBearerTokenCustomErrorPage();
-    }
-
-    /**
-     * KEYCLOAK-518
-     * @throws Exception
-     */
-    @Test
-    public void testBadUser() throws Exception {
-        testStrategy.testBadUser();
-    }
-
-    @Test
-    public void testVersion() throws Exception {
-        testStrategy.testVersion();
-    }
-
-    @Test
-    public void testAuthenticated() throws Exception {
-        testStrategy.testAuthenticated();
-    }
-
-    /**
-     * KEYCLOAK-732
-     *
-     * @throws Throwable
-     */
-    @Test
-    public void testSingleSessionInvalidated() throws Throwable {
-        testStrategy.testSingleSessionInvalidated();
-    }
-
-    /**
-     * KEYCLOAK-741
-     */
-    @Test
-    public void testSessionInvalidatedAfterFailedRefresh() throws Throwable {
-        testStrategy.testSessionInvalidatedAfterFailedRefresh();
-
-    }
-
-    /**
-     * KEYCLOAK-942
-     */
-    @Test
-    public void testAdminApplicationLogout() throws Throwable {
-        testStrategy.testAdminApplicationLogout();
-    }
-
-    /**
-     * KEYCLOAK-1216
-     */
-    @Test
-    public void testAccountManagementSessionsLogout() throws Throwable {
-        testStrategy.testAccountManagementSessionsLogout();
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.adapter;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+
+import java.net.URL;
+import java.security.PublicKey;
+
+/**
+ * Tests Undertow Adapter
+ *
+ * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
+ */
+public class AdapterTest {
+
+    public static PublicKey realmPublicKey;
+    @ClassRule
+    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            RealmModel realm = AdapterTestStrategy.baseAdapterTestInitialization(session, manager, adminRealm, getClass());
+            realmPublicKey = realm.getPublicKey();
+
+            URL url = getClass().getResource("/adapter-test/cust-app-keycloak.json");
+            createApplicationDeployment()
+                    .name("customer-portal").contextPath("/customer-portal")
+                    .servletClass(CustomerServlet.class).adapterConfigPath(url.getPath())
+                    .role("user").deployApplication();
+
+            url = getClass().getResource("/adapter-test/secure-portal-keycloak.json");
+            createApplicationDeployment()
+                    .name("secure-portal").contextPath("/secure-portal")
+                    .servletClass(CallAuthenticatedServlet.class).adapterConfigPath(url.getPath())
+                    .role("user")
+                    .isConstrained(false).deployApplication();
+
+            url = getClass().getResource("/adapter-test/customer-db-keycloak.json");
+            createApplicationDeployment()
+                    .name("customer-db").contextPath("/customer-db")
+                    .servletClass(CustomerDatabaseServlet.class).adapterConfigPath(url.getPath())
+                    .role("user")
+                    .errorPage(null).deployApplication();
+
+            createApplicationDeployment()
+                    .name("customer-db-error-page").contextPath("/customer-db-error-page")
+                    .servletClass(CustomerDatabaseServlet.class).adapterConfigPath(url.getPath())
+                    .role("user").deployApplication();
+
+            url = getClass().getResource("/adapter-test/product-keycloak.json");
+            createApplicationDeployment()
+                    .name("product-portal").contextPath("/product-portal")
+                    .servletClass(ProductServlet.class).adapterConfigPath(url.getPath())
+                    .role("user").deployApplication();
+
+            // Test that replacing system properties works for adapters
+            System.setProperty("app.server.base.url", "http://localhost:8081");
+            System.setProperty("my.host.name", "localhost");
+            url = getClass().getResource("/adapter-test/session-keycloak.json");
+            createApplicationDeployment()
+                    .name("session-portal").contextPath("/session-portal")
+                    .servletClass(SessionServlet.class).adapterConfigPath(url.getPath())
+                    .role("user").deployApplication();
+
+            url = getClass().getResource("/adapter-test/input-keycloak.json");
+            createApplicationDeployment()
+                    .name("input-portal").contextPath("/input-portal")
+                    .servletClass(InputServlet.class).adapterConfigPath(url.getPath())
+                    .role("user").constraintUrl("/secured/*").deployApplication();
+        }
+    };
+
+    @Rule
+    public AdapterTestStrategy testStrategy = new AdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
+
+    @Test
+    public void testLoginSSOAndLogout() throws Exception {
+        testStrategy.testLoginSSOAndLogout();
+    }
+
+    @Test
+    public void testSavedPostRequest() throws Exception {
+        testStrategy.testSavedPostRequest();
+    }
+
+    @Test
+    public void testServletRequestLogout() throws Exception {
+        testStrategy.testServletRequestLogout();
+    }
+
+    @Test
+    public void testLoginSSOIdle() throws Exception {
+        testStrategy.testLoginSSOIdle();
+
+    }
+
+    @Test
+    public void testLoginSSOIdleRemoveExpiredUserSessions() throws Exception {
+        testStrategy.testLoginSSOIdleRemoveExpiredUserSessions();
+    }
+
+    @Test
+    public void testLoginSSOMax() throws Exception {
+        testStrategy.testLoginSSOMax();
+    }
+
+    /**
+     * KEYCLOAK-518
+     * @throws Exception
+     */
+    @Test
+    public void testNullBearerToken() throws Exception {
+        testStrategy.testNullBearerToken();
+    }
+
+    /**
+     * KEYCLOAK-1368
+     * @throws Exception
+     */
+    @Test
+    public void testNullBearerTokenCustomErrorPage() throws Exception {
+        testStrategy.testNullBearerTokenCustomErrorPage();
+    }
+
+    /**
+     * KEYCLOAK-518
+     * @throws Exception
+     */
+    @Test
+    public void testBadUser() throws Exception {
+        testStrategy.testBadUser();
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        testStrategy.testVersion();
+    }
+
+    @Test
+    public void testAuthenticated() throws Exception {
+        testStrategy.testAuthenticated();
+    }
+
+    /**
+     * KEYCLOAK-732
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSingleSessionInvalidated() throws Throwable {
+        testStrategy.testSingleSessionInvalidated();
+    }
+
+    /**
+     * KEYCLOAK-741
+     */
+    @Test
+    public void testSessionInvalidatedAfterFailedRefresh() throws Throwable {
+        testStrategy.testSessionInvalidatedAfterFailedRefresh();
+
+    }
+
+    /**
+     * KEYCLOAK-942
+     */
+    @Test
+    public void testAdminApplicationLogout() throws Throwable {
+        testStrategy.testAdminApplicationLogout();
+    }
+
+    /**
+     * KEYCLOAK-1216
+     */
+    @Test
+    public void testAccountManagementSessionsLogout() throws Throwable {
+        testStrategy.testAccountManagementSessionsLogout();
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CallAuthenticatedServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CallAuthenticatedServlet.java
index 53cba81..20b3618 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CallAuthenticatedServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CallAuthenticatedServlet.java
@@ -1,39 +1,39 @@
-package org.keycloak.testsuite.adapter;
-
-import org.junit.Assert;
-import org.keycloak.KeycloakSecurityContext;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CallAuthenticatedServlet extends HttpServlet {
-    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        if (!req.authenticate(resp)) {
-            return;
-        }
-
-        KeycloakSecurityContext sc = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
-        Assert.assertNotNull(sc);
-        resp.setContentType("text/html");
-        PrintWriter pw = resp.getWriter();
-        pw.printf("<html><head><title>%s</title></head><body>", "Customer Portal");
-        pw.println("Stian Thorgersen");
-        pw.println("Bill Burke");
-        pw.print("</body></html>");
-        pw.flush();
-
-
-
-    }
-}
+package org.keycloak.testsuite.adapter;
+
+import org.junit.Assert;
+import org.keycloak.KeycloakSecurityContext;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CallAuthenticatedServlet extends HttpServlet {
+    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        if (!req.authenticate(resp)) {
+            return;
+        }
+
+        KeycloakSecurityContext sc = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
+        Assert.assertNotNull(sc);
+        resp.setContentType("text/html");
+        PrintWriter pw = resp.getWriter();
+        pw.printf("<html><head><title>%s</title></head><body>", "Customer Portal");
+        pw.println("Stian Thorgersen");
+        pw.println("Bill Burke");
+        pw.print("</body></html>");
+        pw.flush();
+
+
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerDatabaseServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerDatabaseServlet.java
index c2f25ee..c4bc7e3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerDatabaseServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerDatabaseServlet.java
@@ -1,29 +1,29 @@
-package org.keycloak.testsuite.adapter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CustomerDatabaseServlet extends HttpServlet {
-    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        resp.setContentType("text/html");
-        PrintWriter pw = resp.getWriter();
-        pw.printf("<html><head><title>%s</title></head><body>", "Customer Portal");
-        pw.println("Stian Thorgersen");
-        pw.println("Bill Burke");
-        pw.print("</body></html>");
-        pw.flush();
-
-
-    }
-}
+package org.keycloak.testsuite.adapter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CustomerDatabaseServlet extends HttpServlet {
+    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/html");
+        PrintWriter pw = resp.getWriter();
+        pw.printf("<html><head><title>%s</title></head><body>", "Customer Portal");
+        pw.println("Stian Thorgersen");
+        pw.println("Bill Burke");
+        pw.print("</body></html>");
+        pw.flush();
+
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerServlet.java
index e7feeb9..9fa1a47 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CustomerServlet.java
@@ -1,59 +1,59 @@
-package org.keycloak.testsuite.adapter;
-
-import org.junit.Assert;
-import org.keycloak.KeycloakSecurityContext;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CustomerServlet extends HttpServlet {
-    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        PrintWriter pw = resp.getWriter();
-        if (req.getRequestURI().toString().endsWith("logout")) {
-            resp.setStatus(200);
-            pw.println("servlet logout ok");
-
-            // Call logout before pw.flush
-            req.logout();
-            pw.flush();
-            return;
-        }
-        KeycloakSecurityContext context = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
-        Client client = ClientBuilder.newClient();
-
-        try {
-            String appBase = System.getProperty("app.server.base.url", "http://localhost:8081");
-            WebTarget target = client.target(appBase + "/customer-db/");
-            Response response = target.request().get();
-            Assert.assertEquals(401, response.getStatus());
-            response.close();
-            String html = target.request()
-                                .header(HttpHeaders.AUTHORIZATION, "Bearer " + context.getTokenString())
-                                .get(String.class);
-            resp.setContentType("text/html");
-            pw.println(html);
-            pw.flush();
-        } finally {
-            client.close();
-        }
-
-
-    }
-}
+package org.keycloak.testsuite.adapter;
+
+import org.junit.Assert;
+import org.keycloak.KeycloakSecurityContext;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CustomerServlet extends HttpServlet {
+    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        PrintWriter pw = resp.getWriter();
+        if (req.getRequestURI().toString().endsWith("logout")) {
+            resp.setStatus(200);
+            pw.println("servlet logout ok");
+
+            // Call logout before pw.flush
+            req.logout();
+            pw.flush();
+            return;
+        }
+        KeycloakSecurityContext context = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName());
+        Client client = ClientBuilder.newClient();
+
+        try {
+            String appBase = System.getProperty("app.server.base.url", "http://localhost:8081");
+            WebTarget target = client.target(appBase + "/customer-db/");
+            Response response = target.request().get();
+            Assert.assertEquals(401, response.getStatus());
+            response.close();
+            String html = target.request()
+                                .header(HttpHeaders.AUTHORIZATION, "Bearer " + context.getTokenString())
+                                .get(String.class);
+            resp.setContentType("text/html");
+            pw.println(html);
+            pw.flush();
+        } finally {
+            client.close();
+        }
+
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputPage.java
index bd09991..f3b5b76 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/InputPage.java
@@ -1,35 +1,35 @@
-package org.keycloak.testsuite.adapter;
-
-import org.keycloak.testsuite.pages.AbstractPage;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class InputPage extends AbstractPage {
-    @FindBy(id = "parameter")
-    private WebElement parameter;
-
-    @FindBy(name = "submit")
-    private WebElement submit;
-
-    public void execute(String param) {
-        parameter.clear();
-        parameter.sendKeys(param);
-
-        submit.click();
-    }
-
-
-    public boolean isCurrent() {
-        return driver.getTitle().equals("Input Page");
-    }
-
-    @Override
-    public void open() {
-    }
-
-
-}
+package org.keycloak.testsuite.adapter;
+
+import org.keycloak.testsuite.pages.AbstractPage;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class InputPage extends AbstractPage {
+    @FindBy(id = "parameter")
+    private WebElement parameter;
+
+    @FindBy(name = "submit")
+    private WebElement submit;
+
+    public void execute(String param) {
+        parameter.clear();
+        parameter.sendKeys(param);
+
+        submit.click();
+    }
+
+
+    public boolean isCurrent() {
+        return driver.getTitle().equals("Input Page");
+    }
+
+    @Override
+    public void open() {
+    }
+
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/ProductServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/ProductServlet.java
index cd64959..c8de891 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/ProductServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/ProductServlet.java
@@ -1,29 +1,29 @@
-package org.keycloak.testsuite.adapter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class ProductServlet extends HttpServlet {
-    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        resp.setContentType("text/html");
-        PrintWriter pw = resp.getWriter();
-        pw.printf("<html><head><title>%s</title></head><body>", "Product Portal");
-        pw.println("iPhone");
-        pw.println("iPad");
-        pw.print("</body></html>");
-        pw.flush();
-
-
-    }
-}
+package org.keycloak.testsuite.adapter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ProductServlet extends HttpServlet {
+    private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/html");
+        PrintWriter pw = resp.getWriter();
+        pw.printf("<html><head><title>%s</title></head><body>", "Product Portal");
+        pw.println("iPhone");
+        pw.println("iPad");
+        pw.print("</body></html>");
+        pw.flush();
+
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/SessionServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/SessionServlet.java
index f9c5d0b..c7c4d85 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/SessionServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/SessionServlet.java
@@ -1,38 +1,38 @@
-package org.keycloak.testsuite.adapter;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class SessionServlet extends HttpServlet {
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        String counter = increaseAndGetCounter(req);
-
-        resp.setContentType("text/html");
-        PrintWriter pw = resp.getWriter();
-        pw.printf("<html><head><title>%s</title></head><body>", "Session Test");
-        pw.printf("Counter=%s", counter);
-        pw.print("</body></html>");
-        pw.flush();
-
-
-    }
-
-    private String increaseAndGetCounter(HttpServletRequest req) {
-        HttpSession session = req.getSession();
-        Integer counter = (Integer)session.getAttribute("counter");
-        counter = (counter == null) ? 1 : counter + 1;
-        session.setAttribute("counter", counter);
-        return String.valueOf(counter);
-    }
-}
+package org.keycloak.testsuite.adapter;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class SessionServlet extends HttpServlet {
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        String counter = increaseAndGetCounter(req);
+
+        resp.setContentType("text/html");
+        PrintWriter pw = resp.getWriter();
+        pw.printf("<html><head><title>%s</title></head><body>", "Session Test");
+        pw.printf("Counter=%s", counter);
+        pw.print("</body></html>");
+        pw.flush();
+
+
+    }
+
+    private String increaseAndGetCounter(HttpServletRequest req) {
+        HttpSession session = req.getSession();
+        Integer counter = (Integer)session.getAttribute("counter");
+        counter = (counter == null) ? 1 : counter + 1;
+        session.setAttribute("counter", counter);
+        return String.valueOf(counter);
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
index 48ac594..8b751e0 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
@@ -1,82 +1,82 @@
-package org.keycloak.testsuite.broker;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.pages.OAuthGrantPage;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author pedroigor
- */
-public class IdentityProviderHintTest {
-
-    @ClassRule
-    public static BrokerKeyCloakRule keycloakRule = new BrokerKeyCloakRule();
-
-    @ClassRule
-    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
-
-        @Override
-        protected void configureServer(KeycloakServer server) {
-            server.getConfig().setPort(8082);
-        }
-
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-kc-oidc.json"));
-        }
-
-        @Override
-        protected String[] getTestRealms() {
-            return new String[] { "realm-with-oidc-identity-provider" };
-        }
-    };
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    private WebDriver driver;
-
-    @WebResource
-    private LoginPage loginPage;
-
-    @WebResource
-    private OAuthGrantPage grantPage;
-
-    @Test
-    public void testSuccessfulRedirect() {
-        this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=kc-oidc-idp");
-
-        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
-
-        // log in to identity provider
-        this.loginPage.login("test-user", "password");
-
-         // authenticated and redirected to app
-        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
-        assertTrue(this.driver.getPageSource().contains("idToken"));
-    }
-
-    @Test
-    public void testInvalidIdentityProviderHint() {
-        this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=invalid-idp-id");
-
-        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
-
-        assertEquals("Could not find an identity provider with the identifier [invalid-idp-id].", this.driver.findElement(By.className("instruction")).getText());
-    }
-}
+package org.keycloak.testsuite.broker;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.testsuite.KeycloakServer;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author pedroigor
+ */
+public class IdentityProviderHintTest {
+
+    @ClassRule
+    public static BrokerKeyCloakRule keycloakRule = new BrokerKeyCloakRule();
+
+    @ClassRule
+    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
+
+        @Override
+        protected void configureServer(KeycloakServer server) {
+            server.getConfig().setPort(8082);
+        }
+
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-kc-oidc.json"));
+        }
+
+        @Override
+        protected String[] getTestRealms() {
+            return new String[] { "realm-with-oidc-identity-provider" };
+        }
+    };
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    private WebDriver driver;
+
+    @WebResource
+    private LoginPage loginPage;
+
+    @WebResource
+    private OAuthGrantPage grantPage;
+
+    @Test
+    public void testSuccessfulRedirect() {
+        this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=kc-oidc-idp");
+
+        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
+
+        // log in to identity provider
+        this.loginPage.login("test-user", "password");
+
+         // authenticated and redirected to app
+        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
+        assertTrue(this.driver.getPageSource().contains("idToken"));
+    }
+
+    @Test
+    public void testInvalidIdentityProviderHint() {
+        this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=invalid-idp-id");
+
+        assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
+
+        assertEquals("Could not find an identity provider with the identifier [invalid-idp-id].", this.driver.findElement(By.className("instruction")).getText());
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
index b2e3605..8914e7c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
@@ -1,324 +1,324 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Copyright 2013 Red Hat, Inc. and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.keycloak.testsuite.broker;
-
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.junit.Test;
-import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
-import org.keycloak.broker.oidc.OIDCIdentityProvider;
-import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
-import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
-import org.keycloak.broker.saml.SAMLIdentityProvider;
-import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
-import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.social.facebook.FacebookIdentityProvider;
-import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
-import org.keycloak.social.github.GitHubIdentityProvider;
-import org.keycloak.social.github.GitHubIdentityProviderFactory;
-import org.keycloak.social.google.GoogleIdentityProvider;
-import org.keycloak.social.google.GoogleIdentityProviderFactory;
-import org.keycloak.social.linkedin.LinkedInIdentityProvider;
-import org.keycloak.social.linkedin.LinkedInIdentityProviderFactory;
-import org.keycloak.social.stackoverflow.StackOverflowIdentityProviderConfig;
-import org.keycloak.social.stackoverflow.StackoverflowIdentityProvider;
-import org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory;
-import org.keycloak.social.twitter.TwitterIdentityProvider;
-import org.keycloak.social.twitter.TwitterIdentityProviderFactory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author pedroigor
- */
-public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTest {
-
-    @Test
-    public void testInstallation() throws Exception {
-        RealmModel realm = installTestRealm();
-
-        assertIdentityProviderConfig(realm.getIdentityProviders());
-
-        assertTrue(realm.isIdentityFederationEnabled());
-        this.realmManager.removeRealm(realm);
-    }
-
-    @Test
-    public void testUpdateIdentityProvider() throws Exception {
-        RealmModel realm = installTestRealm();
-        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
-
-        assertFalse(identityProviders.isEmpty());
-
-        IdentityProviderModel identityProviderModel = identityProviders.get(0);
-        String identityProviderId = identityProviderModel.getAlias();
-
-        identityProviderModel.getConfig().put("config-added", "value-added");
-        identityProviderModel.setEnabled(false);
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
-        identityProviderModel.setTrustEmail(true);
-        identityProviderModel.setStoreToken(true);
-        identityProviderModel.setAuthenticateByDefault(true);
-
-        realm.updateIdentityProvider(identityProviderModel);
-
-        commit();
-
-        realm = this.realmManager.getRealm(realm.getId());
-
-        identityProviderModel = realm.getIdentityProviderByAlias(identityProviderId);
-
-        assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
-        assertFalse(identityProviderModel.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, identityProviderModel.getUpdateProfileFirstLoginMode());
-        assertTrue(identityProviderModel.isTrustEmail());
-        assertTrue(identityProviderModel.isStoreToken());
-        assertTrue(identityProviderModel.isAuthenticateByDefault());
-
-        identityProviderModel.getConfig().remove("config-added");
-        identityProviderModel.setEnabled(true);
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
-        identityProviderModel.setTrustEmail(false);
-        identityProviderModel.setAuthenticateByDefault(false);
-
-        realm.updateIdentityProvider(identityProviderModel);
-
-        commit();
-
-        realm = this.realmManager.getRealm(realm.getId());
-        identityProviderModel = realm.getIdentityProviderByAlias(identityProviderId);
-
-        assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
-        assertTrue(identityProviderModel.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, identityProviderModel.getUpdateProfileFirstLoginMode());
-        assertFalse(identityProviderModel.isTrustEmail());
-        assertFalse(identityProviderModel.isAuthenticateByDefault());
-        this.realmManager.removeRealm(realm);
-    }
-
-    private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
-        assertFalse(identityProviders.isEmpty());
-
-        Set<String> checkedProviders = new HashSet<String>(getExpectedProviders());
-
-        for (IdentityProviderModel identityProvider : identityProviders) {
-            if (identityProvider.getAlias().startsWith("model-")) {
-                String providerId = identityProvider.getProviderId();
-
-                if (SAMLIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertSamlIdentityProviderConfig(identityProvider);
-                } else if (GoogleIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertGoogleIdentityProviderConfig(identityProvider);
-                } else if (OIDCIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertOidcIdentityProviderConfig(identityProvider);
-                } else if (FacebookIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertFacebookIdentityProviderConfig(identityProvider);
-                } else if (GitHubIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertGitHubIdentityProviderConfig(identityProvider);
-                } else if (TwitterIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertTwitterIdentityProviderConfig(identityProvider);
-                } else if (LinkedInIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertLinkedInIdentityProviderConfig(identityProvider);
-                } else if (StackoverflowIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
-                    assertStackoverflowIdentityProviderConfig(identityProvider);
-                } else {
-                    continue;
-                }
-
-                checkedProviders.remove(providerId);
-            }
-        }
-
-        assertTrue(checkedProviders.isEmpty());
-    }
-
-    private void assertGoogleIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        GoogleIdentityProvider googleIdentityProvider = new GoogleIdentityProviderFactory().create(identityProvider);
-        OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
-
-        assertEquals("model-google", config.getAlias());
-        assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
-        assertEquals(true, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(true, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-        assertEquals(GoogleIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-        assertEquals(GoogleIdentityProvider.TOKEN_URL, config.getTokenUrl());
-        assertEquals(GoogleIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
-
-    }
-
-    private void assertSamlIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        SAMLIdentityProvider samlIdentityProvider = new SAMLIdentityProviderFactory().create(identityProvider);
-        SAMLIdentityProviderConfig config = samlIdentityProvider.getConfig();
-
-        assertEquals("model-saml-signed-idp", config.getAlias());
-        assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isStoreToken());
-        assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl());
-        assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat());
-        assertEquals("MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin", config.getSigningCertificate());
-        assertEquals(true, config.isWantAuthnRequestsSigned());
-        assertEquals(true, config.isForceAuthn());
-        assertEquals(true, config.isPostBindingAuthnRequest());
-        assertEquals(true, config.isPostBindingResponse());
-        assertEquals(true, config.isValidateSignature());
-    }
-
-    private void assertOidcIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        OIDCIdentityProvider googleIdentityProvider = new OIDCIdentityProviderFactory().create(identityProvider);
-        OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
-
-        assertEquals("model-oidc-idp", config.getAlias());
-        assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(false, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(false, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-    }
-
-    private void assertFacebookIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        FacebookIdentityProvider facebookIdentityProvider = new FacebookIdentityProviderFactory().create(identityProvider);
-        OAuth2IdentityProviderConfig config = facebookIdentityProvider.getConfig();
-
-        assertEquals("model-facebook", config.getAlias());
-        assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(false, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-        assertEquals(FacebookIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-        assertEquals(FacebookIdentityProvider.TOKEN_URL, config.getTokenUrl());
-        assertEquals(FacebookIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
-    }
-
-    private void assertGitHubIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        GitHubIdentityProvider gitHubIdentityProvider = new GitHubIdentityProviderFactory().create(identityProvider);
-        OAuth2IdentityProviderConfig config = gitHubIdentityProvider.getConfig();
-
-        assertEquals("model-github", config.getAlias());
-        assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(false, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-        assertEquals(GitHubIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-        assertEquals(GitHubIdentityProvider.TOKEN_URL, config.getTokenUrl());
-        assertEquals(GitHubIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
-    }
-
-    private void assertLinkedInIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        LinkedInIdentityProvider liIdentityProvider = new LinkedInIdentityProviderFactory().create(identityProvider);
-        OAuth2IdentityProviderConfig config = liIdentityProvider.getConfig();
-
-        assertEquals("model-linkedin", config.getAlias());
-      assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-      assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-      assertEquals(false, config.isAuthenticateByDefault());
-      assertEquals(false, config.isStoreToken());
-      assertEquals("clientId", config.getClientId());
-      assertEquals("clientSecret", config.getClientSecret());
-      assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-      assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl());
-      assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
-    }
-
-    private void assertStackoverflowIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        StackoverflowIdentityProvider soIdentityProvider = new StackoverflowIdentityProviderFactory().create(identityProvider);
-        StackOverflowIdentityProviderConfig config = soIdentityProvider.getConfig();
-
-        assertEquals("model-stackoverflow", config.getAlias());
-        assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(false, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-        assertEquals("keyValue", config.getKey());
-        assertEquals(StackoverflowIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-        assertEquals(StackoverflowIdentityProvider.TOKEN_URL, config.getTokenUrl());
-        assertEquals(StackoverflowIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
-    }
-
-    private void assertTwitterIdentityProviderConfig(IdentityProviderModel identityProvider) {
-        TwitterIdentityProvider twitterIdentityProvider = new TwitterIdentityProviderFactory().create(identityProvider);
-        OAuth2IdentityProviderConfig config = twitterIdentityProvider.getConfig();
-
-        assertEquals("model-twitter", config.getAlias());
-        assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-        assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
-        assertEquals(false, config.isTrustEmail());
-        assertEquals(false, config.isAuthenticateByDefault());
-        assertEquals(true, config.isStoreToken());
-        assertEquals("clientId", config.getClientId());
-        assertEquals("clientSecret", config.getClientSecret());
-    }
-
-    private RealmModel installTestRealm() throws IOException {
-        RealmRepresentation realmRepresentation = loadJson("broker-test/test-realm-with-broker.json");
-
-        assertNotNull(realmRepresentation);
-        assertEquals("realm-with-broker", realmRepresentation.getRealm());
-
-        RealmModel realmModel = this.realmManager.getRealm("realm-with-broker");
-
-        if (realmModel == null) {
-            realmModel = this.realmManager.importRealm(realmRepresentation);
-
-            commit();
-
-            realmModel = this.realmManager.getRealm(realmModel.getId());
-
-            assertNotNull(realmModel);
-        }
-
-        return realmModel;
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.broker;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.oidc.OIDCIdentityProvider;
+import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
+import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
+import org.keycloak.broker.saml.SAMLIdentityProvider;
+import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
+import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.social.facebook.FacebookIdentityProvider;
+import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
+import org.keycloak.social.github.GitHubIdentityProvider;
+import org.keycloak.social.github.GitHubIdentityProviderFactory;
+import org.keycloak.social.google.GoogleIdentityProvider;
+import org.keycloak.social.google.GoogleIdentityProviderFactory;
+import org.keycloak.social.linkedin.LinkedInIdentityProvider;
+import org.keycloak.social.linkedin.LinkedInIdentityProviderFactory;
+import org.keycloak.social.stackoverflow.StackOverflowIdentityProviderConfig;
+import org.keycloak.social.stackoverflow.StackoverflowIdentityProvider;
+import org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory;
+import org.keycloak.social.twitter.TwitterIdentityProvider;
+import org.keycloak.social.twitter.TwitterIdentityProviderFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author pedroigor
+ */
+public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTest {
+
+    @Test
+    public void testInstallation() throws Exception {
+        RealmModel realm = installTestRealm();
+
+        assertIdentityProviderConfig(realm.getIdentityProviders());
+
+        assertTrue(realm.isIdentityFederationEnabled());
+        this.realmManager.removeRealm(realm);
+    }
+
+    @Test
+    public void testUpdateIdentityProvider() throws Exception {
+        RealmModel realm = installTestRealm();
+        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
+
+        assertFalse(identityProviders.isEmpty());
+
+        IdentityProviderModel identityProviderModel = identityProviders.get(0);
+        String identityProviderId = identityProviderModel.getAlias();
+
+        identityProviderModel.getConfig().put("config-added", "value-added");
+        identityProviderModel.setEnabled(false);
+        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+        identityProviderModel.setTrustEmail(true);
+        identityProviderModel.setStoreToken(true);
+        identityProviderModel.setAuthenticateByDefault(true);
+
+        realm.updateIdentityProvider(identityProviderModel);
+
+        commit();
+
+        realm = this.realmManager.getRealm(realm.getId());
+
+        identityProviderModel = realm.getIdentityProviderByAlias(identityProviderId);
+
+        assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
+        assertFalse(identityProviderModel.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, identityProviderModel.getUpdateProfileFirstLoginMode());
+        assertTrue(identityProviderModel.isTrustEmail());
+        assertTrue(identityProviderModel.isStoreToken());
+        assertTrue(identityProviderModel.isAuthenticateByDefault());
+
+        identityProviderModel.getConfig().remove("config-added");
+        identityProviderModel.setEnabled(true);
+        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
+        identityProviderModel.setTrustEmail(false);
+        identityProviderModel.setAuthenticateByDefault(false);
+
+        realm.updateIdentityProvider(identityProviderModel);
+
+        commit();
+
+        realm = this.realmManager.getRealm(realm.getId());
+        identityProviderModel = realm.getIdentityProviderByAlias(identityProviderId);
+
+        assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
+        assertTrue(identityProviderModel.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, identityProviderModel.getUpdateProfileFirstLoginMode());
+        assertFalse(identityProviderModel.isTrustEmail());
+        assertFalse(identityProviderModel.isAuthenticateByDefault());
+        this.realmManager.removeRealm(realm);
+    }
+
+    private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
+        assertFalse(identityProviders.isEmpty());
+
+        Set<String> checkedProviders = new HashSet<String>(getExpectedProviders());
+
+        for (IdentityProviderModel identityProvider : identityProviders) {
+            if (identityProvider.getAlias().startsWith("model-")) {
+                String providerId = identityProvider.getProviderId();
+
+                if (SAMLIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertSamlIdentityProviderConfig(identityProvider);
+                } else if (GoogleIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertGoogleIdentityProviderConfig(identityProvider);
+                } else if (OIDCIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertOidcIdentityProviderConfig(identityProvider);
+                } else if (FacebookIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertFacebookIdentityProviderConfig(identityProvider);
+                } else if (GitHubIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertGitHubIdentityProviderConfig(identityProvider);
+                } else if (TwitterIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertTwitterIdentityProviderConfig(identityProvider);
+                } else if (LinkedInIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertLinkedInIdentityProviderConfig(identityProvider);
+                } else if (StackoverflowIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
+                    assertStackoverflowIdentityProviderConfig(identityProvider);
+                } else {
+                    continue;
+                }
+
+                checkedProviders.remove(providerId);
+            }
+        }
+
+        assertTrue(checkedProviders.isEmpty());
+    }
+
+    private void assertGoogleIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        GoogleIdentityProvider googleIdentityProvider = new GoogleIdentityProviderFactory().create(identityProvider);
+        OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
+
+        assertEquals("model-google", config.getAlias());
+        assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
+        assertEquals(true, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(true, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+        assertEquals(GoogleIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+        assertEquals(GoogleIdentityProvider.TOKEN_URL, config.getTokenUrl());
+        assertEquals(GoogleIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+
+    }
+
+    private void assertSamlIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        SAMLIdentityProvider samlIdentityProvider = new SAMLIdentityProviderFactory().create(identityProvider);
+        SAMLIdentityProviderConfig config = samlIdentityProvider.getConfig();
+
+        assertEquals("model-saml-signed-idp", config.getAlias());
+        assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl());
+        assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat());
+        assertEquals("MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin", config.getSigningCertificate());
+        assertEquals(true, config.isWantAuthnRequestsSigned());
+        assertEquals(true, config.isForceAuthn());
+        assertEquals(true, config.isPostBindingAuthnRequest());
+        assertEquals(true, config.isPostBindingResponse());
+        assertEquals(true, config.isValidateSignature());
+    }
+
+    private void assertOidcIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        OIDCIdentityProvider googleIdentityProvider = new OIDCIdentityProviderFactory().create(identityProvider);
+        OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
+
+        assertEquals("model-oidc-idp", config.getAlias());
+        assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(false, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+    }
+
+    private void assertFacebookIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        FacebookIdentityProvider facebookIdentityProvider = new FacebookIdentityProviderFactory().create(identityProvider);
+        OAuth2IdentityProviderConfig config = facebookIdentityProvider.getConfig();
+
+        assertEquals("model-facebook", config.getAlias());
+        assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+        assertEquals(FacebookIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+        assertEquals(FacebookIdentityProvider.TOKEN_URL, config.getTokenUrl());
+        assertEquals(FacebookIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+    }
+
+    private void assertGitHubIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        GitHubIdentityProvider gitHubIdentityProvider = new GitHubIdentityProviderFactory().create(identityProvider);
+        OAuth2IdentityProviderConfig config = gitHubIdentityProvider.getConfig();
+
+        assertEquals("model-github", config.getAlias());
+        assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+        assertEquals(GitHubIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+        assertEquals(GitHubIdentityProvider.TOKEN_URL, config.getTokenUrl());
+        assertEquals(GitHubIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+    }
+
+    private void assertLinkedInIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        LinkedInIdentityProvider liIdentityProvider = new LinkedInIdentityProviderFactory().create(identityProvider);
+        OAuth2IdentityProviderConfig config = liIdentityProvider.getConfig();
+
+        assertEquals("model-linkedin", config.getAlias());
+      assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+      assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+      assertEquals(false, config.isAuthenticateByDefault());
+      assertEquals(false, config.isStoreToken());
+      assertEquals("clientId", config.getClientId());
+      assertEquals("clientSecret", config.getClientSecret());
+      assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+      assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl());
+      assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+    }
+
+    private void assertStackoverflowIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        StackoverflowIdentityProvider soIdentityProvider = new StackoverflowIdentityProviderFactory().create(identityProvider);
+        StackOverflowIdentityProviderConfig config = soIdentityProvider.getConfig();
+
+        assertEquals("model-stackoverflow", config.getAlias());
+        assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+        assertEquals("keyValue", config.getKey());
+        assertEquals(StackoverflowIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+        assertEquals(StackoverflowIdentityProvider.TOKEN_URL, config.getTokenUrl());
+        assertEquals(StackoverflowIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+    }
+
+    private void assertTwitterIdentityProviderConfig(IdentityProviderModel identityProvider) {
+        TwitterIdentityProvider twitterIdentityProvider = new TwitterIdentityProviderFactory().create(identityProvider);
+        OAuth2IdentityProviderConfig config = twitterIdentityProvider.getConfig();
+
+        assertEquals("model-twitter", config.getAlias());
+        assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
+        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
+        assertEquals(false, config.isTrustEmail());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(true, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+    }
+
+    private RealmModel installTestRealm() throws IOException {
+        RealmRepresentation realmRepresentation = loadJson("broker-test/test-realm-with-broker.json");
+
+        assertNotNull(realmRepresentation);
+        assertEquals("realm-with-broker", realmRepresentation.getRealm());
+
+        RealmModel realmModel = this.realmManager.getRealm("realm-with-broker");
+
+        if (realmModel == null) {
+            realmModel = this.realmManager.importRealm(realmRepresentation);
+
+            commit();
+
+            realmModel = this.realmManager.getRealm(realmModel.getId());
+
+            assertNotNull(realmModel);
+        }
+
+        return realmModel;
+    }
+}
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 686355c..0a7ee16 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
@@ -1,132 +1,132 @@
-package org.keycloak.testsuite.broker;
-
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.services.Urls;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.Constants;
-import org.keycloak.testsuite.pages.AccountApplicationsPage;
-import org.keycloak.testsuite.pages.OAuthGrantPage;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.KeycloakServer;
-import org.keycloak.util.JsonSerialization;
-import org.openqa.selenium.NoSuchElementException;
-
-import java.io.IOException;
-
-import javax.ws.rs.core.UriBuilder;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-/**
- * @author pedroigor
- */
-public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderTest {
-
-    private static final int PORT = 8082;
-
-    @ClassRule
-    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
-
-        @Override
-        protected void configureServer(KeycloakServer server) {
-            server.getConfig().setPort(PORT);
-        }
-
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-kc-oidc.json"));
-        }
-
-        @Override
-        protected String[] getTestRealms() {
-            return new String[] { "realm-with-oidc-identity-provider" };
-        }
-    };
-
-    @WebResource
-    private OAuthGrantPage grantPage;
-
-    @WebResource
-    protected AccountApplicationsPage accountApplicationsPage;
-
-    @Override
-    protected void revokeGrant() {
-        String currentUrl = driver.getCurrentUrl();
-
-        String accountAccessPath = Urls.accountApplicationsPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString();
-        accountApplicationsPage.setPath(accountAccessPath);
-        accountApplicationsPage.open();
-        try {
-            accountApplicationsPage.revokeGrant("broker-app");
-        } catch (NoSuchElementException e) {
-            System.err.println("Couldn't revoke broker-app application, maybe because it wasn't granted or user not logged");
-        }
-
-        driver.navigate().to(currentUrl);
-    }
-
-    @Override
-    protected void doAfterProviderAuthentication() {
-        // grant access to broker-app
-        //grantPage.assertCurrent();
-        //grantPage.accept();
-    }
-
-    @Override
-    protected void doAssertTokenRetrieval(String pageSource) {
-        try {
-            AccessTokenResponse accessTokenResponse = JsonSerialization.readValue(pageSource, AccessTokenResponse.class);
-
-            assertNotNull(accessTokenResponse.getToken());
-            assertNotNull(accessTokenResponse.getIdToken());
-        } catch (IOException e) {
-            fail("Could not parse token.");
-        }
-    }
-
-    @Override
-    protected String getProviderId() {
-        return "kc-oidc-idp";
-    }
-
-    @Test
-    public void testSuccessfulAuthentication() {
-        super.testSuccessfulAuthentication();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided();
-    }
-
-    @Test
-    public void testTokenStorageAndRetrievalByApplication() {
-        super.testTokenStorageAndRetrievalByApplication();
-    }
-
-    @Test
-    public void testAccountManagementLinkIdentity() {
-        super.testAccountManagementLinkIdentity();
-    }
-}
+package org.keycloak.testsuite.broker;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.Constants;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.KeycloakServer;
+import org.keycloak.util.JsonSerialization;
+import org.openqa.selenium.NoSuchElementException;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.UriBuilder;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * @author pedroigor
+ */
+public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderTest {
+
+    private static final int PORT = 8082;
+
+    @ClassRule
+    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
+
+        @Override
+        protected void configureServer(KeycloakServer server) {
+            server.getConfig().setPort(PORT);
+        }
+
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-kc-oidc.json"));
+        }
+
+        @Override
+        protected String[] getTestRealms() {
+            return new String[] { "realm-with-oidc-identity-provider" };
+        }
+    };
+
+    @WebResource
+    private OAuthGrantPage grantPage;
+
+    @WebResource
+    protected AccountApplicationsPage accountApplicationsPage;
+
+    @Override
+    protected void revokeGrant() {
+        String currentUrl = driver.getCurrentUrl();
+
+        String accountAccessPath = Urls.accountApplicationsPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString();
+        accountApplicationsPage.setPath(accountAccessPath);
+        accountApplicationsPage.open();
+        try {
+            accountApplicationsPage.revokeGrant("broker-app");
+        } catch (NoSuchElementException e) {
+            System.err.println("Couldn't revoke broker-app application, maybe because it wasn't granted or user not logged");
+        }
+
+        driver.navigate().to(currentUrl);
+    }
+
+    @Override
+    protected void doAfterProviderAuthentication() {
+        // grant access to broker-app
+        //grantPage.assertCurrent();
+        //grantPage.accept();
+    }
+
+    @Override
+    protected void doAssertTokenRetrieval(String pageSource) {
+        try {
+            AccessTokenResponse accessTokenResponse = JsonSerialization.readValue(pageSource, AccessTokenResponse.class);
+
+            assertNotNull(accessTokenResponse.getToken());
+            assertNotNull(accessTokenResponse.getIdToken());
+        } catch (IOException e) {
+            fail("Could not parse token.");
+        }
+    }
+
+    @Override
+    protected String getProviderId() {
+        return "kc-oidc-idp";
+    }
+
+    @Test
+    public void testSuccessfulAuthentication() {
+        super.testSuccessfulAuthentication();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided();
+    }
+
+    @Test
+    public void testTokenStorageAndRetrievalByApplication() {
+        super.testTokenStorageAndRetrievalByApplication();
+    }
+
+    @Test
+    public void testAccountManagementLinkIdentity() {
+        super.testAccountManagementLinkIdentity();
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
index c0ffd00..7bbaa20 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
@@ -1,123 +1,123 @@
-package org.keycloak.testsuite.broker;
-
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * @author pedroigor
- */
-public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderTest {
-
-    @ClassRule
-    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
-
-        @Override
-        protected void configureServer(KeycloakServer server) {
-            server.getConfig().setPort(8082);
-        }
-
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-saml.json"));
-        }
-
-        @Override
-        protected String[] getTestRealms() {
-            return new String[] { "realm-with-saml-idp-basic" };
-        }
-    };
-
-    @Override
-    protected String getProviderId() {
-        return "kc-saml-idp-basic";
-    }
-
-    @Override
-    protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
-        if (isProfileUpdateExpected) {
-            super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
-        } else {
-            if (expectedEmail == null) {
-                // Need to handle differences for various databases (like Oracle)
-                assertTrue(federatedUser.getEmail() == null || federatedUser.getEmail().equals(""));
-            } else {
-                assertEquals(expectedEmail, federatedUser.getEmail());
-            }
-            assertNull(federatedUser.getFirstName());
-            assertNull(federatedUser.getLastName());
-        }
-    }
-
-    @Override
-    protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
-        assertEquals("kc-saml-idp-basic.test-user-noemail", federatedUser.getUsername());
-        //assertEquals("", federatedUser.getEmail());
-        assertEquals(null, federatedUser.getFirstName());
-        assertEquals(null, federatedUser.getLastName());
-    }
-
-    @Override
-    protected void doAssertTokenRetrieval(String pageSource) {
-        try {
-            SAML2Request saml2Request = new SAML2Request();
-            ResponseType responseType = (ResponseType) saml2Request
-                    .getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(pageSource));
-                    //.getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(URLDecoder.decode(pageSource, "UTF-8")));
-
-            assertNotNull(responseType);
-            assertFalse(responseType.getAssertions().isEmpty());
-        } catch (Exception e) {
-            fail("Could not parse token.");
-        }
-    }
-
-    @Override
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile();
-    }
-
-    @Override
-    @Test
-    public void testSuccessfulAuthentication() {
-        super.testSuccessfulAuthentication();
-    }
-
-    @Test
-    public void testAccountManagementLinkIdentity() {
-        super.testAccountManagementLinkIdentity();
-    }
-
-    @Test
-    public void testTokenStorageAndRetrievalByApplication() {
-        super.testTokenStorageAndRetrievalByApplication();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
-        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
-        // skip this test as this provider do not return name and surname so something is missing always
-    }
-}
+package org.keycloak.testsuite.broker;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.KeycloakServer;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author pedroigor
+ */
+public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderTest {
+
+    @ClassRule
+    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
+
+        @Override
+        protected void configureServer(KeycloakServer server) {
+            server.getConfig().setPort(8082);
+        }
+
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-saml.json"));
+        }
+
+        @Override
+        protected String[] getTestRealms() {
+            return new String[] { "realm-with-saml-idp-basic" };
+        }
+    };
+
+    @Override
+    protected String getProviderId() {
+        return "kc-saml-idp-basic";
+    }
+
+    @Override
+    protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
+        if (isProfileUpdateExpected) {
+            super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
+        } else {
+            if (expectedEmail == null) {
+                // Need to handle differences for various databases (like Oracle)
+                assertTrue(federatedUser.getEmail() == null || federatedUser.getEmail().equals(""));
+            } else {
+                assertEquals(expectedEmail, federatedUser.getEmail());
+            }
+            assertNull(federatedUser.getFirstName());
+            assertNull(federatedUser.getLastName());
+        }
+    }
+
+    @Override
+    protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
+        assertEquals("kc-saml-idp-basic.test-user-noemail", federatedUser.getUsername());
+        //assertEquals("", federatedUser.getEmail());
+        assertEquals(null, federatedUser.getFirstName());
+        assertEquals(null, federatedUser.getLastName());
+    }
+
+    @Override
+    protected void doAssertTokenRetrieval(String pageSource) {
+        try {
+            SAML2Request saml2Request = new SAML2Request();
+            ResponseType responseType = (ResponseType) saml2Request
+                    .getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(pageSource));
+                    //.getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(URLDecoder.decode(pageSource, "UTF-8")));
+
+            assertNotNull(responseType);
+            assertFalse(responseType.getAssertions().isEmpty());
+        } catch (Exception e) {
+            fail("Could not parse token.");
+        }
+    }
+
+    @Override
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile();
+    }
+
+    @Override
+    @Test
+    public void testSuccessfulAuthentication() {
+        super.testSuccessfulAuthentication();
+    }
+
+    @Test
+    public void testAccountManagementLinkIdentity() {
+        super.testAccountManagementLinkIdentity();
+    }
+
+    @Test
+    public void testTokenStorageAndRetrievalByApplication() {
+        super.testTokenStorageAndRetrievalByApplication();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
+        super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
+        // skip this test as this provider do not return name and surname so something is missing always
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
index b94f4df..249f2e0 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
@@ -1,116 +1,116 @@
-package org.keycloak.testsuite.broker;
-
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * @author pedroigor
- */
-public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityProviderTest {
-
-    @ClassRule
-    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
-
-        @Override
-        protected void configureServer(KeycloakServer server) {
-            server.getConfig().setPort(8082);
-        }
-
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-saml-with-signature.json"));
-        }
-
-        @Override
-        protected String[] getTestRealms() {
-            return new String[] { "realm-with-saml-signed-idp" };
-        }
-    };
-
-    // @Test
-    public void testSleep() throws Exception {
-        Thread.sleep(100000000);
-    }
-
-    @Override
-    protected String getProviderId() {
-        return "kc-saml-signed-idp";
-    }
-
-    @Override
-    protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
-        if (isProfileUpdateExpected) {
-            super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
-        } else {
-            if (expectedEmail == null) {
-                // Need to handle differences for various databases (like Oracle)
-                assertTrue(federatedUser.getEmail() == null || federatedUser.getEmail().equals(""));
-            } else {
-                assertEquals(expectedEmail, federatedUser.getEmail());
-            }
-            assertNull(federatedUser.getFirstName());
-            assertNull(federatedUser.getLastName());
-        }
-    }
-
-    @Override
-    protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
-        assertEquals("kc-saml-signed-idp.test-user-noemail", federatedUser.getUsername());
-        //assertEquals("", federatedUser.getEmail());
-        assertEquals(null, federatedUser.getFirstName());
-        assertEquals(null, federatedUser.getLastName());
-    }
-
-    @Override
-    protected void doAssertTokenRetrieval(String pageSource) {
-        try {
-            SAML2Request saml2Request = new SAML2Request();
-            ResponseType responseType = (ResponseType) saml2Request
-                        .getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(pageSource));
-
-            assertNotNull(responseType);
-            assertFalse(responseType.getAssertions().isEmpty());
-        } catch (Exception e) {
-            fail("Could not parse token.");
-        }
-    }
-
-    @Override
-    @Test
-    public void testSuccessfulAuthentication() {
-        super.testSuccessfulAuthentication();
-    }
-
-    @Test
-    public void testTokenStorageAndRetrievalByApplication() {
-        super.testTokenStorageAndRetrievalByApplication();
-    }
-
-    @Test
-    public void testAccountManagementLinkIdentity() {
-        super.testAccountManagementLinkIdentity();
-    }
-
-    @Test
-    public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
-        // skip this test as this provider do not return name and surname so something is missing always
-    }
-}
+package org.keycloak.testsuite.broker;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.KeycloakServer;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author pedroigor
+ */
+public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityProviderTest {
+
+    @ClassRule
+    public static AbstractKeycloakRule samlServerRule = new AbstractKeycloakRule() {
+
+        @Override
+        protected void configureServer(KeycloakServer server) {
+            server.getConfig().setPort(8082);
+        }
+
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            server.importRealm(getClass().getResourceAsStream("/broker-test/test-broker-realm-with-saml-with-signature.json"));
+        }
+
+        @Override
+        protected String[] getTestRealms() {
+            return new String[] { "realm-with-saml-signed-idp" };
+        }
+    };
+
+    // @Test
+    public void testSleep() throws Exception {
+        Thread.sleep(100000000);
+    }
+
+    @Override
+    protected String getProviderId() {
+        return "kc-saml-signed-idp";
+    }
+
+    @Override
+    protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
+        if (isProfileUpdateExpected) {
+            super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
+        } else {
+            if (expectedEmail == null) {
+                // Need to handle differences for various databases (like Oracle)
+                assertTrue(federatedUser.getEmail() == null || federatedUser.getEmail().equals(""));
+            } else {
+                assertEquals(expectedEmail, federatedUser.getEmail());
+            }
+            assertNull(federatedUser.getFirstName());
+            assertNull(federatedUser.getLastName());
+        }
+    }
+
+    @Override
+    protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
+        assertEquals("kc-saml-signed-idp.test-user-noemail", federatedUser.getUsername());
+        //assertEquals("", federatedUser.getEmail());
+        assertEquals(null, federatedUser.getFirstName());
+        assertEquals(null, federatedUser.getLastName());
+    }
+
+    @Override
+    protected void doAssertTokenRetrieval(String pageSource) {
+        try {
+            SAML2Request saml2Request = new SAML2Request();
+            ResponseType responseType = (ResponseType) saml2Request
+                        .getSAML2ObjectFromStream(PostBindingUtil.base64DecodeAsStream(pageSource));
+
+            assertNotNull(responseType);
+            assertFalse(responseType.getAssertions().isEmpty());
+        } catch (Exception e) {
+            fail("Could not parse token.");
+        }
+    }
+
+    @Override
+    @Test
+    public void testSuccessfulAuthentication() {
+        super.testSuccessfulAuthentication();
+    }
+
+    @Test
+    public void testTokenStorageAndRetrievalByApplication() {
+        super.testTokenStorageAndRetrievalByApplication();
+    }
+
+    @Test
+    public void testAccountManagementLinkIdentity() {
+        super.testAccountManagementLinkIdentity();
+    }
+
+    @Test
+    public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
+        // skip this test as this provider do not return name and surname so something is missing always
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
index ad61241..e540a32 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
@@ -1,195 +1,195 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.composites;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.ApplicationServlet;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.openqa.selenium.WebDriver;
-
-import java.security.PublicKey;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class CompositeImportRoleTest {
-
-    public static PublicKey realmPublicKey;
-    @ClassRule
-    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            RealmRepresentation representation = KeycloakServer.loadJson(getClass().getResourceAsStream("/testcomposite.json"), RealmRepresentation.class);
-            representation.setId("test");
-            RealmModel realm = manager.importRealm(representation);
-
-            realmPublicKey = realm.getPublicKey();
-
-            deployServlet("app", "/app", ApplicationServlet.class);
-
-        }
-    };
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @WebResource
-    protected OAuthClient oauth;
-
-    @WebResource
-    protected LoginPage loginPage;
-
-    @Test
-    public void testAppCompositeUser() throws Exception {
-        oauth.realm("test");
-        oauth.realmPublicKey(realmPublicKey);
-        oauth.clientId("APP_COMPOSITE_APPLICATION");
-        oauth.doLogin("APP_COMPOSITE_USER", "password");
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "APP_COMPOSITE_USER").getId(), token.getSubject());
-
-        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
-        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
-    }
-
-
-    @Test
-    public void testRealmAppCompositeUser() throws Exception {
-        oauth.realm("test");
-        oauth.realmPublicKey(realmPublicKey);
-        oauth.clientId("APP_ROLE_APPLICATION");
-        oauth.doLogin("REALM_APP_COMPOSITE_USER", "password");
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "REALM_APP_COMPOSITE_USER").getId(), token.getSubject());
-
-        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
-        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
-    }
-
-
-
-    @Test
-    public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
-        oauth.realm("test");
-        oauth.realmPublicKey(realmPublicKey);
-        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
-        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
-
-        Assert.assertEquals(2, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_COMPOSITE_1"));
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
-    }
-
-    @Test
-    public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
-        oauth.realm("test");
-        oauth.realmPublicKey(realmPublicKey);
-        oauth.clientId("REALM_ROLE_1_APPLICATION");
-        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
-
-        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
-    }
-
-    @Test
-    public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
-        oauth.realm("test");
-        oauth.realmPublicKey(realmPublicKey);
-        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
-        oauth.doLogin("REALM_ROLE_1_USER", "password");
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "REALM_ROLE_1_USER").getId(), token.getSubject());
-
-        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.composites;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.ApplicationServlet;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.testsuite.KeycloakServer;
+import org.openqa.selenium.WebDriver;
+
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class CompositeImportRoleTest {
+
+    public static PublicKey realmPublicKey;
+    @ClassRule
+    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            RealmRepresentation representation = KeycloakServer.loadJson(getClass().getResourceAsStream("/testcomposite.json"), RealmRepresentation.class);
+            representation.setId("test");
+            RealmModel realm = manager.importRealm(representation);
+
+            realmPublicKey = realm.getPublicKey();
+
+            deployServlet("app", "/app", ApplicationServlet.class);
+
+        }
+    };
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @Test
+    public void testAppCompositeUser() throws Exception {
+        oauth.realm("test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("APP_COMPOSITE_APPLICATION");
+        oauth.doLogin("APP_COMPOSITE_USER", "password");
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "APP_COMPOSITE_USER").getId(), token.getSubject());
+
+        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+
+    @Test
+    public void testRealmAppCompositeUser() throws Exception {
+        oauth.realm("test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("APP_ROLE_APPLICATION");
+        oauth.doLogin("REALM_APP_COMPOSITE_USER", "password");
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "REALM_APP_COMPOSITE_USER").getId(), token.getSubject());
+
+        Assert.assertEquals(1, token.getResourceAccess("APP_ROLE_APPLICATION").getRoles().size());
+        Assert.assertTrue(token.getResourceAccess("APP_ROLE_APPLICATION").isUserInRole("APP_ROLE_1"));
+    }
+
+
+
+    @Test
+    public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
+        oauth.realm("test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
+        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
+
+        Assert.assertEquals(2, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_COMPOSITE_1"));
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+    @Test
+    public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
+        oauth.realm("test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_ROLE_1_APPLICATION");
+        oauth.doLogin("REALM_COMPOSITE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "REALM_COMPOSITE_1_USER").getId(), token.getSubject());
+
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+    @Test
+    public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
+        oauth.realm("test");
+        oauth.realmPublicKey(realmPublicKey);
+        oauth.clientId("REALM_COMPOSITE_1_APPLICATION");
+        oauth.doLogin("REALM_ROLE_1_USER", "password");
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "REALM_ROLE_1_USER").getId(), token.getSubject());
+
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("REALM_ROLE_1"));
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProvider.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProvider.java
index 865ffa0..b501da9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProvider.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProvider.java
@@ -1,104 +1,104 @@
-package org.keycloak.testsuite;
-
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserModel;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DummyUserFederationProvider implements UserFederationProvider {
-
-    private static Map<String, UserModel> users = new HashMap<String, UserModel>();
-
-    @Override
-    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
-        return local;
-    }
-
-    @Override
-    public boolean synchronizeRegistrations() {
-        return true;
-    }
-
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        users.put(user.getUsername(), user);
-        return user;
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        return users.remove(user.getUsername()) != null;
-    }
-
-    @Override
-    public UserModel getUserByUsername(RealmModel realm, String username) {
-        return users.get(username);
-    }
-
-    @Override
-    public UserModel getUserByEmail(RealmModel realm, String email) {
-        return null;
-    }
-
-    @Override
-    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public void preRemove(RealmModel realm) {
-
-    }
-
-    @Override
-    public void preRemove(RealmModel realm, RoleModel role) {
-
-    }
-
-    @Override
-    public boolean isValid(RealmModel realm, UserModel local) {
-        return false;
-    }
-
-    @Override
-    public Set<String> getSupportedCredentialTypes(UserModel user) {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public Set<String> getSupportedCredentialTypes() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
-        return false;
-    }
-
-    @Override
-    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
-        return false;
-    }
-
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
-        return CredentialValidationOutput.failed();
-    }
-
-    @Override
-    public void close() {
-
-    }
-}
+package org.keycloak.testsuite;
+
+import org.keycloak.models.CredentialValidationOutput;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserModel;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DummyUserFederationProvider implements UserFederationProvider {
+
+    private static Map<String, UserModel> users = new HashMap<String, UserModel>();
+
+    @Override
+    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
+        return local;
+    }
+
+    @Override
+    public boolean synchronizeRegistrations() {
+        return true;
+    }
+
+    @Override
+    public UserModel register(RealmModel realm, UserModel user) {
+        users.put(user.getUsername(), user);
+        return user;
+    }
+
+    @Override
+    public boolean removeUser(RealmModel realm, UserModel user) {
+        return users.remove(user.getUsername()) != null;
+    }
+
+    @Override
+    public UserModel getUserByUsername(RealmModel realm, String username) {
+        return users.get(username);
+    }
+
+    @Override
+    public UserModel getUserByEmail(RealmModel realm, String email) {
+        return null;
+    }
+
+    @Override
+    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void preRemove(RealmModel realm) {
+
+    }
+
+    @Override
+    public void preRemove(RealmModel realm, RoleModel role) {
+
+    }
+
+    @Override
+    public boolean isValid(RealmModel realm, UserModel local) {
+        return false;
+    }
+
+    @Override
+    public Set<String> getSupportedCredentialTypes(UserModel user) {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<String> getSupportedCredentialTypes() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
+        return false;
+    }
+
+    @Override
+    public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
+        return false;
+    }
+
+    @Override
+    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
+        return CredentialValidationOutput.failed();
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java
index b8ec10a..9825f5b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java
@@ -1,87 +1,87 @@
-package org.keycloak.testsuite;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserFederationSyncResult;
-
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class DummyUserFederationProviderFactory implements UserFederationProviderFactory {
-
-    private static final Logger logger = Logger.getLogger(DummyUserFederationProviderFactory.class);
-    public static final String PROVIDER_NAME = "dummy";
-
-    private AtomicInteger fullSyncCounter = new AtomicInteger();
-    private AtomicInteger changedSyncCounter = new AtomicInteger();
-
-    @Override
-    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        return new DummyUserFederationProvider();
-    }
-
-    @Override
-    public Set<String> getConfigurationOptions() {
-        Set<String> list = new HashSet<String>();
-        list.add("important.config");
-        return list;
-    }
-
-    @Override
-    public UserFederationProvider create(KeycloakSession session) {
-        return new DummyUserFederationProvider();
-    }
-
-    @Override
-    public void init(Config.Scope config) {
-
-    }
-
-    @Override
-    public void postInit(KeycloakSessionFactory factory) {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public String getId() {
-        return PROVIDER_NAME;
-    }
-
-    @Override
-    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
-        logger.info("syncAllUsers invoked");
-        fullSyncCounter.incrementAndGet();
-        return UserFederationSyncResult.empty();
-    }
-
-    @Override
-    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
-        logger.info("syncChangedUsers invoked");
-        changedSyncCounter.incrementAndGet();
-        return UserFederationSyncResult.empty();
-    }
-
-    public int getFullSyncCounter() {
-        return fullSyncCounter.get();
-    }
-
-    public int getChangedSyncCounter() {
-        return changedSyncCounter.get();
-    }
-}
+package org.keycloak.testsuite;
+
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderFactory;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserFederationSyncResult;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DummyUserFederationProviderFactory implements UserFederationProviderFactory {
+
+    private static final Logger logger = Logger.getLogger(DummyUserFederationProviderFactory.class);
+    public static final String PROVIDER_NAME = "dummy";
+
+    private AtomicInteger fullSyncCounter = new AtomicInteger();
+    private AtomicInteger changedSyncCounter = new AtomicInteger();
+
+    @Override
+    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
+        return new DummyUserFederationProvider();
+    }
+
+    @Override
+    public Set<String> getConfigurationOptions() {
+        Set<String> list = new HashSet<String>();
+        list.add("important.config");
+        return list;
+    }
+
+    @Override
+    public UserFederationProvider create(KeycloakSession session) {
+        return new DummyUserFederationProvider();
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_NAME;
+    }
+
+    @Override
+    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
+        logger.info("syncAllUsers invoked");
+        fullSyncCounter.incrementAndGet();
+        return UserFederationSyncResult.empty();
+    }
+
+    @Override
+    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
+        logger.info("syncChangedUsers invoked");
+        changedSyncCounter.incrementAndGet();
+        return UserFederationSyncResult.empty();
+    }
+
+    public int getFullSyncCounter() {
+        return fullSyncCounter.get();
+    }
+
+    public int getChangedSyncCounter() {
+        return changedSyncCounter.get();
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
index 8e3ba99..ae40c92 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
@@ -1,386 +1,386 @@
-package org.keycloak.testsuite.exportimport;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.ExternalResource;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TestRule;
-import org.keycloak.exportimport.ExportImportConfig;
-import org.keycloak.exportimport.dir.DirExportProvider;
-import org.keycloak.exportimport.dir.DirExportProviderFactory;
-import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
-import org.keycloak.exportimport.zip.ZipExportProviderFactory;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.model.AbstractModelTest;
-import org.keycloak.testsuite.model.ImportTest;
-import org.keycloak.testsuite.rule.KeycloakRule;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.regex.Matcher;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ExportImportTest {
-
-    private static SystemPropertiesHelper propsHelper = new SystemPropertiesHelper();
-
-    private static final String JPA_CONNECTION_URL = "keycloak.connectionsJpa.url";
-    private static final String JPA_DB_SCHEMA = "keycloak.connectionsJpa.databaseSchema";
-    private static final String MONGO_CLEAR_ON_STARTUP = "keycloak.connectionsMongo.clearOnStartup";
-
-    // We want data to be persisted among server restarts
-    private static ExternalResource persistenceSetupRule = new ExternalResource() {
-
-        private boolean connectionURLSet = false;
-
-        @Override
-        protected void before() throws Throwable {
-            if (System.getProperty(JPA_CONNECTION_URL) == null) {
-                String baseExportImportDir = getExportImportTestDirectory();
-
-                File oldDBFile = new File(baseExportImportDir, "keycloakDB.h2.db");
-                if (oldDBFile.exists()) {
-                    oldDBFile.delete();
-                }
-
-                String dbDir = baseExportImportDir + "/keycloakDB";
-                propsHelper.pushProperty(JPA_CONNECTION_URL, "jdbc:h2:file:" + dbDir + ";DB_CLOSE_DELAY=-1");
-                connectionURLSet = true;
-            }
-            propsHelper.pushProperty(JPA_DB_SCHEMA, "update");
-        }
-
-        @Override
-        protected void after() {
-            if (connectionURLSet) {
-                propsHelper.pullProperty(JPA_CONNECTION_URL);
-            }
-        }
-    };
-
-    private static ExternalResource outerPersistenceSetupRule = new ExternalResource() {
-
-        @Override
-        protected void before() throws Throwable {
-            System.setProperty(JPA_DB_SCHEMA, "update");
-            propsHelper.pushProperty(MONGO_CLEAR_ON_STARTUP, "false");
-        }
-
-        @Override
-        protected void after() {
-            propsHelper.pullProperty(JPA_DB_SCHEMA);
-            propsHelper.pullProperty(MONGO_CLEAR_ON_STARTUP);
-        }
-    };
-
-    private static KeycloakRule keycloakRule = new KeycloakRule( new KeycloakRule.KeycloakSetup() {
-
-        @Override
-        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            // Create some users in "test" and "master" realms
-            addUser(manager.getSession().users(), appRealm, "user1", "password");
-            addUser(manager.getSession().users(), appRealm, "user2", "password");
-            addUser(manager.getSession().users(), appRealm, "user3", "password");
-
-            // Import "test-realm" realm
-            try {
-                RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm.json");
-                rep.setId("test-realm");
-                RealmModel demoRealm = manager.importRealm(rep);
-            } catch (IOException ioe) {
-                throw new RuntimeException(ioe);
-            }
-        }
-
-    }) {
-        @Override
-        protected void after() {
-            super.after();
-
-            // Clear export/import properties after test
-            Properties systemProps = System.getProperties();
-            Set<String> propsToRemove = new HashSet<String>();
-
-            for (Object key : systemProps.keySet()) {
-                if (key.toString().startsWith(ExportImportConfig.PREFIX)) {
-                    propsToRemove.add(key.toString());
-                }
-            }
-
-            for (String propToRemove : propsToRemove) {
-                systemProps.remove(propToRemove);
-            }
-        }
-
-        protected String[] getTestRealms() {
-            return new String[]{"test", "demo", "test-realm"};
-        }
-    };
-
-    @ClassRule
-    public static TestRule chain = RuleChain
-            .outerRule(persistenceSetupRule)
-            .around(keycloakRule)
-            .around(outerPersistenceSetupRule);
-
-    @Test
-    public void testDirFullExportImport() throws Throwable {
-        ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
-        String targetDirPath = getExportImportTestDirectory() + File.separator + "dirExport";
-        DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
-        ExportImportConfig.setDir(targetDirPath);
-        ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
-
-        testFullExportImport();
-
-        // There should be 6 files in target directory (3 realm, 3 user, 1 version)
-        Assert.assertEquals(7, new File(targetDirPath).listFiles().length);
-    }
-
-    @Test
-    public void testDirRealmExportImport() throws Throwable {
-        ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
-        String targetDirPath = getExportImportTestDirectory() + File.separator + "dirRealmExport";
-        DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
-        ExportImportConfig.setDir(targetDirPath);
-        ExportImportConfig.setUsersPerFile(3);
-
-        testRealmExportImport();
-
-        // There should be 3 files in target directory (1 realm, 2 user, 1 version)
-        Assert.assertEquals(4, new File(targetDirPath).listFiles().length);
-    }
-
-    @Test
-    public void testSingleFileFullExportImport() throws Throwable {
-        ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
-        String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-full.json";
-        ExportImportConfig.setFile(targetFilePath);
-
-        testFullExportImport();
-    }
-
-    @Test
-    public void testSingleFileRealmExportImport() throws Throwable {
-        ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
-        String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
-        ExportImportConfig.setFile(targetFilePath);
-
-        testRealmExportImport();
-    }
-
-    @Test
-    public void testZipFullExportImport() throws Throwable {
-        ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
-        String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
-        new File(zipFilePath).delete();
-        ExportImportConfig.setZipFile(zipFilePath);
-        ExportImportConfig.setZipPassword("encPassword");
-        ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
-
-        testFullExportImport();
-    }
-
-    @Test
-    public void testZipRealmExportImport() throws Throwable {
-        ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
-        String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
-        new File(zipFilePath).delete();
-        ExportImportConfig.setZipFile(zipFilePath);
-        ExportImportConfig.setZipPassword("encPassword");
-        ExportImportConfig.setUsersPerFile(3);
-
-        testRealmExportImport();
-    }
-
-    private void testFullExportImport() {
-        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
-        ExportImportConfig.setRealmName(null);
-
-        // Restart server, which triggers export
-        keycloakRule.restartServer();
-
-        // Delete some realm (and some data in admin realm)
-        KeycloakSession session = keycloakRule.startSession();
-        try {
-            RealmProvider realmProvider = session.realms();
-            UserProvider userProvider = session.users();
-            new RealmManager(session).removeRealm(realmProvider.getRealmByName("test"));
-            Assert.assertEquals(2, realmProvider.getRealms().size());
-
-            assertNotAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user1", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user2", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user3", "password");
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-
-        // Configure import
-        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
-
-        // Restart server, which triggers import
-        keycloakRule.restartServer();
-
-        // Ensure data are imported back
-        session = keycloakRule.startSession();
-        try {
-            RealmProvider model = session.realms();
-            UserProvider userProvider = session.users();
-            Assert.assertEquals(3, model.getRealms().size());
-
-            assertAuthenticated(userProvider, model, "test", "test-user@localhost", "password");
-            assertAuthenticated(userProvider, model, "test", "user1", "password");
-            assertAuthenticated(userProvider, model, "test", "user2", "password");
-            assertAuthenticated(userProvider, model, "test", "user3", "password");
-
-            RealmModel testRealmRealm = model.getRealm("test-realm");
-            ImportTest.assertDataImportedInRealm(session, testRealmRealm);
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-    }
-
-    private void testRealmExportImport() {
-        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
-        ExportImportConfig.setRealmName("test");
-
-        // Restart server, which triggers export
-        keycloakRule.restartServer();
-
-        // Delete some realm (and some data in admin realm)
-        KeycloakSession session = keycloakRule.startSession();
-        try {
-            RealmProvider realmProvider = session.realms();
-            UserProvider userProvider = session.users();
-            new RealmManager(session).removeRealm(realmProvider.getRealmByName("test"));
-            Assert.assertEquals(2, realmProvider.getRealms().size());
-
-            assertNotAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user1", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user2", "password");
-            assertNotAuthenticated(userProvider, realmProvider, "test", "user3", "password");
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-
-        // Configure import
-        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
-
-        // Restart server, which triggers import
-        keycloakRule.restartServer();
-
-        // Ensure data are imported back, but just for "test" realm
-        session = keycloakRule.startSession();
-        try {
-            RealmProvider realmProvider = session.realms();
-            UserProvider userProvider = session.users();
-            Assert.assertEquals(3, realmProvider.getRealms().size());
-
-            assertAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
-            assertAuthenticated(userProvider, realmProvider, "test", "user1", "password");
-            assertAuthenticated(userProvider, realmProvider, "test", "user2", "password");
-            assertAuthenticated(userProvider, realmProvider, "test", "user3", "password");
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-    }
-
-    private void assertAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
-        RealmModel realm = realmProvider.getRealmByName(realmName);
-        if (realm == null) {
-            Assert.fail("realm " + realmName + " not found");
-        }
-
-        UserModel user = userProvider.getUserByUsername(username, realm);
-        if (user == null) {
-            Assert.fail("user " + username + " not found");
-        }
-
-        Assert.assertTrue(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
-    }
-
-    private void assertNotAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
-        RealmModel realm = realmProvider.getRealmByName(realmName);
-        if (realm == null) {
-            return;
-        }
-
-        UserModel user = userProvider.getUserByUsername(username, realm);
-        if (user == null) {
-            return;
-        }
-
-        Assert.assertFalse(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
-    }
-
-    private static void addUser(UserProvider userProvider, RealmModel appRealm, String username, String password) {
-        UserModel user = userProvider.addUser(appRealm, username);
-        user.setEmail(username + "@test.com");
-        user.setEnabled(true);
-
-        UserCredentialModel creds = new UserCredentialModel();
-        creds.setType(CredentialRepresentation.PASSWORD);
-        creds.setValue(password);
-        user.updateCredential(creds);
-    }
-
-    private static String getExportImportTestDirectory() {
-        String dirPath = null;
-        String relativeDirExportImportPath = "testsuite" + File.separator + "integration" + File.separator + "target" + File.separator + "export-import";
-
-        if (System.getProperties().containsKey("maven.home")) {
-            dirPath = System.getProperty("user.dir").replaceFirst("testsuite.integration.*", Matcher.quoteReplacement(relativeDirExportImportPath));
-        } else {
-            for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
-                if (c.contains(File.separator + "testsuite" + File.separator + "integration")) {
-                    dirPath = c.replaceFirst("testsuite.integration.*", Matcher.quoteReplacement(relativeDirExportImportPath));
-                }
-            }
-        }
-
-        String absolutePath = new File(dirPath).getAbsolutePath();
-        return absolutePath;
-    }
-
-    private static class SystemPropertiesHelper {
-
-        private Map<String,String> previousValues = new HashMap<String,String>();
-
-        private void pushProperty(String name, String value) {
-            String currentValue = System.getProperty(name);
-            if (currentValue != null) {
-                previousValues.put(name, currentValue);
-            }
-            System.setProperty(name, value);
-        }
-
-        private void pullProperty(String name) {
-            String prevValue = previousValues.get(name);
-
-            if (prevValue == null) {
-                System.getProperties().remove(name);
-            }  else {
-                System.setProperty(name, prevValue);
-            }
-        }
-
-    }
-
-}
+package org.keycloak.testsuite.exportimport;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.keycloak.exportimport.ExportImportConfig;
+import org.keycloak.exportimport.dir.DirExportProvider;
+import org.keycloak.exportimport.dir.DirExportProviderFactory;
+import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
+import org.keycloak.exportimport.zip.ZipExportProviderFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.model.AbstractModelTest;
+import org.keycloak.testsuite.model.ImportTest;
+import org.keycloak.testsuite.rule.KeycloakRule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ExportImportTest {
+
+    private static SystemPropertiesHelper propsHelper = new SystemPropertiesHelper();
+
+    private static final String JPA_CONNECTION_URL = "keycloak.connectionsJpa.url";
+    private static final String JPA_DB_SCHEMA = "keycloak.connectionsJpa.databaseSchema";
+    private static final String MONGO_CLEAR_ON_STARTUP = "keycloak.connectionsMongo.clearOnStartup";
+
+    // We want data to be persisted among server restarts
+    private static ExternalResource persistenceSetupRule = new ExternalResource() {
+
+        private boolean connectionURLSet = false;
+
+        @Override
+        protected void before() throws Throwable {
+            if (System.getProperty(JPA_CONNECTION_URL) == null) {
+                String baseExportImportDir = getExportImportTestDirectory();
+
+                File oldDBFile = new File(baseExportImportDir, "keycloakDB.h2.db");
+                if (oldDBFile.exists()) {
+                    oldDBFile.delete();
+                }
+
+                String dbDir = baseExportImportDir + "/keycloakDB";
+                propsHelper.pushProperty(JPA_CONNECTION_URL, "jdbc:h2:file:" + dbDir + ";DB_CLOSE_DELAY=-1");
+                connectionURLSet = true;
+            }
+            propsHelper.pushProperty(JPA_DB_SCHEMA, "update");
+        }
+
+        @Override
+        protected void after() {
+            if (connectionURLSet) {
+                propsHelper.pullProperty(JPA_CONNECTION_URL);
+            }
+        }
+    };
+
+    private static ExternalResource outerPersistenceSetupRule = new ExternalResource() {
+
+        @Override
+        protected void before() throws Throwable {
+            System.setProperty(JPA_DB_SCHEMA, "update");
+            propsHelper.pushProperty(MONGO_CLEAR_ON_STARTUP, "false");
+        }
+
+        @Override
+        protected void after() {
+            propsHelper.pullProperty(JPA_DB_SCHEMA);
+            propsHelper.pullProperty(MONGO_CLEAR_ON_STARTUP);
+        }
+    };
+
+    private static KeycloakRule keycloakRule = new KeycloakRule( new KeycloakRule.KeycloakSetup() {
+
+        @Override
+        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+            // Create some users in "test" and "master" realms
+            addUser(manager.getSession().users(), appRealm, "user1", "password");
+            addUser(manager.getSession().users(), appRealm, "user2", "password");
+            addUser(manager.getSession().users(), appRealm, "user3", "password");
+
+            // Import "test-realm" realm
+            try {
+                RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm.json");
+                rep.setId("test-realm");
+                RealmModel demoRealm = manager.importRealm(rep);
+            } catch (IOException ioe) {
+                throw new RuntimeException(ioe);
+            }
+        }
+
+    }) {
+        @Override
+        protected void after() {
+            super.after();
+
+            // Clear export/import properties after test
+            Properties systemProps = System.getProperties();
+            Set<String> propsToRemove = new HashSet<String>();
+
+            for (Object key : systemProps.keySet()) {
+                if (key.toString().startsWith(ExportImportConfig.PREFIX)) {
+                    propsToRemove.add(key.toString());
+                }
+            }
+
+            for (String propToRemove : propsToRemove) {
+                systemProps.remove(propToRemove);
+            }
+        }
+
+        protected String[] getTestRealms() {
+            return new String[]{"test", "demo", "test-realm"};
+        }
+    };
+
+    @ClassRule
+    public static TestRule chain = RuleChain
+            .outerRule(persistenceSetupRule)
+            .around(keycloakRule)
+            .around(outerPersistenceSetupRule);
+
+    @Test
+    public void testDirFullExportImport() throws Throwable {
+        ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
+        String targetDirPath = getExportImportTestDirectory() + File.separator + "dirExport";
+        DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
+        ExportImportConfig.setDir(targetDirPath);
+        ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
+
+        testFullExportImport();
+
+        // There should be 6 files in target directory (3 realm, 3 user, 1 version)
+        Assert.assertEquals(7, new File(targetDirPath).listFiles().length);
+    }
+
+    @Test
+    public void testDirRealmExportImport() throws Throwable {
+        ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
+        String targetDirPath = getExportImportTestDirectory() + File.separator + "dirRealmExport";
+        DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
+        ExportImportConfig.setDir(targetDirPath);
+        ExportImportConfig.setUsersPerFile(3);
+
+        testRealmExportImport();
+
+        // There should be 3 files in target directory (1 realm, 2 user, 1 version)
+        Assert.assertEquals(4, new File(targetDirPath).listFiles().length);
+    }
+
+    @Test
+    public void testSingleFileFullExportImport() throws Throwable {
+        ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-full.json";
+        ExportImportConfig.setFile(targetFilePath);
+
+        testFullExportImport();
+    }
+
+    @Test
+    public void testSingleFileRealmExportImport() throws Throwable {
+        ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
+        ExportImportConfig.setFile(targetFilePath);
+
+        testRealmExportImport();
+    }
+
+    @Test
+    public void testZipFullExportImport() throws Throwable {
+        ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
+        String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
+        new File(zipFilePath).delete();
+        ExportImportConfig.setZipFile(zipFilePath);
+        ExportImportConfig.setZipPassword("encPassword");
+        ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
+
+        testFullExportImport();
+    }
+
+    @Test
+    public void testZipRealmExportImport() throws Throwable {
+        ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
+        String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
+        new File(zipFilePath).delete();
+        ExportImportConfig.setZipFile(zipFilePath);
+        ExportImportConfig.setZipPassword("encPassword");
+        ExportImportConfig.setUsersPerFile(3);
+
+        testRealmExportImport();
+    }
+
+    private void testFullExportImport() {
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
+        ExportImportConfig.setRealmName(null);
+
+        // Restart server, which triggers export
+        keycloakRule.restartServer();
+
+        // Delete some realm (and some data in admin realm)
+        KeycloakSession session = keycloakRule.startSession();
+        try {
+            RealmProvider realmProvider = session.realms();
+            UserProvider userProvider = session.users();
+            new RealmManager(session).removeRealm(realmProvider.getRealmByName("test"));
+            Assert.assertEquals(2, realmProvider.getRealms().size());
+
+            assertNotAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user1", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user2", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user3", "password");
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+
+        // Configure import
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
+
+        // Restart server, which triggers import
+        keycloakRule.restartServer();
+
+        // Ensure data are imported back
+        session = keycloakRule.startSession();
+        try {
+            RealmProvider model = session.realms();
+            UserProvider userProvider = session.users();
+            Assert.assertEquals(3, model.getRealms().size());
+
+            assertAuthenticated(userProvider, model, "test", "test-user@localhost", "password");
+            assertAuthenticated(userProvider, model, "test", "user1", "password");
+            assertAuthenticated(userProvider, model, "test", "user2", "password");
+            assertAuthenticated(userProvider, model, "test", "user3", "password");
+
+            RealmModel testRealmRealm = model.getRealm("test-realm");
+            ImportTest.assertDataImportedInRealm(session, testRealmRealm);
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+    }
+
+    private void testRealmExportImport() {
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
+        ExportImportConfig.setRealmName("test");
+
+        // Restart server, which triggers export
+        keycloakRule.restartServer();
+
+        // Delete some realm (and some data in admin realm)
+        KeycloakSession session = keycloakRule.startSession();
+        try {
+            RealmProvider realmProvider = session.realms();
+            UserProvider userProvider = session.users();
+            new RealmManager(session).removeRealm(realmProvider.getRealmByName("test"));
+            Assert.assertEquals(2, realmProvider.getRealms().size());
+
+            assertNotAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user1", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user2", "password");
+            assertNotAuthenticated(userProvider, realmProvider, "test", "user3", "password");
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+
+        // Configure import
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
+
+        // Restart server, which triggers import
+        keycloakRule.restartServer();
+
+        // Ensure data are imported back, but just for "test" realm
+        session = keycloakRule.startSession();
+        try {
+            RealmProvider realmProvider = session.realms();
+            UserProvider userProvider = session.users();
+            Assert.assertEquals(3, realmProvider.getRealms().size());
+
+            assertAuthenticated(userProvider, realmProvider, "test", "test-user@localhost", "password");
+            assertAuthenticated(userProvider, realmProvider, "test", "user1", "password");
+            assertAuthenticated(userProvider, realmProvider, "test", "user2", "password");
+            assertAuthenticated(userProvider, realmProvider, "test", "user3", "password");
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+    }
+
+    private void assertAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
+        RealmModel realm = realmProvider.getRealmByName(realmName);
+        if (realm == null) {
+            Assert.fail("realm " + realmName + " not found");
+        }
+
+        UserModel user = userProvider.getUserByUsername(username, realm);
+        if (user == null) {
+            Assert.fail("user " + username + " not found");
+        }
+
+        Assert.assertTrue(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
+    }
+
+    private void assertNotAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
+        RealmModel realm = realmProvider.getRealmByName(realmName);
+        if (realm == null) {
+            return;
+        }
+
+        UserModel user = userProvider.getUserByUsername(username, realm);
+        if (user == null) {
+            return;
+        }
+
+        Assert.assertFalse(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
+    }
+
+    private static void addUser(UserProvider userProvider, RealmModel appRealm, String username, String password) {
+        UserModel user = userProvider.addUser(appRealm, username);
+        user.setEmail(username + "@test.com");
+        user.setEnabled(true);
+
+        UserCredentialModel creds = new UserCredentialModel();
+        creds.setType(CredentialRepresentation.PASSWORD);
+        creds.setValue(password);
+        user.updateCredential(creds);
+    }
+
+    private static String getExportImportTestDirectory() {
+        String dirPath = null;
+        String relativeDirExportImportPath = "testsuite" + File.separator + "integration" + File.separator + "target" + File.separator + "export-import";
+
+        if (System.getProperties().containsKey("maven.home")) {
+            dirPath = System.getProperty("user.dir").replaceFirst("testsuite.integration.*", Matcher.quoteReplacement(relativeDirExportImportPath));
+        } else {
+            for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
+                if (c.contains(File.separator + "testsuite" + File.separator + "integration")) {
+                    dirPath = c.replaceFirst("testsuite.integration.*", Matcher.quoteReplacement(relativeDirExportImportPath));
+                }
+            }
+        }
+
+        String absolutePath = new File(dirPath).getAbsolutePath();
+        return absolutePath;
+    }
+
+    private static class SystemPropertiesHelper {
+
+        private Map<String,String> previousValues = new HashMap<String,String>();
+
+        private void pushProperty(String name, String value) {
+            String currentValue = System.getProperty(name);
+            if (currentValue != null) {
+                previousValues.put(name, currentValue);
+            }
+            System.setProperty(name, value);
+        }
+
+        private void pullProperty(String name) {
+            String prevValue = previousValues.get(name);
+
+            if (prevValue == null) {
+                System.getProperties().remove(name);
+            }  else {
+                System.setProperty(name, prevValue);
+            }
+        }
+
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
index 57b4ce9..238184e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
@@ -1,804 +1,804 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserCredentialValueModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserProvider;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.managers.RealmManager;
-
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class AdapterTest extends AbstractModelTest {
-    private RealmModel realmModel;
-
-    @Test
-    public void test1CreateRealm() throws Exception {
-        realmModel = realmManager.createRealm("JUGGLER");
-        realmModel.setAccessCodeLifespan(100);
-        realmModel.setAccessCodeLifespanUserAction(600);
-        realmModel.setEnabled(true);
-        realmModel.setName("JUGGLER");
-
-        KeyPair keyPair = generateKeypair();
-
-        realmModel.setPrivateKey(keyPair.getPrivate());
-        realmModel.setPublicKey(keyPair.getPublic());
-        realmModel.setAccessTokenLifespan(1000);
-        realmModel.addDefaultRole("foo");
-
-        session.getTransaction().commit();
-        resetSession();
-
-        realmModel = realmManager.getRealm(realmModel.getId());
-        assertNotNull(realmModel);
-        Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
-        Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
-        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
-        Assert.assertEquals(realmModel.isEnabled(), true);
-        Assert.assertEquals(realmModel.getName(), "JUGGLER");
-        Assert.assertArrayEquals(realmModel.getPrivateKey().getEncoded(), keyPair.getPrivate().getEncoded());
-        Assert.assertArrayEquals(realmModel.getPublicKey().getEncoded(), keyPair.getPublic().getEncoded());
-        Assert.assertEquals(1, realmModel.getDefaultRoles().size());
-        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
-    }
-
-    @Test
-    public void testRealmListing() throws Exception {
-        realmModel = realmManager.createRealm("JUGGLER");
-        realmModel.setAccessCodeLifespan(100);
-        realmModel.setAccessCodeLifespanUserAction(600);
-        realmModel.setEnabled(true);
-        realmModel.setName("JUGGLER");
-        KeyPair keyPair = generateKeypair();
-        realmModel.setPrivateKey(keyPair.getPrivate());
-        realmModel.setPublicKey(keyPair.getPublic());
-        realmModel.setAccessTokenLifespan(1000);
-        realmModel.addDefaultRole("foo");
-
-        realmModel = realmManager.getRealm(realmModel.getId());
-        assertNotNull(realmModel);
-        Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
-        Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
-        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
-        Assert.assertEquals(realmModel.isEnabled(), true);
-        Assert.assertEquals(realmModel.getName(), "JUGGLER");
-        Assert.assertArrayEquals(realmModel.getPrivateKey().getEncoded(), keyPair.getPrivate().getEncoded());
-        Assert.assertArrayEquals(realmModel.getPublicKey().getEncoded(), keyPair.getPublic().getEncoded());
-        Assert.assertEquals(1, realmModel.getDefaultRoles().size());
-        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
-
-        realmModel.getId();
-
-        commit();
-        List<RealmModel> realms = model.getRealms();
-        Assert.assertEquals(realms.size(), 2);
-    }
-
-
-    @Test
-    public void test2RequiredCredential() throws Exception {
-        test1CreateRealm();
-        realmModel.addRequiredCredential(CredentialRepresentation.PASSWORD);
-        List<RequiredCredentialModel> storedCreds = realmModel.getRequiredCredentials();
-        Assert.assertEquals(1, storedCreds.size());
-
-        Set<String> creds = new HashSet<String>();
-        creds.add(CredentialRepresentation.PASSWORD);
-        creds.add(CredentialRepresentation.TOTP);
-        realmModel.updateRequiredCredentials(creds);
-        storedCreds = realmModel.getRequiredCredentials();
-        Assert.assertEquals(2, storedCreds.size());
-        boolean totp = false;
-        boolean password = false;
-        for (RequiredCredentialModel cred : storedCreds) {
-            Assert.assertTrue(cred.isInput());
-            if (cred.getType().equals(CredentialRepresentation.PASSWORD)) {
-                password = true;
-                Assert.assertTrue(cred.isSecret());
-            } else if (cred.getType().equals(CredentialRepresentation.TOTP)) {
-                totp = true;
-                Assert.assertFalse(cred.isSecret());
-            }
-        }
-        Assert.assertTrue(totp);
-        Assert.assertTrue(password);
-    }
-
-    @Test
-    public void testCredentialValidation() throws Exception {
-        test1CreateRealm();
-        UserProvider userProvider = realmManager.getSession().users();
-        UserModel user = userProvider.addUser(realmModel, "bburke");
-        UserCredentialModel cred = new UserCredentialModel();
-        cred.setType(CredentialRepresentation.PASSWORD);
-        cred.setValue("geheim");
-        user.updateCredential(cred);
-        Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
-        List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
-        Assert.assertEquals(creds.get(0).getHashIterations(), 1);
-        realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(200)"));
-        Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
-        creds = user.getCredentialsDirectly();
-        Assert.assertEquals(creds.get(0).getHashIterations(), 200);
-        realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(1)"));
-    }
-
-    @Test
-    public void testDeleteUser() throws Exception {
-        test1CreateRealm();
-
-        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-        user.setSingleAttribute("attr1", "val1");
-        user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-
-        RoleModel testRole = realmModel.addRole("test");
-        user.grantRole(testRole);
-
-        ClientModel app = realmModel.addClient("test-app");
-        RoleModel appRole = app.addRole("test");
-        user.grantRole(appRole);
-
-        FederatedIdentityModel socialLink = new FederatedIdentityModel("google", "google1", user.getUsername());
-        realmManager.getSession().users().addFederatedIdentity(realmModel, user, socialLink);
-
-        UserCredentialModel cred = new UserCredentialModel();
-        cred.setType(CredentialRepresentation.PASSWORD);
-        cred.setValue("password");
-        user.updateCredential(cred);
-
-        commit();
-
-        realmModel = model.getRealm("JUGGLER");
-        Assert.assertTrue(realmManager.getSession().users().removeUser(realmModel, user));
-        assertNull(realmManager.getSession().users().getUserByUsername("bburke", realmModel));
-    }
-
-    @Test
-    public void testRemoveApplication() throws Exception {
-        test1CreateRealm();
-
-        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-
-        ClientModel client = realmModel.addClient("client");
-
-        ClientModel app = realmModel.addClient("test-app");
-
-        RoleModel appRole = app.addRole("test");
-        user.grantRole(appRole);
-        client.addScopeMapping(appRole);
-
-        RoleModel realmRole = realmModel.addRole("test");
-        app.addScopeMapping(realmRole);
-
-        Assert.assertTrue(realmModel.removeClient(app.getId()));
-        Assert.assertFalse(realmModel.removeClient(app.getId()));
-        assertNull(realmModel.getClientById(app.getId()));
-    }
-
-
-    @Test
-    public void testRemoveRealm() throws Exception {
-        test1CreateRealm();
-
-        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-
-        UserCredentialModel cred = new UserCredentialModel();
-        cred.setType(CredentialRepresentation.PASSWORD);
-        cred.setValue("password");
-        user.updateCredential(cred);
-
-        ClientModel client = realmModel.addClient("client");
-
-        ClientModel app = realmModel.addClient("test-app");
-
-        RoleModel appRole = app.addRole("test");
-        user.grantRole(appRole);
-        client.addScopeMapping(appRole);
-
-        RoleModel realmRole = realmModel.addRole("test");
-        RoleModel realmRole2 = realmModel.addRole("test2");
-        realmRole.addCompositeRole(realmRole2);
-        realmRole.addCompositeRole(appRole);
-
-        app.addScopeMapping(realmRole);
-
-        commit();
-        realmModel = model.getRealm("JUGGLER");
-
-        Assert.assertTrue(realmManager.removeRealm(realmModel));
-        Assert.assertFalse(realmManager.removeRealm(realmModel));
-        assertNull(realmManager.getRealm(realmModel.getId()));
-    }
-
-
-    @Test
-    public void testRemoveRole() throws Exception {
-        test1CreateRealm();
-
-        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-
-        ClientModel client = realmModel.addClient("client");
-
-        ClientModel app = realmModel.addClient("test-app");
-
-        RoleModel appRole = app.addRole("test");
-        user.grantRole(appRole);
-        client.addScopeMapping(appRole);
-
-        RoleModel realmRole = realmModel.addRole("test");
-        app.addScopeMapping(realmRole);
-
-        commit();
-        realmModel = model.getRealm("JUGGLER");
-        app = realmModel.getClientByClientId("test-app");
-        user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
-
-        Assert.assertTrue(realmModel.removeRoleById(realmRole.getId()));
-        Assert.assertFalse(realmModel.removeRoleById(realmRole.getId()));
-        assertNull(realmModel.getRole(realmRole.getName()));
-
-        Assert.assertTrue(realmModel.removeRoleById(appRole.getId()));
-        Assert.assertFalse(realmModel.removeRoleById(appRole.getId()));
-        assertNull(app.getRole(appRole.getName()));
-
-        user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
-
-    }
-
-    @Test
-    public void testUserSearch() throws Exception {
-        test1CreateRealm();
-        {
-            UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-            user.setLastName("Burke");
-            user.setFirstName("Bill");
-            user.setEmail("bburke@redhat.com");
-
-            UserModel user2 = realmManager.getSession().users().addUser(realmModel, "doublefirst");
-            user2.setFirstName("Knut Ole");
-            user2.setLastName("Alver");
-            user2.setEmail("knut@redhat.com");
-
-            UserModel user3 = realmManager.getSession().users().addUser(realmModel, "doublelast");
-            user3.setFirstName("Ole");
-            user3.setLastName("Alver Veland");
-            user3.setEmail("knut2@redhat.com");
-        }
-
-        RealmManager adapter = realmManager;
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("total junk query", realmModel);
-            Assert.assertEquals(userModels.size(), 0);
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("Bill Burke", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("bill burk", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            ArrayList<String> users = new ArrayList<String>();
-            for (UserModel u : adapter.searchUsers("ole alver", realmModel)) {
-                users.add(u.getUsername());
-            }
-            String[] usernames = users.toArray(new String[users.size()]);
-            Arrays.sort(usernames);
-            Assert.assertArrayEquals(new String[]{"doublefirst", "doublelast"}, usernames);
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("bburke@redhat.com", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("rke@redhat.com", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("bburke", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("BurK", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("Burke", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Bill");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
-        }
-
-        {
-            UserModel user = realmManager.getSession().users().addUser(realmModel, "mburke");
-            user.setLastName("Burke");
-            user.setFirstName("Monica");
-            user.setEmail("mburke@redhat.com");
-        }
-
-        {
-            UserModel user = realmManager.getSession().users().addUser(realmModel, "thor");
-            user.setLastName("Thorgersen");
-            user.setFirstName("Stian");
-            user.setEmail("thor@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("Monica Burke", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Monica");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
-        }
-
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("mburke@redhat.com", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Monica");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("mburke", realmModel);
-            Assert.assertEquals(userModels.size(), 1);
-            UserModel bburke = userModels.get(0);
-            Assert.assertEquals(bburke.getFirstName(), "Monica");
-            Assert.assertEquals(bburke.getLastName(), "Burke");
-            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
-        }
-
-        {
-            List<UserModel> userModels = adapter.searchUsers("Burke", realmModel);
-            Assert.assertEquals(userModels.size(), 2);
-            UserModel first = userModels.get(0);
-            UserModel second = userModels.get(1);
-            if (!first.getEmail().equals("bburke@redhat.com") && !second.getEmail().equals("bburke@redhat.com")) {
-                Assert.fail();
-            }
-            if (!first.getEmail().equals("mburke@redhat.com") && !second.getEmail().equals("mburke@redhat.com")) {
-                Assert.fail();
-            }
-        }
-
-        RealmModel otherRealm = adapter.createRealm("other");
-        realmManager.getSession().users().addUser(otherRealm, "bburke");
-
-        Assert.assertEquals(1, realmManager.getSession().users().getUsers(otherRealm).size());
-        Assert.assertEquals(1, realmManager.getSession().users().searchForUser("bu", otherRealm).size());
-    }
-
-
-    @Test
-    public void testRoles() throws Exception {
-        test1CreateRealm();
-        realmModel.addRole("admin");
-        realmModel.addRole("user");
-        Set<RoleModel> roles = realmModel.getRoles();
-        Assert.assertEquals(3, roles.size());
-        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
-        RoleModel realmUserRole = realmModel.getRole("user");
-        user.grantRole(realmUserRole);
-        Assert.assertTrue(user.hasRole(realmUserRole));
-        RoleModel found = realmModel.getRoleById(realmUserRole.getId());
-        assertNotNull(found);
-        assertRolesEquals(found, realmUserRole);
-
-        // Test app roles
-        ClientModel application = realmModel.addClient("app1");
-        application.addRole("user");
-        application.addRole("bar");
-        Set<RoleModel> appRoles = application.getRoles();
-        Assert.assertEquals(2, appRoles.size());
-        RoleModel appBarRole = application.getRole("bar");
-        assertNotNull(appBarRole);
-
-        found = realmModel.getRoleById(appBarRole.getId());
-        assertNotNull(found);
-        assertRolesEquals(found, appBarRole);
-
-        user.grantRole(appBarRole);
-        user.grantRole(application.getRole("user"));
-
-        roles = user.getRealmRoleMappings();
-        Assert.assertEquals(roles.size(), 2);
-        assertRolesContains(realmUserRole, roles);
-        Assert.assertTrue(user.hasRole(realmUserRole));
-        // Role "foo" is default realm role
-        Assert.assertTrue(user.hasRole(realmModel.getRole("foo")));
-
-        roles = user.getClientRoleMappings(application);
-        Assert.assertEquals(roles.size(), 2);
-        assertRolesContains(application.getRole("user"), roles);
-        assertRolesContains(appBarRole, roles);
-        Assert.assertTrue(user.hasRole(appBarRole));
-
-        // Test that application role 'user' don't clash with realm role 'user'
-        Assert.assertNotEquals(realmModel.getRole("user").getId(), application.getRole("user").getId());
-
-        Assert.assertEquals(6, user.getRoleMappings().size());
-
-        // Revoke some roles
-        user.deleteRoleMapping(realmModel.getRole("foo"));
-        user.deleteRoleMapping(appBarRole);
-        roles = user.getRoleMappings();
-        Assert.assertEquals(4, roles.size());
-        assertRolesContains(realmUserRole, roles);
-        assertRolesContains(application.getRole("user"), roles);
-        Assert.assertFalse(user.hasRole(appBarRole));
-    }
-
-    @Test
-    public void testScopes() throws Exception {
-        test1CreateRealm();
-        RoleModel realmRole = realmModel.addRole("realm");
-
-        ClientModel app1 = realmModel.addClient("app1");
-        RoleModel appRole = app1.addRole("app");
-
-        ClientModel app2 = realmModel.addClient("app2");
-        app2.addScopeMapping(realmRole);
-        app2.addScopeMapping(appRole);
-
-        ClientModel client = realmModel.addClient("client");
-        client.addScopeMapping(realmRole);
-        client.addScopeMapping(appRole);
-
-        commit();
-
-        realmModel = model.getRealmByName("JUGGLER");
-        app1 = realmModel.getClientByClientId("app1");
-        app2 = realmModel.getClientByClientId("app2");
-        client = realmModel.getClientByClientId("client");
-
-        Set<RoleModel> scopeMappings = app2.getScopeMappings();
-        Assert.assertEquals(2, scopeMappings.size());
-        Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
-        Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
-
-        scopeMappings = client.getScopeMappings();
-        Assert.assertEquals(2, scopeMappings.size());
-        Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
-        Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
-    }
-
-    @Test
-    public void testRealmNameCollisions() throws Exception {
-        test1CreateRealm();
-
-        commit();
-
-        // Try to create realm with duplicate name
-        try {
-            test1CreateRealm();
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Try to rename realm to duplicate name
-        realmManager.createRealm("JUGGLER2");
-        commit();
-        try {
-            realmManager.getRealmByName("JUGGLER2").setName("JUGGLER");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testAppNameCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addClient("app1");
-        realmManager.createRealm("JUGGLER2").addClient("app1");
-
-        commit();
-
-        // Try to create app with duplicate name
-        try {
-            realmManager.getRealmByName("JUGGLER1").addClient("app1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Ty to rename app to duplicate name
-        realmManager.getRealmByName("JUGGLER1").addClient("app2");
-        commit();
-        try {
-            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app2").setClientId("app1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testClientNameCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addClient("client1");
-        realmManager.createRealm("JUGGLER2").addClient("client1");
-
-        commit();
-
-        // Try to create app with duplicate name
-        try {
-            realmManager.getRealmByName("JUGGLER1").addClient("client1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Ty to rename app to duplicate name
-        realmManager.getRealmByName("JUGGLER1").addClient("client2");
-        commit();
-        try {
-            realmManager.getRealmByName("JUGGLER1").addClient("client2").setClientId("client1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testUsernameCollisions() throws Exception {
-        RealmModel juggler1 = realmManager.createRealm("JUGGLER1");
-        realmManager.getSession().users().addUser(juggler1, "user1");
-        RealmModel juggler2 = realmManager.createRealm("JUGGLER2");
-        realmManager.getSession().users().addUser(juggler2, "user1");
-        commit();
-
-        // Try to create user with duplicate login name
-        try {
-            juggler1 = realmManager.getRealmByName("JUGGLER1");
-            realmManager.getSession().users().addUser(juggler1, "user1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Ty to rename user to duplicate login name
-        juggler1 = realmManager.getRealmByName("JUGGLER1");
-        realmManager.getSession().users().addUser(juggler1, "user2");
-        commit();
-        try {
-            juggler1 = realmManager.getRealmByName("JUGGLER1");
-            realmManager.getSession().users().getUserByUsername("user2", juggler1).setUsername("user1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testEmailCollisions() throws Exception {
-        RealmModel juggler1 = realmManager.createRealm("JUGGLER1");
-        realmManager.getSession().users().addUser(juggler1, "user1").setEmail("email@example.com");
-        RealmModel juggler2 = realmManager.createRealm("JUGGLER2");
-        realmManager.getSession().users().addUser(juggler2, "user1").setEmail("email@example.com");
-        commit();
-
-        // Try to create user with duplicate email
-        juggler1 = realmManager.getRealmByName("JUGGLER1");
-        try {
-            realmManager.getSession().users().addUser(juggler1, "user2").setEmail("email@example.com");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-
-        // Ty to rename user to duplicate email
-        juggler1 = realmManager.getRealmByName("JUGGLER1");
-        realmManager.getSession().users().addUser(juggler1, "user3").setEmail("email2@example.com");
-        commit();
-        try {
-            juggler1 = realmManager.getRealmByName("JUGGLER1");
-            realmManager.getSession().users().getUserByUsername("user3", juggler1).setEmail("email@example.com");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testAppRoleCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
-
-        commit();
-
-        // Try to add role with same name
-        try {
-            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Ty to rename role to duplicate name
-        realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role2");
-        commit();
-        try {
-            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").getRole("role2").setName("role1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testRealmRoleCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
-
-        commit();
-
-        // Try to add role with same name
-        try {
-            realmManager.getRealmByName("JUGGLER1").addRole("role1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Ty to rename role to duplicate name
-        realmManager.getRealmByName("JUGGLER1").addRole("role2");
-        commit();
-        try {
-            realmManager.getRealmByName("JUGGLER1").getRole("role2").setName("role1");
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-
-        resetSession();
-    }
-
-    @Test
-    public void testUserFederationProviderDisplayNameCollisions() throws Exception {
-        RealmModel realm = realmManager.createRealm("JUGGLER1");
-        Map<String, String> cfg = Collections.emptyMap();
-        realm.addUserFederationProvider("ldap", cfg, 1, "providerName1", -1, -1, 0);
-        realm.addUserFederationProvider("ldap", cfg, 1, "providerName2", -1, -1, 0);
-
-        commit();
-
-        // Try to add federation provider with same display name
-        try {
-            realmManager.getRealmByName("JUGGLER1").addUserFederationProvider("ldap", cfg, 1, "providerName1", -1, -1, 0);
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Try to rename federation provider tu duplicate display name
-        try {
-            List<UserFederationProviderModel> fedProviders = realmManager.getRealmByName("JUGGLER1").getUserFederationProviders();
-            for (UserFederationProviderModel fedProvider : fedProviders) {
-                if ("providerName1".equals(fedProvider.getDisplayName())) {
-                    fedProvider.setDisplayName("providerName2");
-                    realm.updateUserFederationProvider(fedProvider);
-                    break;
-                }
-            }
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-        // Try to rename federation provider tu duplicate display name
-        try {
-            List<UserFederationProviderModel> fedProviders = realmManager.getRealmByName("JUGGLER1").getUserFederationProviders();
-            for (UserFederationProviderModel fedProvider : fedProviders) {
-                if ("providerName1".equals(fedProvider.getDisplayName())) {
-                    fedProvider.setDisplayName("providerName2");
-                    break;
-                }
-            }
-
-            realm.setUserFederationProviders(fedProviders);
-            commit();
-            Assert.fail("Expected exception");
-        } catch (ModelDuplicateException e) {
-        }
-        commit(true);
-
-    }
-
-    private KeyPair generateKeypair() throws NoSuchAlgorithmException {
-        return KeyPairGenerator.getInstance("RSA").generateKeyPair();
-    }
-
-}
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserProvider;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.RealmManager;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class AdapterTest extends AbstractModelTest {
+    private RealmModel realmModel;
+
+    @Test
+    public void test1CreateRealm() throws Exception {
+        realmModel = realmManager.createRealm("JUGGLER");
+        realmModel.setAccessCodeLifespan(100);
+        realmModel.setAccessCodeLifespanUserAction(600);
+        realmModel.setEnabled(true);
+        realmModel.setName("JUGGLER");
+
+        KeyPair keyPair = generateKeypair();
+
+        realmModel.setPrivateKey(keyPair.getPrivate());
+        realmModel.setPublicKey(keyPair.getPublic());
+        realmModel.setAccessTokenLifespan(1000);
+        realmModel.addDefaultRole("foo");
+
+        session.getTransaction().commit();
+        resetSession();
+
+        realmModel = realmManager.getRealm(realmModel.getId());
+        assertNotNull(realmModel);
+        Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
+        Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
+        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
+        Assert.assertEquals(realmModel.isEnabled(), true);
+        Assert.assertEquals(realmModel.getName(), "JUGGLER");
+        Assert.assertArrayEquals(realmModel.getPrivateKey().getEncoded(), keyPair.getPrivate().getEncoded());
+        Assert.assertArrayEquals(realmModel.getPublicKey().getEncoded(), keyPair.getPublic().getEncoded());
+        Assert.assertEquals(1, realmModel.getDefaultRoles().size());
+        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
+    }
+
+    @Test
+    public void testRealmListing() throws Exception {
+        realmModel = realmManager.createRealm("JUGGLER");
+        realmModel.setAccessCodeLifespan(100);
+        realmModel.setAccessCodeLifespanUserAction(600);
+        realmModel.setEnabled(true);
+        realmModel.setName("JUGGLER");
+        KeyPair keyPair = generateKeypair();
+        realmModel.setPrivateKey(keyPair.getPrivate());
+        realmModel.setPublicKey(keyPair.getPublic());
+        realmModel.setAccessTokenLifespan(1000);
+        realmModel.addDefaultRole("foo");
+
+        realmModel = realmManager.getRealm(realmModel.getId());
+        assertNotNull(realmModel);
+        Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
+        Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());
+        Assert.assertEquals(realmModel.getAccessTokenLifespan(), 1000);
+        Assert.assertEquals(realmModel.isEnabled(), true);
+        Assert.assertEquals(realmModel.getName(), "JUGGLER");
+        Assert.assertArrayEquals(realmModel.getPrivateKey().getEncoded(), keyPair.getPrivate().getEncoded());
+        Assert.assertArrayEquals(realmModel.getPublicKey().getEncoded(), keyPair.getPublic().getEncoded());
+        Assert.assertEquals(1, realmModel.getDefaultRoles().size());
+        Assert.assertEquals("foo", realmModel.getDefaultRoles().get(0));
+
+        realmModel.getId();
+
+        commit();
+        List<RealmModel> realms = model.getRealms();
+        Assert.assertEquals(realms.size(), 2);
+    }
+
+
+    @Test
+    public void test2RequiredCredential() throws Exception {
+        test1CreateRealm();
+        realmModel.addRequiredCredential(CredentialRepresentation.PASSWORD);
+        List<RequiredCredentialModel> storedCreds = realmModel.getRequiredCredentials();
+        Assert.assertEquals(1, storedCreds.size());
+
+        Set<String> creds = new HashSet<String>();
+        creds.add(CredentialRepresentation.PASSWORD);
+        creds.add(CredentialRepresentation.TOTP);
+        realmModel.updateRequiredCredentials(creds);
+        storedCreds = realmModel.getRequiredCredentials();
+        Assert.assertEquals(2, storedCreds.size());
+        boolean totp = false;
+        boolean password = false;
+        for (RequiredCredentialModel cred : storedCreds) {
+            Assert.assertTrue(cred.isInput());
+            if (cred.getType().equals(CredentialRepresentation.PASSWORD)) {
+                password = true;
+                Assert.assertTrue(cred.isSecret());
+            } else if (cred.getType().equals(CredentialRepresentation.TOTP)) {
+                totp = true;
+                Assert.assertFalse(cred.isSecret());
+            }
+        }
+        Assert.assertTrue(totp);
+        Assert.assertTrue(password);
+    }
+
+    @Test
+    public void testCredentialValidation() throws Exception {
+        test1CreateRealm();
+        UserProvider userProvider = realmManager.getSession().users();
+        UserModel user = userProvider.addUser(realmModel, "bburke");
+        UserCredentialModel cred = new UserCredentialModel();
+        cred.setType(CredentialRepresentation.PASSWORD);
+        cred.setValue("geheim");
+        user.updateCredential(cred);
+        Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
+        List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
+        Assert.assertEquals(creds.get(0).getHashIterations(), 1);
+        realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(200)"));
+        Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
+        creds = user.getCredentialsDirectly();
+        Assert.assertEquals(creds.get(0).getHashIterations(), 200);
+        realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(1)"));
+    }
+
+    @Test
+    public void testDeleteUser() throws Exception {
+        test1CreateRealm();
+
+        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+        user.setSingleAttribute("attr1", "val1");
+        user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+
+        RoleModel testRole = realmModel.addRole("test");
+        user.grantRole(testRole);
+
+        ClientModel app = realmModel.addClient("test-app");
+        RoleModel appRole = app.addRole("test");
+        user.grantRole(appRole);
+
+        FederatedIdentityModel socialLink = new FederatedIdentityModel("google", "google1", user.getUsername());
+        realmManager.getSession().users().addFederatedIdentity(realmModel, user, socialLink);
+
+        UserCredentialModel cred = new UserCredentialModel();
+        cred.setType(CredentialRepresentation.PASSWORD);
+        cred.setValue("password");
+        user.updateCredential(cred);
+
+        commit();
+
+        realmModel = model.getRealm("JUGGLER");
+        Assert.assertTrue(realmManager.getSession().users().removeUser(realmModel, user));
+        assertNull(realmManager.getSession().users().getUserByUsername("bburke", realmModel));
+    }
+
+    @Test
+    public void testRemoveApplication() throws Exception {
+        test1CreateRealm();
+
+        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+
+        ClientModel client = realmModel.addClient("client");
+
+        ClientModel app = realmModel.addClient("test-app");
+
+        RoleModel appRole = app.addRole("test");
+        user.grantRole(appRole);
+        client.addScopeMapping(appRole);
+
+        RoleModel realmRole = realmModel.addRole("test");
+        app.addScopeMapping(realmRole);
+
+        Assert.assertTrue(realmModel.removeClient(app.getId()));
+        Assert.assertFalse(realmModel.removeClient(app.getId()));
+        assertNull(realmModel.getClientById(app.getId()));
+    }
+
+
+    @Test
+    public void testRemoveRealm() throws Exception {
+        test1CreateRealm();
+
+        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+
+        UserCredentialModel cred = new UserCredentialModel();
+        cred.setType(CredentialRepresentation.PASSWORD);
+        cred.setValue("password");
+        user.updateCredential(cred);
+
+        ClientModel client = realmModel.addClient("client");
+
+        ClientModel app = realmModel.addClient("test-app");
+
+        RoleModel appRole = app.addRole("test");
+        user.grantRole(appRole);
+        client.addScopeMapping(appRole);
+
+        RoleModel realmRole = realmModel.addRole("test");
+        RoleModel realmRole2 = realmModel.addRole("test2");
+        realmRole.addCompositeRole(realmRole2);
+        realmRole.addCompositeRole(appRole);
+
+        app.addScopeMapping(realmRole);
+
+        commit();
+        realmModel = model.getRealm("JUGGLER");
+
+        Assert.assertTrue(realmManager.removeRealm(realmModel));
+        Assert.assertFalse(realmManager.removeRealm(realmModel));
+        assertNull(realmManager.getRealm(realmModel.getId()));
+    }
+
+
+    @Test
+    public void testRemoveRole() throws Exception {
+        test1CreateRealm();
+
+        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+
+        ClientModel client = realmModel.addClient("client");
+
+        ClientModel app = realmModel.addClient("test-app");
+
+        RoleModel appRole = app.addRole("test");
+        user.grantRole(appRole);
+        client.addScopeMapping(appRole);
+
+        RoleModel realmRole = realmModel.addRole("test");
+        app.addScopeMapping(realmRole);
+
+        commit();
+        realmModel = model.getRealm("JUGGLER");
+        app = realmModel.getClientByClientId("test-app");
+        user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
+
+        Assert.assertTrue(realmModel.removeRoleById(realmRole.getId()));
+        Assert.assertFalse(realmModel.removeRoleById(realmRole.getId()));
+        assertNull(realmModel.getRole(realmRole.getName()));
+
+        Assert.assertTrue(realmModel.removeRoleById(appRole.getId()));
+        Assert.assertFalse(realmModel.removeRoleById(appRole.getId()));
+        assertNull(app.getRole(appRole.getName()));
+
+        user = realmManager.getSession().users().getUserByUsername("bburke", realmModel);
+
+    }
+
+    @Test
+    public void testUserSearch() throws Exception {
+        test1CreateRealm();
+        {
+            UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+            user.setLastName("Burke");
+            user.setFirstName("Bill");
+            user.setEmail("bburke@redhat.com");
+
+            UserModel user2 = realmManager.getSession().users().addUser(realmModel, "doublefirst");
+            user2.setFirstName("Knut Ole");
+            user2.setLastName("Alver");
+            user2.setEmail("knut@redhat.com");
+
+            UserModel user3 = realmManager.getSession().users().addUser(realmModel, "doublelast");
+            user3.setFirstName("Ole");
+            user3.setLastName("Alver Veland");
+            user3.setEmail("knut2@redhat.com");
+        }
+
+        RealmManager adapter = realmManager;
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("total junk query", realmModel);
+            Assert.assertEquals(userModels.size(), 0);
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("Bill Burke", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("bill burk", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            ArrayList<String> users = new ArrayList<String>();
+            for (UserModel u : adapter.searchUsers("ole alver", realmModel)) {
+                users.add(u.getUsername());
+            }
+            String[] usernames = users.toArray(new String[users.size()]);
+            Arrays.sort(usernames);
+            Assert.assertArrayEquals(new String[]{"doublefirst", "doublelast"}, usernames);
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("bburke@redhat.com", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("rke@redhat.com", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("bburke", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("BurK", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("Burke", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Bill");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "bburke@redhat.com");
+        }
+
+        {
+            UserModel user = realmManager.getSession().users().addUser(realmModel, "mburke");
+            user.setLastName("Burke");
+            user.setFirstName("Monica");
+            user.setEmail("mburke@redhat.com");
+        }
+
+        {
+            UserModel user = realmManager.getSession().users().addUser(realmModel, "thor");
+            user.setLastName("Thorgersen");
+            user.setFirstName("Stian");
+            user.setEmail("thor@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("Monica Burke", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Monica");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
+        }
+
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("mburke@redhat.com", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Monica");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("mburke", realmModel);
+            Assert.assertEquals(userModels.size(), 1);
+            UserModel bburke = userModels.get(0);
+            Assert.assertEquals(bburke.getFirstName(), "Monica");
+            Assert.assertEquals(bburke.getLastName(), "Burke");
+            Assert.assertEquals(bburke.getEmail(), "mburke@redhat.com");
+        }
+
+        {
+            List<UserModel> userModels = adapter.searchUsers("Burke", realmModel);
+            Assert.assertEquals(userModels.size(), 2);
+            UserModel first = userModels.get(0);
+            UserModel second = userModels.get(1);
+            if (!first.getEmail().equals("bburke@redhat.com") && !second.getEmail().equals("bburke@redhat.com")) {
+                Assert.fail();
+            }
+            if (!first.getEmail().equals("mburke@redhat.com") && !second.getEmail().equals("mburke@redhat.com")) {
+                Assert.fail();
+            }
+        }
+
+        RealmModel otherRealm = adapter.createRealm("other");
+        realmManager.getSession().users().addUser(otherRealm, "bburke");
+
+        Assert.assertEquals(1, realmManager.getSession().users().getUsers(otherRealm).size());
+        Assert.assertEquals(1, realmManager.getSession().users().searchForUser("bu", otherRealm).size());
+    }
+
+
+    @Test
+    public void testRoles() throws Exception {
+        test1CreateRealm();
+        realmModel.addRole("admin");
+        realmModel.addRole("user");
+        Set<RoleModel> roles = realmModel.getRoles();
+        Assert.assertEquals(3, roles.size());
+        UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
+        RoleModel realmUserRole = realmModel.getRole("user");
+        user.grantRole(realmUserRole);
+        Assert.assertTrue(user.hasRole(realmUserRole));
+        RoleModel found = realmModel.getRoleById(realmUserRole.getId());
+        assertNotNull(found);
+        assertRolesEquals(found, realmUserRole);
+
+        // Test app roles
+        ClientModel application = realmModel.addClient("app1");
+        application.addRole("user");
+        application.addRole("bar");
+        Set<RoleModel> appRoles = application.getRoles();
+        Assert.assertEquals(2, appRoles.size());
+        RoleModel appBarRole = application.getRole("bar");
+        assertNotNull(appBarRole);
+
+        found = realmModel.getRoleById(appBarRole.getId());
+        assertNotNull(found);
+        assertRolesEquals(found, appBarRole);
+
+        user.grantRole(appBarRole);
+        user.grantRole(application.getRole("user"));
+
+        roles = user.getRealmRoleMappings();
+        Assert.assertEquals(roles.size(), 2);
+        assertRolesContains(realmUserRole, roles);
+        Assert.assertTrue(user.hasRole(realmUserRole));
+        // Role "foo" is default realm role
+        Assert.assertTrue(user.hasRole(realmModel.getRole("foo")));
+
+        roles = user.getClientRoleMappings(application);
+        Assert.assertEquals(roles.size(), 2);
+        assertRolesContains(application.getRole("user"), roles);
+        assertRolesContains(appBarRole, roles);
+        Assert.assertTrue(user.hasRole(appBarRole));
+
+        // Test that application role 'user' don't clash with realm role 'user'
+        Assert.assertNotEquals(realmModel.getRole("user").getId(), application.getRole("user").getId());
+
+        Assert.assertEquals(6, user.getRoleMappings().size());
+
+        // Revoke some roles
+        user.deleteRoleMapping(realmModel.getRole("foo"));
+        user.deleteRoleMapping(appBarRole);
+        roles = user.getRoleMappings();
+        Assert.assertEquals(4, roles.size());
+        assertRolesContains(realmUserRole, roles);
+        assertRolesContains(application.getRole("user"), roles);
+        Assert.assertFalse(user.hasRole(appBarRole));
+    }
+
+    @Test
+    public void testScopes() throws Exception {
+        test1CreateRealm();
+        RoleModel realmRole = realmModel.addRole("realm");
+
+        ClientModel app1 = realmModel.addClient("app1");
+        RoleModel appRole = app1.addRole("app");
+
+        ClientModel app2 = realmModel.addClient("app2");
+        app2.addScopeMapping(realmRole);
+        app2.addScopeMapping(appRole);
+
+        ClientModel client = realmModel.addClient("client");
+        client.addScopeMapping(realmRole);
+        client.addScopeMapping(appRole);
+
+        commit();
+
+        realmModel = model.getRealmByName("JUGGLER");
+        app1 = realmModel.getClientByClientId("app1");
+        app2 = realmModel.getClientByClientId("app2");
+        client = realmModel.getClientByClientId("client");
+
+        Set<RoleModel> scopeMappings = app2.getScopeMappings();
+        Assert.assertEquals(2, scopeMappings.size());
+        Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
+        Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
+
+        scopeMappings = client.getScopeMappings();
+        Assert.assertEquals(2, scopeMappings.size());
+        Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
+        Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
+    }
+
+    @Test
+    public void testRealmNameCollisions() throws Exception {
+        test1CreateRealm();
+
+        commit();
+
+        // Try to create realm with duplicate name
+        try {
+            test1CreateRealm();
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Try to rename realm to duplicate name
+        realmManager.createRealm("JUGGLER2");
+        commit();
+        try {
+            realmManager.getRealmByName("JUGGLER2").setName("JUGGLER");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testAppNameCollisions() throws Exception {
+        realmManager.createRealm("JUGGLER1").addClient("app1");
+        realmManager.createRealm("JUGGLER2").addClient("app1");
+
+        commit();
+
+        // Try to create app with duplicate name
+        try {
+            realmManager.getRealmByName("JUGGLER1").addClient("app1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Ty to rename app to duplicate name
+        realmManager.getRealmByName("JUGGLER1").addClient("app2");
+        commit();
+        try {
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app2").setClientId("app1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testClientNameCollisions() throws Exception {
+        realmManager.createRealm("JUGGLER1").addClient("client1");
+        realmManager.createRealm("JUGGLER2").addClient("client1");
+
+        commit();
+
+        // Try to create app with duplicate name
+        try {
+            realmManager.getRealmByName("JUGGLER1").addClient("client1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Ty to rename app to duplicate name
+        realmManager.getRealmByName("JUGGLER1").addClient("client2");
+        commit();
+        try {
+            realmManager.getRealmByName("JUGGLER1").addClient("client2").setClientId("client1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testUsernameCollisions() throws Exception {
+        RealmModel juggler1 = realmManager.createRealm("JUGGLER1");
+        realmManager.getSession().users().addUser(juggler1, "user1");
+        RealmModel juggler2 = realmManager.createRealm("JUGGLER2");
+        realmManager.getSession().users().addUser(juggler2, "user1");
+        commit();
+
+        // Try to create user with duplicate login name
+        try {
+            juggler1 = realmManager.getRealmByName("JUGGLER1");
+            realmManager.getSession().users().addUser(juggler1, "user1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Ty to rename user to duplicate login name
+        juggler1 = realmManager.getRealmByName("JUGGLER1");
+        realmManager.getSession().users().addUser(juggler1, "user2");
+        commit();
+        try {
+            juggler1 = realmManager.getRealmByName("JUGGLER1");
+            realmManager.getSession().users().getUserByUsername("user2", juggler1).setUsername("user1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testEmailCollisions() throws Exception {
+        RealmModel juggler1 = realmManager.createRealm("JUGGLER1");
+        realmManager.getSession().users().addUser(juggler1, "user1").setEmail("email@example.com");
+        RealmModel juggler2 = realmManager.createRealm("JUGGLER2");
+        realmManager.getSession().users().addUser(juggler2, "user1").setEmail("email@example.com");
+        commit();
+
+        // Try to create user with duplicate email
+        juggler1 = realmManager.getRealmByName("JUGGLER1");
+        try {
+            realmManager.getSession().users().addUser(juggler1, "user2").setEmail("email@example.com");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+
+        // Ty to rename user to duplicate email
+        juggler1 = realmManager.getRealmByName("JUGGLER1");
+        realmManager.getSession().users().addUser(juggler1, "user3").setEmail("email2@example.com");
+        commit();
+        try {
+            juggler1 = realmManager.getRealmByName("JUGGLER1");
+            realmManager.getSession().users().getUserByUsername("user3", juggler1).setEmail("email@example.com");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testAppRoleCollisions() throws Exception {
+        realmManager.createRealm("JUGGLER1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
+
+        commit();
+
+        // Try to add role with same name
+        try {
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Ty to rename role to duplicate name
+        realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role2");
+        commit();
+        try {
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").getRole("role2").setName("role1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testRealmRoleCollisions() throws Exception {
+        realmManager.createRealm("JUGGLER1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
+
+        commit();
+
+        // Try to add role with same name
+        try {
+            realmManager.getRealmByName("JUGGLER1").addRole("role1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Ty to rename role to duplicate name
+        realmManager.getRealmByName("JUGGLER1").addRole("role2");
+        commit();
+        try {
+            realmManager.getRealmByName("JUGGLER1").getRole("role2").setName("role1");
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+
+        resetSession();
+    }
+
+    @Test
+    public void testUserFederationProviderDisplayNameCollisions() throws Exception {
+        RealmModel realm = realmManager.createRealm("JUGGLER1");
+        Map<String, String> cfg = Collections.emptyMap();
+        realm.addUserFederationProvider("ldap", cfg, 1, "providerName1", -1, -1, 0);
+        realm.addUserFederationProvider("ldap", cfg, 1, "providerName2", -1, -1, 0);
+
+        commit();
+
+        // Try to add federation provider with same display name
+        try {
+            realmManager.getRealmByName("JUGGLER1").addUserFederationProvider("ldap", cfg, 1, "providerName1", -1, -1, 0);
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Try to rename federation provider tu duplicate display name
+        try {
+            List<UserFederationProviderModel> fedProviders = realmManager.getRealmByName("JUGGLER1").getUserFederationProviders();
+            for (UserFederationProviderModel fedProvider : fedProviders) {
+                if ("providerName1".equals(fedProvider.getDisplayName())) {
+                    fedProvider.setDisplayName("providerName2");
+                    realm.updateUserFederationProvider(fedProvider);
+                    break;
+                }
+            }
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+        // Try to rename federation provider tu duplicate display name
+        try {
+            List<UserFederationProviderModel> fedProviders = realmManager.getRealmByName("JUGGLER1").getUserFederationProviders();
+            for (UserFederationProviderModel fedProvider : fedProviders) {
+                if ("providerName1".equals(fedProvider.getDisplayName())) {
+                    fedProvider.setDisplayName("providerName2");
+                    break;
+                }
+            }
+
+            realm.setUserFederationProviders(fedProviders);
+            commit();
+            Assert.fail("Expected exception");
+        } catch (ModelDuplicateException e) {
+        }
+        commit(true);
+
+    }
+
+    private KeyPair generateKeypair() throws NoSuchAlgorithmException {
+        return KeyPairGenerator.getInstance("RSA").generateKeyPair();
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java
index 15aeffa..11e1887 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java
@@ -1,288 +1,288 @@
-package org.keycloak.testsuite.model;
-
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.ClientConnection;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserModel.RequiredAction;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.TimeBasedOTP;
-import org.keycloak.representations.PasswordToken;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
-import org.keycloak.services.managers.BruteForceProtector;
-import org.keycloak.util.Time;
-
-import javax.ws.rs.core.MultivaluedMap;
-import java.util.UUID;
-
-public class AuthenticationManagerTest extends AbstractModelTest {
-
-    private AuthenticationManager am;
-    private MultivaluedMap<String, String> formData;
-    private TimeBasedOTP otp;
-    private RealmModel realm;
-    private UserModel user;
-    private BruteForceProtector protector;
-    private ClientConnection dummyConnection = new ClientConnection() {
-        @Override
-        public String getRemoteAddr() {
-            return "127.0.0.1";
-
-        }
-
-        @Override
-        public String getRemoteHost() {
-            return "localhost";
-
-        }
-
-        @Override
-        public int getReportPort() {
-            return 8080;
-        }
-    };
-
-    @Test
-    public void authForm() {
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
-    }
-
-    @Test
-    public void authFormInvalidPassword() {
-        formData.remove(CredentialRepresentation.PASSWORD);
-        formData.add(CredentialRepresentation.PASSWORD, "invalid");
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormMissingUsername() {
-        formData.remove("username");
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_USER, status);
-    }
-
-    @Test
-    public void authFormMissingPassword() {
-        formData.remove(CredentialRepresentation.PASSWORD);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.MISSING_PASSWORD, status);
-    }
-
-    @Test
-    public void authFormRequiredAction() {
-        realm.addRequiredCredential(CredentialRepresentation.TOTP);
-        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.ACTIONS_REQUIRED, status);
-    }
-
-    @Test
-    public void authFormUserDisabled() {
-        user.setEnabled(false);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.ACCOUNT_DISABLED, status);
-    }
-
-    @Test
-    public void authFormWithTotp() {
-        realm.addRequiredCredential(CredentialRepresentation.TOTP);
-
-        String totpSecret = UUID.randomUUID().toString();
-
-        UserCredentialModel credential = new UserCredentialModel();
-        credential.setType(CredentialRepresentation.TOTP);
-        credential.setValue(totpSecret);
-
-        user.updateCredential(credential);
-
-        user.setTotp(true);
-
-        String token = otp.generate(totpSecret);
-
-        formData.add(CredentialRepresentation.TOTP, token);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
-    }
-
-    @Test
-    public void authFormWithTotpInvalidPassword() {
-        authFormWithTotp();
-
-        formData.remove(CredentialRepresentation.PASSWORD);
-        formData.add(CredentialRepresentation.PASSWORD, "invalid");
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormWithTotpMissingPassword() {
-        authFormWithTotp();
-
-        formData.remove(CredentialRepresentation.PASSWORD);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.MISSING_PASSWORD, status);
-    }
-
-    @Test
-    public void authFormWithTotpInvalidTotp() {
-        authFormWithTotp();
-
-        formData.remove(CredentialRepresentation.TOTP);
-        formData.add(CredentialRepresentation.TOTP, "invalid");
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormWithTotpMissingTotp() {
-        authFormWithTotp();
-
-        formData.remove(CredentialRepresentation.TOTP);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.MISSING_TOTP, status);
-    }
-
-    @Test
-    public void authFormWithTotpPasswordToken() {
-        realm.addRequiredCredential(CredentialRepresentation.TOTP);
-
-        String totpSecret = UUID.randomUUID().toString();
-
-        UserCredentialModel credential = new UserCredentialModel();
-        credential.setType(CredentialRepresentation.TOTP);
-        credential.setValue(totpSecret);
-
-        user.updateCredential(credential);
-
-        user.setTotp(true);
-
-        String token = otp.generate(totpSecret);
-
-        formData.add(CredentialRepresentation.TOTP, token);
-        formData.remove(CredentialRepresentation.PASSWORD);
-
-        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
-        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
-    }
-
-    @Test
-    public void authFormWithTotpPasswordTokenInvalidKey() {
-        authFormWithTotpPasswordToken();
-
-        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
-        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
-        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
-
-        KeycloakModelUtils.generateRealmKeys(realm);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormWithTotpPasswordTokenInvalidRealm() {
-        authFormWithTotpPasswordToken();
-
-        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
-        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken("invalid", user.getId())).rsa256(realm.getPrivateKey());
-        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormWithTotpPasswordTokenInvalidUser() {
-        authFormWithTotpPasswordToken();
-
-        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
-        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), "invalid")).rsa256(realm.getPrivateKey());
-        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
-
-        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-    }
-
-    @Test
-    public void authFormWithTotpPasswordTokenExpired() throws InterruptedException {
-        int lifespan = realm.getAccessCodeLifespanUserAction();
-
-        try {
-            authFormWithTotpPasswordToken();
-
-            realm.setAccessCodeLifespanUserAction(1);
-
-            formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
-            String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), "invalid")).rsa256(realm.getPrivateKey());
-            formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
-
-            Time.setOffset(2);
-
-            AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
-            Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
-
-            Time.setOffset(0);
-        } finally {
-            realm.setAccessCodeLifespanUserAction(lifespan);
-        }
-    }
-
-    @Before
-    @Override
-    public void before() throws Exception {
-        super.before();
-
-        realm = realmManager.createRealm("TestAuth");
-        realm.setAccessCodeLifespan(100);
-        realm.setAccessCodeLifespanUserAction(100);
-        realm.setEnabled(true);
-        realm.setName("TestAuth");
-
-        KeycloakModelUtils.generateRealmKeys(realm);
-
-        realm.setAccessTokenLifespan(1000);
-        realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
-
-        protector = ResteasyProviderFactory.getContextData(BruteForceProtector.class);
-        am = new AuthenticationManager(protector);
-
-        user = realmManager.getSession().users().addUser(realm, "test");
-        user.setEnabled(true);
-
-        UserCredentialModel credential = new UserCredentialModel();
-        credential.setType(CredentialRepresentation.PASSWORD);
-        credential.setValue("password");
-
-        user.updateCredential(credential);
-
-        formData = new MultivaluedMapImpl<String, String>();
-        formData.add("username", "test");
-        formData.add(CredentialRepresentation.PASSWORD, "password");
-
-        otp = new TimeBasedOTP();
-    }
-
-}
+package org.keycloak.testsuite.model;
+
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.ClientConnection;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.TimeBasedOTP;
+import org.keycloak.representations.PasswordToken;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
+import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.util.Time;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.UUID;
+
+public class AuthenticationManagerTest extends AbstractModelTest {
+
+    private AuthenticationManager am;
+    private MultivaluedMap<String, String> formData;
+    private TimeBasedOTP otp;
+    private RealmModel realm;
+    private UserModel user;
+    private BruteForceProtector protector;
+    private ClientConnection dummyConnection = new ClientConnection() {
+        @Override
+        public String getRemoteAddr() {
+            return "127.0.0.1";
+
+        }
+
+        @Override
+        public String getRemoteHost() {
+            return "localhost";
+
+        }
+
+        @Override
+        public int getReportPort() {
+            return 8080;
+        }
+    };
+
+    @Test
+    public void authForm() {
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
+    }
+
+    @Test
+    public void authFormInvalidPassword() {
+        formData.remove(CredentialRepresentation.PASSWORD);
+        formData.add(CredentialRepresentation.PASSWORD, "invalid");
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormMissingUsername() {
+        formData.remove("username");
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_USER, status);
+    }
+
+    @Test
+    public void authFormMissingPassword() {
+        formData.remove(CredentialRepresentation.PASSWORD);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.MISSING_PASSWORD, status);
+    }
+
+    @Test
+    public void authFormRequiredAction() {
+        realm.addRequiredCredential(CredentialRepresentation.TOTP);
+        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.ACTIONS_REQUIRED, status);
+    }
+
+    @Test
+    public void authFormUserDisabled() {
+        user.setEnabled(false);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.ACCOUNT_DISABLED, status);
+    }
+
+    @Test
+    public void authFormWithTotp() {
+        realm.addRequiredCredential(CredentialRepresentation.TOTP);
+
+        String totpSecret = UUID.randomUUID().toString();
+
+        UserCredentialModel credential = new UserCredentialModel();
+        credential.setType(CredentialRepresentation.TOTP);
+        credential.setValue(totpSecret);
+
+        user.updateCredential(credential);
+
+        user.setTotp(true);
+
+        String token = otp.generate(totpSecret);
+
+        formData.add(CredentialRepresentation.TOTP, token);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
+    }
+
+    @Test
+    public void authFormWithTotpInvalidPassword() {
+        authFormWithTotp();
+
+        formData.remove(CredentialRepresentation.PASSWORD);
+        formData.add(CredentialRepresentation.PASSWORD, "invalid");
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormWithTotpMissingPassword() {
+        authFormWithTotp();
+
+        formData.remove(CredentialRepresentation.PASSWORD);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.MISSING_PASSWORD, status);
+    }
+
+    @Test
+    public void authFormWithTotpInvalidTotp() {
+        authFormWithTotp();
+
+        formData.remove(CredentialRepresentation.TOTP);
+        formData.add(CredentialRepresentation.TOTP, "invalid");
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormWithTotpMissingTotp() {
+        authFormWithTotp();
+
+        formData.remove(CredentialRepresentation.TOTP);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.MISSING_TOTP, status);
+    }
+
+    @Test
+    public void authFormWithTotpPasswordToken() {
+        realm.addRequiredCredential(CredentialRepresentation.TOTP);
+
+        String totpSecret = UUID.randomUUID().toString();
+
+        UserCredentialModel credential = new UserCredentialModel();
+        credential.setType(CredentialRepresentation.TOTP);
+        credential.setValue(totpSecret);
+
+        user.updateCredential(credential);
+
+        user.setTotp(true);
+
+        String token = otp.generate(totpSecret);
+
+        formData.add(CredentialRepresentation.TOTP, token);
+        formData.remove(CredentialRepresentation.PASSWORD);
+
+        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
+        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.SUCCESS, status);
+    }
+
+    @Test
+    public void authFormWithTotpPasswordTokenInvalidKey() {
+        authFormWithTotpPasswordToken();
+
+        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
+        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
+        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
+
+        KeycloakModelUtils.generateRealmKeys(realm);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormWithTotpPasswordTokenInvalidRealm() {
+        authFormWithTotpPasswordToken();
+
+        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
+        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken("invalid", user.getId())).rsa256(realm.getPrivateKey());
+        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormWithTotpPasswordTokenInvalidUser() {
+        authFormWithTotpPasswordToken();
+
+        formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
+        String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), "invalid")).rsa256(realm.getPrivateKey());
+        formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
+
+        AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+        Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+    }
+
+    @Test
+    public void authFormWithTotpPasswordTokenExpired() throws InterruptedException {
+        int lifespan = realm.getAccessCodeLifespanUserAction();
+
+        try {
+            authFormWithTotpPasswordToken();
+
+            realm.setAccessCodeLifespanUserAction(1);
+
+            formData.remove(CredentialRepresentation.PASSWORD_TOKEN);
+            String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), "invalid")).rsa256(realm.getPrivateKey());
+            formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
+
+            Time.setOffset(2);
+
+            AuthenticationStatus status = am.authenticateForm(session, dummyConnection, realm, formData);
+            Assert.assertEquals(AuthenticationStatus.INVALID_CREDENTIALS, status);
+
+            Time.setOffset(0);
+        } finally {
+            realm.setAccessCodeLifespanUserAction(lifespan);
+        }
+    }
+
+    @Before
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        realm = realmManager.createRealm("TestAuth");
+        realm.setAccessCodeLifespan(100);
+        realm.setAccessCodeLifespanUserAction(100);
+        realm.setEnabled(true);
+        realm.setName("TestAuth");
+
+        KeycloakModelUtils.generateRealmKeys(realm);
+
+        realm.setAccessTokenLifespan(1000);
+        realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
+
+        protector = ResteasyProviderFactory.getContextData(BruteForceProtector.class);
+        am = new AuthenticationManager(protector);
+
+        user = realmManager.getSession().users().addUser(realm, "test");
+        user.setEnabled(true);
+
+        UserCredentialModel credential = new UserCredentialModel();
+        credential.setType(CredentialRepresentation.PASSWORD);
+        credential.setValue("password");
+
+        user.updateCredential(credential);
+
+        formData = new MultivaluedMapImpl<String, String>();
+        formData.add("username", "test");
+        formData.add(CredentialRepresentation.PASSWORD, "password");
+
+        otp = new TimeBasedOTP();
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
index 5f8371c..2b05cb9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
@@ -1,91 +1,91 @@
-package org.keycloak.testsuite.model;
-
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.keycloak.models.*;
-import org.keycloak.testsuite.rule.KeycloakRule;
-
-import static org.junit.Assert.assertNotNull;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CacheTest {
-    @ClassRule
-    public static KeycloakRule kc = new KeycloakRule();
-
-    @Test
-    public void testStaleCache() throws Exception {
-        String appId = null;
-        {
-            // load up cache
-            KeycloakSession session = kc.startSession();
-            RealmModel realm = session.realms().getRealmByName("test");
-            ClientModel testApp = realm.getClientByClientId("test-app");
-            assertNotNull(testApp);
-            appId = testApp.getId();
-            Assert.assertTrue(testApp.isEnabled());
-            kc.stopSession(session, true);
-        }
-        {
-            // update realm, then get an AppModel and change it.  The AppModel would not be a cache adapter
-            KeycloakSession session = kc.startSession();
-
-            // KEYCLOAK-1240 - obtain the realm via session.realms().getRealms()
-            RealmModel realm = null;
-            List<RealmModel> realms = session.realms().getRealms();
-            for (RealmModel current : realms) {
-                if ("test".equals(current.getName())) {
-                    realm = current;
-                    break;
-                }
-            }
-
-            Assert.assertTrue(realm instanceof org.keycloak.models.cache.RealmAdapter);
-            realm.setAccessCodeLifespanLogin(200);
-            ClientModel testApp = realm.getClientByClientId("test-app");
-            assertNotNull(testApp);
-            testApp.setEnabled(false);
-            kc.stopSession(session, true);
-        }
-        // make sure that app cache was flushed and enabled changed
-        {
-            KeycloakSession session = kc.startSession();
-            RealmModel realm = session.realms().getRealmByName("test");
-            Assert.assertEquals(200, realm.getAccessCodeLifespanLogin());
-            ClientModel testApp = session.realms().getClientById(appId, realm);
-            Assert.assertFalse(testApp.isEnabled());
-            kc.stopSession(session, true);
-
-        }
-
-
-    }
-
-    @Test
-    public void testAddUserNotAddedToCache() {
-        KeycloakSession session = kc.startSession();
-        try {
-            RealmModel realm = session.realms().getRealmByName("test");
-
-            UserModel user = session.users().addUser(realm, "testAddUserNotAddedToCache");
-            user.setFirstName("firstName");
-            user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
-
-            UserSessionModel userSession = session.sessions().createUserSession(realm, user, "testAddUserNotAddedToCache", "127.0.0.1", "auth", false, null, null);
-            UserModel user2 = userSession.getUser();
-
-            user.setLastName("lastName");
-
-            assertNotNull(user2.getLastName());
-        } finally {
-            session.getTransaction().commit();
-            session.close();
-        }
-    }
-
-}
+package org.keycloak.testsuite.model;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.keycloak.models.*;
+import org.keycloak.testsuite.rule.KeycloakRule;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTest {
+    @ClassRule
+    public static KeycloakRule kc = new KeycloakRule();
+
+    @Test
+    public void testStaleCache() throws Exception {
+        String appId = null;
+        {
+            // load up cache
+            KeycloakSession session = kc.startSession();
+            RealmModel realm = session.realms().getRealmByName("test");
+            ClientModel testApp = realm.getClientByClientId("test-app");
+            assertNotNull(testApp);
+            appId = testApp.getId();
+            Assert.assertTrue(testApp.isEnabled());
+            kc.stopSession(session, true);
+        }
+        {
+            // update realm, then get an AppModel and change it.  The AppModel would not be a cache adapter
+            KeycloakSession session = kc.startSession();
+
+            // KEYCLOAK-1240 - obtain the realm via session.realms().getRealms()
+            RealmModel realm = null;
+            List<RealmModel> realms = session.realms().getRealms();
+            for (RealmModel current : realms) {
+                if ("test".equals(current.getName())) {
+                    realm = current;
+                    break;
+                }
+            }
+
+            Assert.assertTrue(realm instanceof org.keycloak.models.cache.RealmAdapter);
+            realm.setAccessCodeLifespanLogin(200);
+            ClientModel testApp = realm.getClientByClientId("test-app");
+            assertNotNull(testApp);
+            testApp.setEnabled(false);
+            kc.stopSession(session, true);
+        }
+        // make sure that app cache was flushed and enabled changed
+        {
+            KeycloakSession session = kc.startSession();
+            RealmModel realm = session.realms().getRealmByName("test");
+            Assert.assertEquals(200, realm.getAccessCodeLifespanLogin());
+            ClientModel testApp = session.realms().getClientById(appId, realm);
+            Assert.assertFalse(testApp.isEnabled());
+            kc.stopSession(session, true);
+
+        }
+
+
+    }
+
+    @Test
+    public void testAddUserNotAddedToCache() {
+        KeycloakSession session = kc.startSession();
+        try {
+            RealmModel realm = session.realms().getRealmByName("test");
+
+            UserModel user = session.users().addUser(realm, "testAddUserNotAddedToCache");
+            user.setFirstName("firstName");
+            user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
+
+            UserSessionModel userSession = session.sessions().createUserSession(realm, user, "testAddUserNotAddedToCache", "127.0.0.1", "auth", false, null, null);
+            UserModel user2 = userSession.getUser();
+
+            user.setLastName("lastName");
+
+            assertNotNull(user2.getLastName());
+        } finally {
+            session.getTransaction().commit();
+            session.close();
+        }
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
index efbefa6..eff25e3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
@@ -1,109 +1,109 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.services.managers.ClientManager;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class ClientModelTest extends AbstractModelTest {
-    private ClientModel client;
-    private RealmModel realm;
-    private ClientManager appManager;
-
-    @Before
-    @Override
-    public void before() throws Exception {
-        super.before();
-        appManager = new ClientManager(realmManager);
-
-        realm = realmManager.createRealm("original");
-        client = realm.addClient("application");
-        client.setName("Application");
-        client.setBaseUrl("http://base");
-        client.setManagementUrl("http://management");
-        client.setClientId("app-name");
-        client.addRole("role-1");
-        client.addRole("role-2");
-        client.addRole("role-3");
-        client.addDefaultRole("role-1");
-        client.addDefaultRole("role-2");
-
-        client.addRedirectUri("redirect-1");
-        client.addRedirectUri("redirect-2");
-
-        client.addWebOrigin("origin-1");
-        client.addWebOrigin("origin-2");
-
-        client.registerNode("node1", 10);
-        client.registerNode("10.20.30.40", 50);
-
-        client.updateClient();
-    }
-
-    @Test
-    public void persist() {
-        RealmModel persisted = realmManager.getRealm(realm.getId());
-
-        ClientModel actual = persisted.getClientNameMap().get("app-name");
-        assertEquals(client, actual);
-    }
-
-    @Test
-    public void json() {
-        ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
-        representation.setId(null);
-        for (ProtocolMapperRepresentation protocolMapper : representation.getProtocolMappers()) {
-            protocolMapper.setId(null);
-        }
-
-        RealmModel realm = realmManager.createRealm("copy");
-        ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true);
-
-        assertEquals(client, copy);
-    }
-
-    @Test
-    public void testAddApplicationWithId() {
-        client = realm.addClient("app-123", "application2");
-        commit();
-        client = realmManager.getRealm(realm.getId()).getClientById("app-123");
-        Assert.assertNotNull(client);
-    }
-
-
-    public static void assertEquals(ClientModel expected, ClientModel actual) {
-        Assert.assertEquals(expected.getClientId(), actual.getClientId());
-        Assert.assertEquals(expected.getName(), actual.getName());
-        Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
-        Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
-        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
-
-        Assert.assertTrue(expected.getRedirectUris().containsAll(actual.getRedirectUris()));
-        Assert.assertTrue(expected.getWebOrigins().containsAll(actual.getWebOrigins()));
-        Assert.assertTrue(expected.getRegisteredNodes().equals(actual.getRegisteredNodes()));
-    }
-
-    public static void assertEquals(List<RoleModel> expected, List<RoleModel> actual) {
-        Assert.assertEquals(expected.size(), actual.size());
-        Iterator<RoleModel> exp = expected.iterator();
-        Iterator<RoleModel> act = actual.iterator();
-        while (exp.hasNext()) {
-            Assert.assertEquals(exp.next().getName(), act.next().getName());
-        }
-    }
-
-}
-
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.services.managers.ClientManager;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ClientModelTest extends AbstractModelTest {
+    private ClientModel client;
+    private RealmModel realm;
+    private ClientManager appManager;
+
+    @Before
+    @Override
+    public void before() throws Exception {
+        super.before();
+        appManager = new ClientManager(realmManager);
+
+        realm = realmManager.createRealm("original");
+        client = realm.addClient("application");
+        client.setName("Application");
+        client.setBaseUrl("http://base");
+        client.setManagementUrl("http://management");
+        client.setClientId("app-name");
+        client.addRole("role-1");
+        client.addRole("role-2");
+        client.addRole("role-3");
+        client.addDefaultRole("role-1");
+        client.addDefaultRole("role-2");
+
+        client.addRedirectUri("redirect-1");
+        client.addRedirectUri("redirect-2");
+
+        client.addWebOrigin("origin-1");
+        client.addWebOrigin("origin-2");
+
+        client.registerNode("node1", 10);
+        client.registerNode("10.20.30.40", 50);
+
+        client.updateClient();
+    }
+
+    @Test
+    public void persist() {
+        RealmModel persisted = realmManager.getRealm(realm.getId());
+
+        ClientModel actual = persisted.getClientNameMap().get("app-name");
+        assertEquals(client, actual);
+    }
+
+    @Test
+    public void json() {
+        ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
+        representation.setId(null);
+        for (ProtocolMapperRepresentation protocolMapper : representation.getProtocolMappers()) {
+            protocolMapper.setId(null);
+        }
+
+        RealmModel realm = realmManager.createRealm("copy");
+        ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true);
+
+        assertEquals(client, copy);
+    }
+
+    @Test
+    public void testAddApplicationWithId() {
+        client = realm.addClient("app-123", "application2");
+        commit();
+        client = realmManager.getRealm(realm.getId()).getClientById("app-123");
+        Assert.assertNotNull(client);
+    }
+
+
+    public static void assertEquals(ClientModel expected, ClientModel actual) {
+        Assert.assertEquals(expected.getClientId(), actual.getClientId());
+        Assert.assertEquals(expected.getName(), actual.getName());
+        Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
+        Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
+        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
+
+        Assert.assertTrue(expected.getRedirectUris().containsAll(actual.getRedirectUris()));
+        Assert.assertTrue(expected.getWebOrigins().containsAll(actual.getWebOrigins()));
+        Assert.assertTrue(expected.getRegisteredNodes().equals(actual.getRegisteredNodes()));
+    }
+
+    public static void assertEquals(List<RoleModel> expected, List<RoleModel> actual) {
+        Assert.assertEquals(expected.size(), actual.size());
+        Iterator<RoleModel> exp = expected.iterator();
+        Iterator<RoleModel> act = actual.iterator();
+        while (exp.hasNext()) {
+            Assert.assertEquals(exp.next().getName(), act.next().getName());
+        }
+    }
+
+}
+
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
index a23e048..1d1100f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
@@ -1,114 +1,114 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.managers.RealmManager;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class CompositeRolesModelTest extends AbstractModelTest {
-
-    @Before
-    @Override
-    public void before() throws Exception {
-        super.before();
-        RealmManager manager = realmManager;
-        RealmRepresentation rep = AbstractModelTest.loadJson("model/testcomposites.json");
-        rep.setId("TestComposites");
-        RealmModel realm = manager.importRealm(rep);
-    }
-
-    @Test
-    public void testComposites() {
-        Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_USER");
-        Assert.assertEquals(2, requestedRoles.size());
-        assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
-        assertContains("realm", "REALM_ROLE_1", requestedRoles);
-
-        requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
-        Assert.assertEquals(1, requestedRoles.size());
-        assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
-
-        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
-        Assert.assertEquals(1, requestedRoles.size());
-        assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
-
-        requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
-        Assert.assertEquals(1, requestedRoles.size());
-        assertContains("realm", "REALM_ROLE_1", requestedRoles);
-
-        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
-        Assert.assertEquals(1, requestedRoles.size());
-        assertContains("realm", "REALM_ROLE_1", requestedRoles);
-    }
-
-    // Same algorithm as in TokenManager.createAccessCode
-    private Set<RoleModel> getRequestedRoles(String applicationName, String username) {
-        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
-
-        RealmModel realm = realmManager.getRealm("TestComposites");
-        UserModel user = realmManager.getSession().users().getUserByUsername(username, realm);
-        ClientModel application = realm.getClientByClientId(applicationName);
-
-        Set<RoleModel> roleMappings = user.getRoleMappings();
-        Set<RoleModel> scopeMappings = application.getScopeMappings();
-        Set<RoleModel> appRoles = application.getRoles();
-        if (appRoles != null) scopeMappings.addAll(appRoles);
-
-        for (RoleModel role : roleMappings) {
-            if (role.getContainer().equals(application)) requestedRoles.add(role);
-            for (RoleModel desiredRole : scopeMappings) {
-                Set<RoleModel> visited = new HashSet<RoleModel>();
-                applyScope(role, desiredRole, visited, requestedRoles);
-            }
-        }
-
-        return requestedRoles;
-    }
-
-    private static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
-        if (visited.contains(scope)) return;
-        visited.add(scope);
-        if (role.hasRole(scope)) {
-            requested.add(scope);
-            return;
-        }
-        if (!scope.isComposite()) return;
-
-        for (RoleModel contained : scope.getComposites()) {
-            applyScope(role, contained, visited, requested);
-        }
-    }
-
-    private RoleModel getRole(String appName, String roleName) {
-        RealmModel realm = realmManager.getRealm("TestComposites");
-        if ("realm".equals(appName)) {
-            return realm.getRole(roleName);
-        }  else {
-            return realm.getClientByClientId(appName).getRole(roleName);
-        }
-    }
-
-    private void assertContains(String appName, String roleName, Set<RoleModel> requestedRoles) {
-        RoleModel expectedRole = getRole(appName, roleName);
-
-        Assert.assertTrue(requestedRoles.contains(expectedRole));
-
-        // Check if requestedRole has correct role container
-        for (RoleModel role : requestedRoles) {
-            if (role.equals(expectedRole)) {
-                Assert.assertEquals(role.getContainer(), expectedRole.getContainer());
-            }
-        }
-    }
-}
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class CompositeRolesModelTest extends AbstractModelTest {
+
+    @Before
+    @Override
+    public void before() throws Exception {
+        super.before();
+        RealmManager manager = realmManager;
+        RealmRepresentation rep = AbstractModelTest.loadJson("model/testcomposites.json");
+        rep.setId("TestComposites");
+        RealmModel realm = manager.importRealm(rep);
+    }
+
+    @Test
+    public void testComposites() {
+        Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_USER");
+        Assert.assertEquals(2, requestedRoles.size());
+        assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
+        assertContains("realm", "REALM_ROLE_1", requestedRoles);
+
+        requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
+        Assert.assertEquals(1, requestedRoles.size());
+        assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
+
+        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
+        Assert.assertEquals(1, requestedRoles.size());
+        assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
+
+        requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
+        Assert.assertEquals(1, requestedRoles.size());
+        assertContains("realm", "REALM_ROLE_1", requestedRoles);
+
+        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
+        Assert.assertEquals(1, requestedRoles.size());
+        assertContains("realm", "REALM_ROLE_1", requestedRoles);
+    }
+
+    // Same algorithm as in TokenManager.createAccessCode
+    private Set<RoleModel> getRequestedRoles(String applicationName, String username) {
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+
+        RealmModel realm = realmManager.getRealm("TestComposites");
+        UserModel user = realmManager.getSession().users().getUserByUsername(username, realm);
+        ClientModel application = realm.getClientByClientId(applicationName);
+
+        Set<RoleModel> roleMappings = user.getRoleMappings();
+        Set<RoleModel> scopeMappings = application.getScopeMappings();
+        Set<RoleModel> appRoles = application.getRoles();
+        if (appRoles != null) scopeMappings.addAll(appRoles);
+
+        for (RoleModel role : roleMappings) {
+            if (role.getContainer().equals(application)) requestedRoles.add(role);
+            for (RoleModel desiredRole : scopeMappings) {
+                Set<RoleModel> visited = new HashSet<RoleModel>();
+                applyScope(role, desiredRole, visited, requestedRoles);
+            }
+        }
+
+        return requestedRoles;
+    }
+
+    private static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
+        if (visited.contains(scope)) return;
+        visited.add(scope);
+        if (role.hasRole(scope)) {
+            requested.add(scope);
+            return;
+        }
+        if (!scope.isComposite()) return;
+
+        for (RoleModel contained : scope.getComposites()) {
+            applyScope(role, contained, visited, requested);
+        }
+    }
+
+    private RoleModel getRole(String appName, String roleName) {
+        RealmModel realm = realmManager.getRealm("TestComposites");
+        if ("realm".equals(appName)) {
+            return realm.getRole(roleName);
+        }  else {
+            return realm.getClientByClientId(appName).getRole(roleName);
+        }
+    }
+
+    private void assertContains(String appName, String roleName, Set<RoleModel> requestedRoles) {
+        RoleModel expectedRole = getRole(appName, roleName);
+
+        Assert.assertTrue(requestedRoles.contains(expectedRole));
+
+        // Check if requestedRole has correct role container
+        for (RoleModel role : requestedRoles) {
+            if (role.equals(expectedRole)) {
+                Assert.assertEquals(role.getContainer(), expectedRole.getContainer());
+            }
+        }
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
index 86ca62e..31a9574 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
@@ -1,325 +1,325 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-import org.keycloak.constants.KerberosConstants;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.FederatedIdentityModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserConsentModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
-import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.managers.RealmManager;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class ImportTest extends AbstractModelTest {
-
-    @Test
-    public void demoDelete() throws Exception {
-        // was having trouble deleting this realm from admin console
-        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm2.json");
-        RealmModel realm = realmManager.importRealm(rep);
-        commit();
-        realm = realmManager.getRealmByName("demo-delete");
-        realmManager.removeRealm(realm);
-    }
-
-    @Test
-    public void install() throws Exception {
-        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm.json");
-        rep.setId("demo");
-        RealmModel realm = realmManager.importRealm(rep);
-
-        // Commit after import
-        commit();
-
-        realm = realmManager.getRealm("demo");
-        assertDataImportedInRealm(realmManager.getSession(), realm);
-
-        commit();
-
-        realm = realmManager.getRealm("demo");
-        realmManager.removeRealm(realm);
-    }
-
-    // Moved to static method, so it's possible to test this from other places too (for example export-import tests)
-    public static void assertDataImportedInRealm(KeycloakSession session, RealmModel realm) {
-        Assert.assertTrue(realm.isVerifyEmail());
-
-        List<RequiredCredentialModel> creds = realm.getRequiredCredentials();
-        Assert.assertEquals(1, creds.size());
-        RequiredCredentialModel cred = creds.get(0);
-        Assert.assertEquals("password", cred.getFormLabel());
-        Assert.assertEquals(2, realm.getDefaultRoles().size());
-
-        Assert.assertNotNull(realm.getRole("foo"));
-        Assert.assertNotNull(realm.getRole("bar"));
-
-        UserModel user = session.users().getUserByUsername("loginclient", realm);
-        Assert.assertNotNull(user);
-        Assert.assertEquals(0,  session.users().getFederatedIdentities(user, realm).size());
-
-        List<ClientModel> resources = realm.getClients();
-        Assert.assertEquals(7, resources.size());
-
-        // Test applications imported
-        ClientModel application = realm.getClientByClientId("Application");
-        ClientModel otherApp = realm.getClientByClientId("OtherApp");
-        ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-        ClientModel nonExisting = realm.getClientByClientId("NonExisting");
-        Assert.assertNotNull(application);
-        Assert.assertNotNull(otherApp);
-        Assert.assertNull(nonExisting);
-        Map<String, ClientModel> clients = realm.getClientNameMap();
-        Assert.assertEquals(7, clients.size());
-        Assert.assertTrue(clients.values().contains(application));
-        Assert.assertTrue(clients.values().contains(otherApp));
-        Assert.assertTrue(clients.values().contains(accountApp));
-        realm.getClients().containsAll(clients.values());
-
-        Assert.assertEquals("Applicationn", application.getName());
-        Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
-        Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
-        Assert.assertEquals(2, appRegisteredNodes.size());
-        Assert.assertTrue(10 == appRegisteredNodes.get("node1"));
-        Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20"));
-
-        // Test finding applications by ID
-        Assert.assertNull(realm.getClientById("982734"));
-        Assert.assertEquals(application, realm.getClientById(application.getId()));
-
-
-        // Test role mappings
-        UserModel admin =  session.users().getUserByUsername("admin", realm);
-        // user without creation timestamp in import
-        Assert.assertNull(admin.getCreatedTimestamp());
-        Set<RoleModel> allRoles = admin.getRoleMappings();
-        Assert.assertEquals(3, allRoles.size());
-        Assert.assertTrue(allRoles.contains(realm.getRole("admin")));
-        Assert.assertTrue(allRoles.contains(application.getRole("app-admin")));
-        Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin")));
-
-        UserModel wburke =  session.users().getUserByUsername("wburke", realm);
-        // user with creation timestamp in import
-        Assert.assertEquals(new Long(123654), wburke.getCreatedTimestamp());
-        allRoles = wburke.getRoleMappings();
-        Assert.assertEquals(2, allRoles.size());
-        Assert.assertFalse(allRoles.contains(realm.getRole("admin")));
-        Assert.assertTrue(allRoles.contains(application.getRole("app-user")));
-        Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-user")));
-
-        Assert.assertEquals(0, wburke.getRealmRoleMappings().size());
-
-        UserModel loginclient = session.users().getUserByUsername("loginclient", realm);
-        // user with creation timestamp as string in import
-        Assert.assertEquals(new Long(123655), loginclient.getCreatedTimestamp());
-
-        Set<RoleModel> realmRoles = admin.getRealmRoleMappings();
-        Assert.assertEquals(1, realmRoles.size());
-        Assert.assertEquals("admin", realmRoles.iterator().next().getName());
-
-        Set<RoleModel> appRoles = admin.getClientRoleMappings(application);
-        Assert.assertEquals(1, appRoles.size());
-        Assert.assertEquals("app-admin", appRoles.iterator().next().getName());
-
-        // Test attributes
-        Map<String, List<String>> attrs = wburke.getAttributes();
-        Assert.assertEquals(1, attrs.size());
-        List<String> attrVals = attrs.get("email");
-        Assert.assertEquals(1, attrVals.size());
-        Assert.assertEquals("bburke@redhat.com", attrVals.get(0));
-
-        attrs = admin.getAttributes();
-        Assert.assertEquals(2, attrs.size());
-        attrVals = attrs.get("key1");
-        Assert.assertEquals(1, attrVals.size());
-        Assert.assertEquals("val1", attrVals.get(0));
-        attrVals = attrs.get("key2");
-        Assert.assertEquals(2, attrVals.size());
-        Assert.assertTrue(attrVals.contains("val21") && attrVals.contains("val22"));
-
-        // Test client
-        ClientModel oauthClient = realm.getClientByClientId("oauthclient");
-        Assert.assertEquals("clientpassword", oauthClient.getSecret());
-        Assert.assertEquals(true, oauthClient.isEnabled());
-        Assert.assertNotNull(oauthClient);
-
-        // Test scope relationship
-        Set<RoleModel> allScopes = oauthClient.getScopeMappings();
-        Assert.assertEquals(2, allScopes.size());
-        Assert.assertTrue(allScopes.contains(realm.getRole("admin")));
-        Assert.assertTrue(allScopes.contains(application.getRole("app-user")));
-
-        Set<RoleModel> realmScopes = oauthClient.getRealmScopeMappings();
-        Assert.assertTrue(realmScopes.contains(realm.getRole("admin")));
-
-        Set<RoleModel> appScopes = application.getClientScopeMappings(oauthClient);
-        Assert.assertTrue(appScopes.contains(application.getRole("app-user")));
-
-
-        // Test social linking
-        UserModel socialUser = session.users().getUserByUsername("mySocialUser", realm);
-        Set<FederatedIdentityModel> socialLinks = session.users().getFederatedIdentities(socialUser, realm);
-        Assert.assertEquals(3, socialLinks.size());
-        boolean facebookFound = false;
-        boolean googleFound = false;
-        boolean twitterFound = false;
-        for (FederatedIdentityModel federatedIdentityModel : socialLinks) {
-            if ("facebook".equals(federatedIdentityModel.getIdentityProvider())) {
-                facebookFound = true;
-                Assert.assertEquals(federatedIdentityModel.getUserId(), "facebook1");
-                Assert.assertEquals(federatedIdentityModel.getUserName(), "fbuser1");
-            } else if ("google".equals(federatedIdentityModel.getIdentityProvider())) {
-                googleFound = true;
-                Assert.assertEquals(federatedIdentityModel.getUserId(), "google1");
-                Assert.assertEquals(federatedIdentityModel.getUserName(), "mysocialuser@gmail.com");
-            } else if ("twitter".equals(federatedIdentityModel.getIdentityProvider())) {
-                twitterFound = true;
-                Assert.assertEquals(federatedIdentityModel.getUserId(), "twitter1");
-                Assert.assertEquals(federatedIdentityModel.getUserName(), "twuser1");
-            }
-        }
-        Assert.assertTrue(facebookFound && twitterFound && googleFound);
-
-        UserModel foundSocialUser = session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "facebook1", "fbuser1"), realm);
-        Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
-        Assert.assertNull(session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "not-existing", "not-existing"), realm));
-
-        FederatedIdentityModel foundSocialLink = session.users().getFederatedIdentity(socialUser, "facebook", realm);
-        Assert.assertEquals("facebook1", foundSocialLink.getUserId());
-        Assert.assertEquals("fbuser1", foundSocialLink.getUserName());
-        Assert.assertEquals("facebook", foundSocialLink.getIdentityProvider());
-
-        // Test removing social link
-        Assert.assertTrue(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
-        Assert.assertNull(session.users().getFederatedIdentity(socialUser, "facebook", realm));
-        Assert.assertFalse(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
-        session.users().addFederatedIdentity(realm, socialUser, new FederatedIdentityModel("facebook", "facebook1", "fbuser1"));
-
-        // Test smtp config
-        Map<String, String> smtpConfig = realm.getSmtpConfig();
-        Assert.assertTrue(smtpConfig.size() == 3);
-        Assert.assertEquals("auto@keycloak.org", smtpConfig.get("from"));
-        Assert.assertEquals("localhost", smtpConfig.get("host"));
-        Assert.assertEquals("3025", smtpConfig.get("port"));
-
-        // Test identity providers
-        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
-        Assert.assertEquals(1, identityProviders.size());
-        IdentityProviderModel google = identityProviders.get(0);
-        Assert.assertEquals("google1", google.getAlias());
-        Assert.assertEquals("google", google.getProviderId());
-        Assert.assertTrue(google.isEnabled());
-        Assert.assertEquals("googleId", google.getConfig().get("clientId"));
-        Assert.assertEquals("googleSecret", google.getConfig().get("clientSecret"));
-
-        // Test federation providers
-        List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
-        Assert.assertTrue(fedProviders.size() == 2);
-        UserFederationProviderModel ldap1 = fedProviders.get(0);
-        Assert.assertEquals("MyLDAPProvider1", ldap1.getDisplayName());
-        Assert.assertEquals("ldap", ldap1.getProviderName());
-        Assert.assertEquals(1, ldap1.getPriority());
-        Assert.assertEquals("ldap://foo", ldap1.getConfig().get(LDAPConstants.CONNECTION_URL));
-
-        UserFederationProviderModel ldap2 = fedProviders.get(1);
-        Assert.assertEquals("MyLDAPProvider2", ldap2.getDisplayName());
-        Assert.assertEquals("ldap://bar", ldap2.getConfig().get(LDAPConstants.CONNECTION_URL));
-
-        // Test federation mappers
-        Set<UserFederationMapperModel> fedMappers1 = realm.getUserFederationMappersByFederationProvider(ldap1.getId());
-        Assert.assertTrue(fedMappers1.size() == 1);
-        UserFederationMapperModel fullNameMapper = fedMappers1.iterator().next();
-        Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
-        Assert.assertEquals(FullNameLDAPFederationMapperFactory.PROVIDER_ID, fullNameMapper.getFederationMapperType());
-        Assert.assertEquals(ldap1.getId(), fullNameMapper.getFederationProviderId());
-        Assert.assertEquals("cn", fullNameMapper.getConfig().get(FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE));
-
-        // All builtin LDAP mappers should be here
-        Set<UserFederationMapperModel> fedMappers2 = realm.getUserFederationMappersByFederationProvider(ldap2.getId());
-        Assert.assertTrue(fedMappers2.size() > 3);
-        Set<UserFederationMapperModel> allMappers = realm.getUserFederationMappers();
-        Assert.assertEquals(allMappers.size(), fedMappers1.size() + fedMappers2.size());
-
-        // Assert that federation link wasn't created during import
-        UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
-        Assert.assertNull(factory.getInstance(session, null).getUserByUsername(realm, "wburke"));
-
-        // Test protocol mappers. Default application has all the builtin protocol mappers. OtherApp just gss credential
-        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
-        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "email"));
-        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "given name"));
-        Assert.assertNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
-
-        Assert.assertEquals(1, otherApp.getProtocolMappers().size());
-        Assert.assertNull(otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
-        ProtocolMapperModel gssCredentialMapper = otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
-        Assert.assertEquals(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, gssCredentialMapper.getName());
-        Assert.assertEquals( OIDCLoginProtocol.LOGIN_PROTOCOL, gssCredentialMapper.getProtocol());
-        Assert.assertEquals(UserSessionNoteMapper.PROVIDER_ID, gssCredentialMapper.getProtocolMapper());
-        String includeInAccessToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
-        String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
-        Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
-        Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);
-
-        // Test user consents
-        admin =  session.users().getUserByUsername("admin", realm);
-        Assert.assertEquals(2, admin.getConsents().size());
-
-        UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
-        Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
-        Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
-        Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
-        Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
-
-        UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
-        Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
-        Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
-        Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
-        Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
-        Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));
-    }
-
-    @Test
-    public void install2() throws Exception {
-        RealmManager manager = realmManager;
-        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm-demo.json");
-        rep.setId("demo");
-        RealmModel realm =manager.importRealm(rep);
-
-        Assert.assertEquals(600, realm.getAccessCodeLifespanUserAction());
-        verifyRequiredCredentials(realm.getRequiredCredentials(), "password");
-    }
-
-    private void verifyRequiredCredentials(List<RequiredCredentialModel> requiredCreds, String expectedType) {
-        Assert.assertEquals(1, requiredCreds.size());
-        Assert.assertEquals(expectedType, requiredCreds.get(0).getType());
-    }
-
-}
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.keycloak.constants.KerberosConstants;
+import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
+import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserConsentModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderFactory;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
+import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ImportTest extends AbstractModelTest {
+
+    @Test
+    public void demoDelete() throws Exception {
+        // was having trouble deleting this realm from admin console
+        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm2.json");
+        RealmModel realm = realmManager.importRealm(rep);
+        commit();
+        realm = realmManager.getRealmByName("demo-delete");
+        realmManager.removeRealm(realm);
+    }
+
+    @Test
+    public void install() throws Exception {
+        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm.json");
+        rep.setId("demo");
+        RealmModel realm = realmManager.importRealm(rep);
+
+        // Commit after import
+        commit();
+
+        realm = realmManager.getRealm("demo");
+        assertDataImportedInRealm(realmManager.getSession(), realm);
+
+        commit();
+
+        realm = realmManager.getRealm("demo");
+        realmManager.removeRealm(realm);
+    }
+
+    // Moved to static method, so it's possible to test this from other places too (for example export-import tests)
+    public static void assertDataImportedInRealm(KeycloakSession session, RealmModel realm) {
+        Assert.assertTrue(realm.isVerifyEmail());
+
+        List<RequiredCredentialModel> creds = realm.getRequiredCredentials();
+        Assert.assertEquals(1, creds.size());
+        RequiredCredentialModel cred = creds.get(0);
+        Assert.assertEquals("password", cred.getFormLabel());
+        Assert.assertEquals(2, realm.getDefaultRoles().size());
+
+        Assert.assertNotNull(realm.getRole("foo"));
+        Assert.assertNotNull(realm.getRole("bar"));
+
+        UserModel user = session.users().getUserByUsername("loginclient", realm);
+        Assert.assertNotNull(user);
+        Assert.assertEquals(0,  session.users().getFederatedIdentities(user, realm).size());
+
+        List<ClientModel> resources = realm.getClients();
+        Assert.assertEquals(7, resources.size());
+
+        // Test applications imported
+        ClientModel application = realm.getClientByClientId("Application");
+        ClientModel otherApp = realm.getClientByClientId("OtherApp");
+        ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        ClientModel nonExisting = realm.getClientByClientId("NonExisting");
+        Assert.assertNotNull(application);
+        Assert.assertNotNull(otherApp);
+        Assert.assertNull(nonExisting);
+        Map<String, ClientModel> clients = realm.getClientNameMap();
+        Assert.assertEquals(7, clients.size());
+        Assert.assertTrue(clients.values().contains(application));
+        Assert.assertTrue(clients.values().contains(otherApp));
+        Assert.assertTrue(clients.values().contains(accountApp));
+        realm.getClients().containsAll(clients.values());
+
+        Assert.assertEquals("Applicationn", application.getName());
+        Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
+        Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
+        Assert.assertEquals(2, appRegisteredNodes.size());
+        Assert.assertTrue(10 == appRegisteredNodes.get("node1"));
+        Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20"));
+
+        // Test finding applications by ID
+        Assert.assertNull(realm.getClientById("982734"));
+        Assert.assertEquals(application, realm.getClientById(application.getId()));
+
+
+        // Test role mappings
+        UserModel admin =  session.users().getUserByUsername("admin", realm);
+        // user without creation timestamp in import
+        Assert.assertNull(admin.getCreatedTimestamp());
+        Set<RoleModel> allRoles = admin.getRoleMappings();
+        Assert.assertEquals(3, allRoles.size());
+        Assert.assertTrue(allRoles.contains(realm.getRole("admin")));
+        Assert.assertTrue(allRoles.contains(application.getRole("app-admin")));
+        Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin")));
+
+        UserModel wburke =  session.users().getUserByUsername("wburke", realm);
+        // user with creation timestamp in import
+        Assert.assertEquals(new Long(123654), wburke.getCreatedTimestamp());
+        allRoles = wburke.getRoleMappings();
+        Assert.assertEquals(2, allRoles.size());
+        Assert.assertFalse(allRoles.contains(realm.getRole("admin")));
+        Assert.assertTrue(allRoles.contains(application.getRole("app-user")));
+        Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-user")));
+
+        Assert.assertEquals(0, wburke.getRealmRoleMappings().size());
+
+        UserModel loginclient = session.users().getUserByUsername("loginclient", realm);
+        // user with creation timestamp as string in import
+        Assert.assertEquals(new Long(123655), loginclient.getCreatedTimestamp());
+
+        Set<RoleModel> realmRoles = admin.getRealmRoleMappings();
+        Assert.assertEquals(1, realmRoles.size());
+        Assert.assertEquals("admin", realmRoles.iterator().next().getName());
+
+        Set<RoleModel> appRoles = admin.getClientRoleMappings(application);
+        Assert.assertEquals(1, appRoles.size());
+        Assert.assertEquals("app-admin", appRoles.iterator().next().getName());
+
+        // Test attributes
+        Map<String, List<String>> attrs = wburke.getAttributes();
+        Assert.assertEquals(1, attrs.size());
+        List<String> attrVals = attrs.get("email");
+        Assert.assertEquals(1, attrVals.size());
+        Assert.assertEquals("bburke@redhat.com", attrVals.get(0));
+
+        attrs = admin.getAttributes();
+        Assert.assertEquals(2, attrs.size());
+        attrVals = attrs.get("key1");
+        Assert.assertEquals(1, attrVals.size());
+        Assert.assertEquals("val1", attrVals.get(0));
+        attrVals = attrs.get("key2");
+        Assert.assertEquals(2, attrVals.size());
+        Assert.assertTrue(attrVals.contains("val21") && attrVals.contains("val22"));
+
+        // Test client
+        ClientModel oauthClient = realm.getClientByClientId("oauthclient");
+        Assert.assertEquals("clientpassword", oauthClient.getSecret());
+        Assert.assertEquals(true, oauthClient.isEnabled());
+        Assert.assertNotNull(oauthClient);
+
+        // Test scope relationship
+        Set<RoleModel> allScopes = oauthClient.getScopeMappings();
+        Assert.assertEquals(2, allScopes.size());
+        Assert.assertTrue(allScopes.contains(realm.getRole("admin")));
+        Assert.assertTrue(allScopes.contains(application.getRole("app-user")));
+
+        Set<RoleModel> realmScopes = oauthClient.getRealmScopeMappings();
+        Assert.assertTrue(realmScopes.contains(realm.getRole("admin")));
+
+        Set<RoleModel> appScopes = application.getClientScopeMappings(oauthClient);
+        Assert.assertTrue(appScopes.contains(application.getRole("app-user")));
+
+
+        // Test social linking
+        UserModel socialUser = session.users().getUserByUsername("mySocialUser", realm);
+        Set<FederatedIdentityModel> socialLinks = session.users().getFederatedIdentities(socialUser, realm);
+        Assert.assertEquals(3, socialLinks.size());
+        boolean facebookFound = false;
+        boolean googleFound = false;
+        boolean twitterFound = false;
+        for (FederatedIdentityModel federatedIdentityModel : socialLinks) {
+            if ("facebook".equals(federatedIdentityModel.getIdentityProvider())) {
+                facebookFound = true;
+                Assert.assertEquals(federatedIdentityModel.getUserId(), "facebook1");
+                Assert.assertEquals(federatedIdentityModel.getUserName(), "fbuser1");
+            } else if ("google".equals(federatedIdentityModel.getIdentityProvider())) {
+                googleFound = true;
+                Assert.assertEquals(federatedIdentityModel.getUserId(), "google1");
+                Assert.assertEquals(federatedIdentityModel.getUserName(), "mysocialuser@gmail.com");
+            } else if ("twitter".equals(federatedIdentityModel.getIdentityProvider())) {
+                twitterFound = true;
+                Assert.assertEquals(federatedIdentityModel.getUserId(), "twitter1");
+                Assert.assertEquals(federatedIdentityModel.getUserName(), "twuser1");
+            }
+        }
+        Assert.assertTrue(facebookFound && twitterFound && googleFound);
+
+        UserModel foundSocialUser = session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "facebook1", "fbuser1"), realm);
+        Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
+        Assert.assertNull(session.users().getUserByFederatedIdentity(new FederatedIdentityModel("facebook", "not-existing", "not-existing"), realm));
+
+        FederatedIdentityModel foundSocialLink = session.users().getFederatedIdentity(socialUser, "facebook", realm);
+        Assert.assertEquals("facebook1", foundSocialLink.getUserId());
+        Assert.assertEquals("fbuser1", foundSocialLink.getUserName());
+        Assert.assertEquals("facebook", foundSocialLink.getIdentityProvider());
+
+        // Test removing social link
+        Assert.assertTrue(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
+        Assert.assertNull(session.users().getFederatedIdentity(socialUser, "facebook", realm));
+        Assert.assertFalse(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
+        session.users().addFederatedIdentity(realm, socialUser, new FederatedIdentityModel("facebook", "facebook1", "fbuser1"));
+
+        // Test smtp config
+        Map<String, String> smtpConfig = realm.getSmtpConfig();
+        Assert.assertTrue(smtpConfig.size() == 3);
+        Assert.assertEquals("auto@keycloak.org", smtpConfig.get("from"));
+        Assert.assertEquals("localhost", smtpConfig.get("host"));
+        Assert.assertEquals("3025", smtpConfig.get("port"));
+
+        // Test identity providers
+        List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
+        Assert.assertEquals(1, identityProviders.size());
+        IdentityProviderModel google = identityProviders.get(0);
+        Assert.assertEquals("google1", google.getAlias());
+        Assert.assertEquals("google", google.getProviderId());
+        Assert.assertTrue(google.isEnabled());
+        Assert.assertEquals("googleId", google.getConfig().get("clientId"));
+        Assert.assertEquals("googleSecret", google.getConfig().get("clientSecret"));
+
+        // Test federation providers
+        List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
+        Assert.assertTrue(fedProviders.size() == 2);
+        UserFederationProviderModel ldap1 = fedProviders.get(0);
+        Assert.assertEquals("MyLDAPProvider1", ldap1.getDisplayName());
+        Assert.assertEquals("ldap", ldap1.getProviderName());
+        Assert.assertEquals(1, ldap1.getPriority());
+        Assert.assertEquals("ldap://foo", ldap1.getConfig().get(LDAPConstants.CONNECTION_URL));
+
+        UserFederationProviderModel ldap2 = fedProviders.get(1);
+        Assert.assertEquals("MyLDAPProvider2", ldap2.getDisplayName());
+        Assert.assertEquals("ldap://bar", ldap2.getConfig().get(LDAPConstants.CONNECTION_URL));
+
+        // Test federation mappers
+        Set<UserFederationMapperModel> fedMappers1 = realm.getUserFederationMappersByFederationProvider(ldap1.getId());
+        Assert.assertTrue(fedMappers1.size() == 1);
+        UserFederationMapperModel fullNameMapper = fedMappers1.iterator().next();
+        Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
+        Assert.assertEquals(FullNameLDAPFederationMapperFactory.PROVIDER_ID, fullNameMapper.getFederationMapperType());
+        Assert.assertEquals(ldap1.getId(), fullNameMapper.getFederationProviderId());
+        Assert.assertEquals("cn", fullNameMapper.getConfig().get(FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE));
+
+        // All builtin LDAP mappers should be here
+        Set<UserFederationMapperModel> fedMappers2 = realm.getUserFederationMappersByFederationProvider(ldap2.getId());
+        Assert.assertTrue(fedMappers2.size() > 3);
+        Set<UserFederationMapperModel> allMappers = realm.getUserFederationMappers();
+        Assert.assertEquals(allMappers.size(), fedMappers1.size() + fedMappers2.size());
+
+        // Assert that federation link wasn't created during import
+        UserFederationProviderFactory factory = (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, "dummy");
+        Assert.assertNull(factory.getInstance(session, null).getUserByUsername(realm, "wburke"));
+
+        // Test protocol mappers. Default application has all the builtin protocol mappers. OtherApp just gss credential
+        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
+        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "email"));
+        Assert.assertNotNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "given name"));
+        Assert.assertNull(application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
+
+        Assert.assertEquals(1, otherApp.getProtocolMappers().size());
+        Assert.assertNull(otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
+        ProtocolMapperModel gssCredentialMapper = otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
+        Assert.assertEquals(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, gssCredentialMapper.getName());
+        Assert.assertEquals( OIDCLoginProtocol.LOGIN_PROTOCOL, gssCredentialMapper.getProtocol());
+        Assert.assertEquals(UserSessionNoteMapper.PROVIDER_ID, gssCredentialMapper.getProtocolMapper());
+        String includeInAccessToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
+        String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
+        Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
+        Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);
+
+        // Test user consents
+        admin =  session.users().getUserByUsername("admin", realm);
+        Assert.assertEquals(2, admin.getConsents().size());
+
+        UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
+        Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
+        Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
+        Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
+        Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
+
+        UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
+        Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
+        Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
+        Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
+        Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
+        Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));
+    }
+
+    @Test
+    public void install2() throws Exception {
+        RealmManager manager = realmManager;
+        RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm-demo.json");
+        rep.setId("demo");
+        RealmModel realm =manager.importRealm(rep);
+
+        Assert.assertEquals(600, realm.getAccessCodeLifespanUserAction());
+        verifyRequiredCredentials(realm.getRequiredCredentials(), "password");
+    }
+
+    private void verifyRequiredCredentials(List<RequiredCredentialModel> requiredCreds, String expectedType) {
+        Assert.assertEquals(1, requiredCreds.size());
+        Assert.assertEquals(expectedType, requiredCreds.get(0).getType());
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java
index 7637f1d..d4418b1 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java
@@ -1,91 +1,91 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-
-public class ModelTest extends AbstractModelTest {
-
-    @Test
-    public void importExportRealm() {
-        RealmModel realm = realmManager.createRealm("original");
-        realm.setRegistrationAllowed(true);
-        realm.setRegistrationEmailAsUsername(true);
-        realm.setResetPasswordAllowed(true);
-        realm.setEditUsernameAllowed(true);
-        realm.setSslRequired(SslRequired.EXTERNAL);
-        realm.setVerifyEmail(true);
-        realm.setAccessTokenLifespan(1000);
-        realm.setPasswordPolicy(new PasswordPolicy("length"));
-        realm.setAccessCodeLifespan(1001);
-        realm.setAccessCodeLifespanUserAction(1002);
-        KeycloakModelUtils.generateRealmKeys(realm);
-        realm.addDefaultRole("default-role");
-
-        HashMap<String, String> smtp = new HashMap<String,String>();
-        smtp.put("from", "auto@keycloak");
-        smtp.put("hostname", "localhost");
-        realm.setSmtpConfig(smtp);
-
-        realm.setDefaultLocale("en");
-        realm.setAccessCodeLifespanLogin(100);
-        realm.setInternationalizationEnabled(true);
-        realm.setRegistrationEmailAsUsername(true);
-        realm.setSupportedLocales(new HashSet<String>(Arrays.asList("en", "cz")));
-        realm.setEventsListeners(new HashSet<String>(Arrays.asList("jpa", "mongo", "foo")));
-        realm.setEventsExpiration(200);
-        realm.setEventsEnabled(true);
-
-        RealmModel persisted = realmManager.getRealm(realm.getId());
-        assertEquals(realm, persisted);
-
-        RealmModel copy = importExport(realm, "copy");
-        assertEquals(realm, copy);
-    }
-
-    public static void assertEquals(RealmModel expected, RealmModel actual) {
-        Assert.assertEquals(expected.isRegistrationAllowed(), actual.isRegistrationAllowed());
-        Assert.assertEquals(expected.isRegistrationEmailAsUsername(), actual.isRegistrationEmailAsUsername());
-        Assert.assertEquals(expected.isResetPasswordAllowed(), actual.isResetPasswordAllowed());
-        Assert.assertEquals(expected.isEditUsernameAllowed(), actual.isEditUsernameAllowed());
-        Assert.assertEquals(expected.getSslRequired(), actual.getSslRequired());
-        Assert.assertEquals(expected.isVerifyEmail(), actual.isVerifyEmail());
-        Assert.assertEquals(expected.getAccessTokenLifespan(), actual.getAccessTokenLifespan());
-
-        Assert.assertEquals(expected.getAccessCodeLifespan(), actual.getAccessCodeLifespan());
-        Assert.assertEquals(expected.getAccessCodeLifespanUserAction(), actual.getAccessCodeLifespanUserAction());
-        Assert.assertEquals(expected.getPublicKeyPem(), actual.getPublicKeyPem());
-        Assert.assertEquals(expected.getPrivateKeyPem(), actual.getPrivateKeyPem());
-
-        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
-
-        Assert.assertEquals(expected.getSmtpConfig(), actual.getSmtpConfig());
-
-        Assert.assertEquals(expected.getDefaultLocale(), actual.getDefaultLocale());
-        Assert.assertEquals(expected.getAccessCodeLifespanLogin(), actual.getAccessCodeLifespanLogin());
-        Assert.assertEquals(expected.isInternationalizationEnabled(), actual.isInternationalizationEnabled());
-        Assert.assertEquals(expected.isRegistrationEmailAsUsername(), actual.isRegistrationEmailAsUsername());
-        Assert.assertEquals(expected.getSupportedLocales(), actual.getSupportedLocales());
-        Assert.assertEquals(expected.getEventsListeners(), actual.getEventsListeners());
-        Assert.assertEquals(expected.getEventsExpiration(), actual.getEventsExpiration());
-        Assert.assertEquals(expected.isEventsEnabled(), actual.isEventsEnabled());
-    }
-
-    private RealmModel importExport(RealmModel src, String copyName) {
-        RealmRepresentation representation = ModelToRepresentation.toRepresentation(src, true);
-        representation.setRealm(copyName);
-        representation.setId(copyName);
-        RealmModel copy = realmManager.importRealm(representation);
-        return realmManager.getRealm(copy.getId());
-    }
-
-}
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+public class ModelTest extends AbstractModelTest {
+
+    @Test
+    public void importExportRealm() {
+        RealmModel realm = realmManager.createRealm("original");
+        realm.setRegistrationAllowed(true);
+        realm.setRegistrationEmailAsUsername(true);
+        realm.setResetPasswordAllowed(true);
+        realm.setEditUsernameAllowed(true);
+        realm.setSslRequired(SslRequired.EXTERNAL);
+        realm.setVerifyEmail(true);
+        realm.setAccessTokenLifespan(1000);
+        realm.setPasswordPolicy(new PasswordPolicy("length"));
+        realm.setAccessCodeLifespan(1001);
+        realm.setAccessCodeLifespanUserAction(1002);
+        KeycloakModelUtils.generateRealmKeys(realm);
+        realm.addDefaultRole("default-role");
+
+        HashMap<String, String> smtp = new HashMap<String,String>();
+        smtp.put("from", "auto@keycloak");
+        smtp.put("hostname", "localhost");
+        realm.setSmtpConfig(smtp);
+
+        realm.setDefaultLocale("en");
+        realm.setAccessCodeLifespanLogin(100);
+        realm.setInternationalizationEnabled(true);
+        realm.setRegistrationEmailAsUsername(true);
+        realm.setSupportedLocales(new HashSet<String>(Arrays.asList("en", "cz")));
+        realm.setEventsListeners(new HashSet<String>(Arrays.asList("jpa", "mongo", "foo")));
+        realm.setEventsExpiration(200);
+        realm.setEventsEnabled(true);
+
+        RealmModel persisted = realmManager.getRealm(realm.getId());
+        assertEquals(realm, persisted);
+
+        RealmModel copy = importExport(realm, "copy");
+        assertEquals(realm, copy);
+    }
+
+    public static void assertEquals(RealmModel expected, RealmModel actual) {
+        Assert.assertEquals(expected.isRegistrationAllowed(), actual.isRegistrationAllowed());
+        Assert.assertEquals(expected.isRegistrationEmailAsUsername(), actual.isRegistrationEmailAsUsername());
+        Assert.assertEquals(expected.isResetPasswordAllowed(), actual.isResetPasswordAllowed());
+        Assert.assertEquals(expected.isEditUsernameAllowed(), actual.isEditUsernameAllowed());
+        Assert.assertEquals(expected.getSslRequired(), actual.getSslRequired());
+        Assert.assertEquals(expected.isVerifyEmail(), actual.isVerifyEmail());
+        Assert.assertEquals(expected.getAccessTokenLifespan(), actual.getAccessTokenLifespan());
+
+        Assert.assertEquals(expected.getAccessCodeLifespan(), actual.getAccessCodeLifespan());
+        Assert.assertEquals(expected.getAccessCodeLifespanUserAction(), actual.getAccessCodeLifespanUserAction());
+        Assert.assertEquals(expected.getPublicKeyPem(), actual.getPublicKeyPem());
+        Assert.assertEquals(expected.getPrivateKeyPem(), actual.getPrivateKeyPem());
+
+        Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
+
+        Assert.assertEquals(expected.getSmtpConfig(), actual.getSmtpConfig());
+
+        Assert.assertEquals(expected.getDefaultLocale(), actual.getDefaultLocale());
+        Assert.assertEquals(expected.getAccessCodeLifespanLogin(), actual.getAccessCodeLifespanLogin());
+        Assert.assertEquals(expected.isInternationalizationEnabled(), actual.isInternationalizationEnabled());
+        Assert.assertEquals(expected.isRegistrationEmailAsUsername(), actual.isRegistrationEmailAsUsername());
+        Assert.assertEquals(expected.getSupportedLocales(), actual.getSupportedLocales());
+        Assert.assertEquals(expected.getEventsListeners(), actual.getEventsListeners());
+        Assert.assertEquals(expected.getEventsExpiration(), actual.getEventsExpiration());
+        Assert.assertEquals(expected.isEventsEnabled(), actual.isEventsEnabled());
+    }
+
+    private RealmModel importExport(RealmModel src, String copyName) {
+        RealmRepresentation representation = ModelToRepresentation.toRepresentation(src, true);
+        representation.setRealm(copyName);
+        representation.setId(copyName);
+        RealmModel copy = realmManager.importRealm(representation);
+        return realmManager.getRealm(copy.getId());
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index 58196f6..afeb1d3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -1,216 +1,216 @@
-package org.keycloak.testsuite.model;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserModel.RequiredAction;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class UserModelTest extends AbstractModelTest {
-
-    @Test
-    public void persistUser() {
-        RealmModel realm = realmManager.createRealm("original");
-        KeycloakSession session = realmManager.getSession();
-        UserModel user = session.users().addUser(realm, "user");
-        user.setFirstName("first-name");
-        user.setLastName("last-name");
-        user.setEmail("email");
-        assertNotNull(user.getCreatedTimestamp());
-        // test that timestamp is current with 10s tollerance
-        Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
-
-        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
-        user.addRequiredAction(RequiredAction.UPDATE_PASSWORD);
-
-        RealmModel searchRealm = realmManager.getRealm(realm.getId());
-        UserModel persisted = session.users().getUserByUsername("user", searchRealm);
-
-        assertEquals(user, persisted);
-
-        searchRealm = realmManager.getRealm(realm.getId());
-        UserModel persisted2 =  session.users().getUserById(user.getId(), searchRealm);
-        assertEquals(user, persisted2);
-
-        Map<String, String> attributes = new HashMap<String, String>();
-        attributes.put(UserModel.LAST_NAME, "last-name");
-        List<UserModel> search = session.users().searchForUserByAttributes(attributes, realm);
-        Assert.assertEquals(search.size(), 1);
-        Assert.assertEquals(search.get(0).getUsername(), "user");
-
-        attributes.clear();
-        attributes.put(UserModel.EMAIL, "email");
-        search = session.users().searchForUserByAttributes(attributes, realm);
-        Assert.assertEquals(search.size(), 1);
-        Assert.assertEquals(search.get(0).getUsername(), "user");
-
-        attributes.clear();
-        attributes.put(UserModel.LAST_NAME, "last-name");
-        attributes.put(UserModel.EMAIL, "email");
-        search = session.users().searchForUserByAttributes(attributes, realm);
-        Assert.assertEquals(search.size(), 1);
-        Assert.assertEquals(search.get(0).getUsername(), "user");
-    }
-    
-    @Test
-    public void webOriginSetTest() {
-        RealmModel realm = realmManager.createRealm("original");
-        ClientModel client = realm.addClient("user");
-
-        Assert.assertTrue(client.getWebOrigins().isEmpty());
-
-        client.addWebOrigin("origin-1");
-        Assert.assertEquals(1, client.getWebOrigins().size());
-
-        client.addWebOrigin("origin-2");
-        Assert.assertEquals(2, client.getWebOrigins().size());
-
-        client.removeWebOrigin("origin-2");
-        Assert.assertEquals(1, client.getWebOrigins().size());
-
-        client.removeWebOrigin("origin-1");
-        Assert.assertTrue(client.getWebOrigins().isEmpty());
-
-        client = realm.addClient("oauthclient2");
-
-        Assert.assertTrue(client.getWebOrigins().isEmpty());
-
-        client.addWebOrigin("origin-1");
-        Assert.assertEquals(1, client.getWebOrigins().size());
-
-        client.addWebOrigin("origin-2");
-        Assert.assertEquals(2, client.getWebOrigins().size());
-
-        client.removeWebOrigin("origin-2");
-        Assert.assertEquals(1, client.getWebOrigins().size());
-
-        client.removeWebOrigin("origin-1");
-        Assert.assertTrue(client.getWebOrigins().isEmpty());
-
-    }
-
-    @Test
-    public void testUserRequiredActions() throws Exception {
-        RealmModel realm = realmManager.createRealm("original");
-        UserModel user = session.users().addUser(realm, "user");
-
-        Assert.assertTrue(user.getRequiredActions().isEmpty());
-
-        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
-        String id = realm.getId();
-        commit();
-        realm = realmManager.getRealm(id);
-        user = session.users().getUserByUsername("user", realm);
-
-        Assert.assertEquals(1, user.getRequiredActions().size());
-        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
-
-        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
-        user = session.users().getUserByUsername("user", realm);
-
-        Assert.assertEquals(1, user.getRequiredActions().size());
-        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
-
-        user.addRequiredAction(RequiredAction.VERIFY_EMAIL.name());
-        user = session.users().getUserByUsername("user", realm);
-
-        Assert.assertEquals(2, user.getRequiredActions().size());
-        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
-        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
-
-        user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP.name());
-        user = session.users().getUserByUsername("user", realm);
-
-        Assert.assertEquals(1, user.getRequiredActions().size());
-        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
-
-        user.removeRequiredAction(RequiredAction.VERIFY_EMAIL.name());
-        user = session.users().getUserByUsername("user", realm);
-
-        Assert.assertTrue(user.getRequiredActions().isEmpty());
-    }
-
-    @Test
-    public void testUserMultipleAttributes() throws Exception {
-        RealmModel realm = realmManager.createRealm("original");
-        UserModel user = session.users().addUser(realm, "user");
-
-        user.setSingleAttribute("key1", "value1");
-        List<String> attrVals = new ArrayList<>(Arrays.asList( "val21", "val22" ));
-        user.setAttribute("key2", attrVals);
-
-        commit();
-
-        // Test read attributes
-        realm = realmManager.getRealmByName("original");
-        user = session.users().getUserByUsername("user", realm);
-
-        attrVals = user.getAttribute("key1");
-        Assert.assertEquals(1, attrVals.size());
-        Assert.assertEquals("value1", attrVals.get(0));
-        Assert.assertEquals("value1", user.getFirstAttribute("key1"));
-
-        attrVals = user.getAttribute("key2");
-        Assert.assertEquals(2, attrVals.size());
-        Assert.assertTrue(attrVals.contains("val21"));
-        Assert.assertTrue(attrVals.contains("val22"));
-
-        attrVals = user.getAttribute("key3");
-        Assert.assertTrue(attrVals.isEmpty());
-        Assert.assertNull(user.getFirstAttribute("key3"));
-
-        Map<String, List<String>> allAttrVals = user.getAttributes();
-        Assert.assertEquals(2, allAttrVals.size());
-        Assert.assertEquals(allAttrVals.get("key1"), user.getAttribute("key1"));
-        Assert.assertEquals(allAttrVals.get("key2"), user.getAttribute("key2"));
-
-        // Test searching
-        Map<String, String> attributes = new HashMap<String, String>();
-        attributes.put("key2", "val22");
-        List<UserModel> users = session.users().searchForUserByAttributes(attributes, realm);
-        Assert.assertEquals(1, users.size());
-        Assert.assertEquals(users.get(0), user);
-
-        // Test remove and rewrite attribute
-        user.removeAttribute("key1");
-        user.setSingleAttribute("key2", "val23");
-
-        commit();
-
-        realm = realmManager.getRealmByName("original");
-        user = session.users().getUserByUsername("user", realm);
-        Assert.assertNull(user.getFirstAttribute("key1"));
-        attrVals = user.getAttribute("key2");
-        Assert.assertEquals(1, attrVals.size());
-        Assert.assertEquals("val23", attrVals.get(0));
-    }
-
-    public static void assertEquals(UserModel expected, UserModel actual) {
-        Assert.assertEquals(expected.getUsername(), actual.getUsername());
-        Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());
-        Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
-        Assert.assertEquals(expected.getLastName(), actual.getLastName());
-
-        String[] expectedRequiredActions = expected.getRequiredActions().toArray(new String[expected.getRequiredActions().size()]);
-        Arrays.sort(expectedRequiredActions);
-        String[] actualRequiredActions = actual.getRequiredActions().toArray(new String[actual.getRequiredActions().size()]);
-        Arrays.sort(actualRequiredActions);
-
-        Assert.assertArrayEquals(expectedRequiredActions, actualRequiredActions);
-    }
-
-}
-
+package org.keycloak.testsuite.model;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserModel.RequiredAction;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class UserModelTest extends AbstractModelTest {
+
+    @Test
+    public void persistUser() {
+        RealmModel realm = realmManager.createRealm("original");
+        KeycloakSession session = realmManager.getSession();
+        UserModel user = session.users().addUser(realm, "user");
+        user.setFirstName("first-name");
+        user.setLastName("last-name");
+        user.setEmail("email");
+        assertNotNull(user.getCreatedTimestamp());
+        // test that timestamp is current with 10s tollerance
+        Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
+
+        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
+        user.addRequiredAction(RequiredAction.UPDATE_PASSWORD);
+
+        RealmModel searchRealm = realmManager.getRealm(realm.getId());
+        UserModel persisted = session.users().getUserByUsername("user", searchRealm);
+
+        assertEquals(user, persisted);
+
+        searchRealm = realmManager.getRealm(realm.getId());
+        UserModel persisted2 =  session.users().getUserById(user.getId(), searchRealm);
+        assertEquals(user, persisted2);
+
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put(UserModel.LAST_NAME, "last-name");
+        List<UserModel> search = session.users().searchForUserByAttributes(attributes, realm);
+        Assert.assertEquals(search.size(), 1);
+        Assert.assertEquals(search.get(0).getUsername(), "user");
+
+        attributes.clear();
+        attributes.put(UserModel.EMAIL, "email");
+        search = session.users().searchForUserByAttributes(attributes, realm);
+        Assert.assertEquals(search.size(), 1);
+        Assert.assertEquals(search.get(0).getUsername(), "user");
+
+        attributes.clear();
+        attributes.put(UserModel.LAST_NAME, "last-name");
+        attributes.put(UserModel.EMAIL, "email");
+        search = session.users().searchForUserByAttributes(attributes, realm);
+        Assert.assertEquals(search.size(), 1);
+        Assert.assertEquals(search.get(0).getUsername(), "user");
+    }
+    
+    @Test
+    public void webOriginSetTest() {
+        RealmModel realm = realmManager.createRealm("original");
+        ClientModel client = realm.addClient("user");
+
+        Assert.assertTrue(client.getWebOrigins().isEmpty());
+
+        client.addWebOrigin("origin-1");
+        Assert.assertEquals(1, client.getWebOrigins().size());
+
+        client.addWebOrigin("origin-2");
+        Assert.assertEquals(2, client.getWebOrigins().size());
+
+        client.removeWebOrigin("origin-2");
+        Assert.assertEquals(1, client.getWebOrigins().size());
+
+        client.removeWebOrigin("origin-1");
+        Assert.assertTrue(client.getWebOrigins().isEmpty());
+
+        client = realm.addClient("oauthclient2");
+
+        Assert.assertTrue(client.getWebOrigins().isEmpty());
+
+        client.addWebOrigin("origin-1");
+        Assert.assertEquals(1, client.getWebOrigins().size());
+
+        client.addWebOrigin("origin-2");
+        Assert.assertEquals(2, client.getWebOrigins().size());
+
+        client.removeWebOrigin("origin-2");
+        Assert.assertEquals(1, client.getWebOrigins().size());
+
+        client.removeWebOrigin("origin-1");
+        Assert.assertTrue(client.getWebOrigins().isEmpty());
+
+    }
+
+    @Test
+    public void testUserRequiredActions() throws Exception {
+        RealmModel realm = realmManager.createRealm("original");
+        UserModel user = session.users().addUser(realm, "user");
+
+        Assert.assertTrue(user.getRequiredActions().isEmpty());
+
+        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
+        String id = realm.getId();
+        commit();
+        realm = realmManager.getRealm(id);
+        user = session.users().getUserByUsername("user", realm);
+
+        Assert.assertEquals(1, user.getRequiredActions().size());
+        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
+
+        user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
+        user = session.users().getUserByUsername("user", realm);
+
+        Assert.assertEquals(1, user.getRequiredActions().size());
+        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
+
+        user.addRequiredAction(RequiredAction.VERIFY_EMAIL.name());
+        user = session.users().getUserByUsername("user", realm);
+
+        Assert.assertEquals(2, user.getRequiredActions().size());
+        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
+        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
+
+        user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP.name());
+        user = session.users().getUserByUsername("user", realm);
+
+        Assert.assertEquals(1, user.getRequiredActions().size());
+        Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
+
+        user.removeRequiredAction(RequiredAction.VERIFY_EMAIL.name());
+        user = session.users().getUserByUsername("user", realm);
+
+        Assert.assertTrue(user.getRequiredActions().isEmpty());
+    }
+
+    @Test
+    public void testUserMultipleAttributes() throws Exception {
+        RealmModel realm = realmManager.createRealm("original");
+        UserModel user = session.users().addUser(realm, "user");
+
+        user.setSingleAttribute("key1", "value1");
+        List<String> attrVals = new ArrayList<>(Arrays.asList( "val21", "val22" ));
+        user.setAttribute("key2", attrVals);
+
+        commit();
+
+        // Test read attributes
+        realm = realmManager.getRealmByName("original");
+        user = session.users().getUserByUsername("user", realm);
+
+        attrVals = user.getAttribute("key1");
+        Assert.assertEquals(1, attrVals.size());
+        Assert.assertEquals("value1", attrVals.get(0));
+        Assert.assertEquals("value1", user.getFirstAttribute("key1"));
+
+        attrVals = user.getAttribute("key2");
+        Assert.assertEquals(2, attrVals.size());
+        Assert.assertTrue(attrVals.contains("val21"));
+        Assert.assertTrue(attrVals.contains("val22"));
+
+        attrVals = user.getAttribute("key3");
+        Assert.assertTrue(attrVals.isEmpty());
+        Assert.assertNull(user.getFirstAttribute("key3"));
+
+        Map<String, List<String>> allAttrVals = user.getAttributes();
+        Assert.assertEquals(2, allAttrVals.size());
+        Assert.assertEquals(allAttrVals.get("key1"), user.getAttribute("key1"));
+        Assert.assertEquals(allAttrVals.get("key2"), user.getAttribute("key2"));
+
+        // Test searching
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put("key2", "val22");
+        List<UserModel> users = session.users().searchForUserByAttributes(attributes, realm);
+        Assert.assertEquals(1, users.size());
+        Assert.assertEquals(users.get(0), user);
+
+        // Test remove and rewrite attribute
+        user.removeAttribute("key1");
+        user.setSingleAttribute("key2", "val23");
+
+        commit();
+
+        realm = realmManager.getRealmByName("original");
+        user = session.users().getUserByUsername("user", realm);
+        Assert.assertNull(user.getFirstAttribute("key1"));
+        attrVals = user.getAttribute("key2");
+        Assert.assertEquals(1, attrVals.size());
+        Assert.assertEquals("val23", attrVals.get(0));
+    }
+
+    public static void assertEquals(UserModel expected, UserModel actual) {
+        Assert.assertEquals(expected.getUsername(), actual.getUsername());
+        Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());
+        Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
+        Assert.assertEquals(expected.getLastName(), actual.getLastName());
+
+        String[] expectedRequiredActions = expected.getRequiredActions().toArray(new String[expected.getRequiredActions().size()]);
+        Arrays.sort(expectedRequiredActions);
+        String[] actualRequiredActions = actual.getRequiredActions().toArray(new String[actual.getRequiredActions().size()]);
+        Arrays.sort(actualRequiredActions);
+
+        Assert.assertArrayEquals(expectedRequiredActions, actualRequiredActions);
+    }
+
+}
+
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 89d353b..4c62dd8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -1,756 +1,756 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.oauth;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.VerificationException;
-import org.keycloak.enums.SslRequired;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
-import org.keycloak.events.Event;
-import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.protocol.oidc.mappers.AddressMapper;
-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.representations.AccessToken;
-import org.keycloak.representations.IDToken;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.AssertEvents;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.util.BasicAuthHelper;
-import org.keycloak.util.Time;
-import org.openqa.selenium.WebDriver;
-
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class AccessTokenTest {
-
-    @ClassRule
-    public static KeycloakRule keycloakRule = new KeycloakRule();
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @WebResource
-    protected OAuthClient oauth;
-
-    @WebResource
-    protected LoginPage loginPage;
-
-    @Rule
-    public AssertEvents events = new AssertEvents(keycloakRule);
-
-    @Test
-    public void accessTokenRequest() throws Exception {
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-
-        String sessionId = loginEvent.getSessionId();
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
-        Assert.assertThat(response.getRefreshExpiresIn(), allOf(greaterThanOrEqualTo(1750), lessThanOrEqualTo(1800)));
-
-        Assert.assertEquals("bearer", response.getTokenType());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-
-        Assert.assertEquals(keycloakRule.getUser("test", "test-user@localhost").getId(), token.getSubject());
-        Assert.assertNotEquals("test-user@localhost", token.getSubject());
-
-        Assert.assertEquals(sessionId, token.getSessionState());
-
-        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
-
-        Assert.assertEquals(1, token.getResourceAccess(oauth.getClientId()).getRoles().size());
-        Assert.assertTrue(token.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
-
-        Event event = events.expectCodeToToken(codeId, sessionId).assertEvent();
-        Assert.assertEquals(token.getId(), event.getDetails().get(Details.TOKEN_ID));
-        Assert.assertEquals(oauth.verifyRefreshToken(response.getRefreshToken()).getId(), event.getDetails().get(Details.REFRESH_TOKEN_ID));
-        Assert.assertEquals(sessionId, token.getSessionState());
-
-    }
-
-    @Test
-    public void accessTokenInvalidClientCredentials() throws Exception {
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "invalid");
-        Assert.assertEquals(400, response.getStatusCode());
-
-        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_client_credentials").clearDetails().user((String) null).session((String) null);
-        expectedEvent.assertEvent();
-    }
-
-    @Test
-    public void accessTokenInvalidRedirectUri() throws Exception {
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-
-        oauth.redirectUri("http://invalid");
-
-        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-        Assert.assertEquals(400, response.getStatusCode());
-        Assert.assertEquals("invalid_grant", response.getError());
-        Assert.assertEquals("Incorrect redirect_uri", response.getErrorDescription());
-
-        events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).assertEvent();
-    }
-
-    @Test
-    public void accessTokenUserSessionExpired() {
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-        String sessionId = loginEvent.getSessionId();
-
-        keycloakRule.removeUserSession(sessionId);
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-
-        OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
-        assertEquals(400, tokenResponse.getStatusCode());
-        assertNull(tokenResponse.getAccessToken());
-        assertNull(tokenResponse.getRefreshToken());
-
-        events.expectCodeToToken(codeId, sessionId).removeDetail(Details.TOKEN_ID).user((String) null).session((String) null).removeDetail(Details.REFRESH_TOKEN_ID).error(Errors.INVALID_CODE).assertEvent();
-
-        events.clear();
-    }
-
-    @Test
-    public void accessTokenCodeExpired() {
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setAccessCodeLifespan(1);
-            }
-        });
-
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-        loginEvent.getSessionId();
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-
-        Time.setOffset(2);
-
-        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-        Assert.assertEquals(400, response.getStatusCode());
-
-        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
-        expectedEvent.error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).user((String) null);
-        expectedEvent.assertEvent();
-
-        events.clear();
-
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setAccessCodeLifespan(60);
-            }
-        });
-
-        Time.setOffset(0);
-    }
-
-    @Test
-    public void accessTokenCodeUsed() {
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-        loginEvent.getSessionId();
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-        Assert.assertEquals(200, response.getStatusCode());
-
-        events.clear();
-
-        response = oauth.doAccessTokenRequest(code, "password");
-        Assert.assertEquals(400, response.getStatusCode());
-
-        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
-        expectedEvent.error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).user((String) null);
-        expectedEvent.assertEvent();
-
-        events.clear();
-
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.setAccessCodeLifespan(60);
-            }
-        });
-    }
-
-    @Test
-    public void accessTokenCodeRoleMissing() {
-        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                RoleModel role = appRealm.addRole("tmp-role");
-                session.users().getUserByUsername("test-user@localhost", appRealm).grantRole(role);
-            }
-        });
-
-        oauth.doLogin("test-user@localhost", "password");
-
-        Event loginEvent = events.expectLogin().assertEvent();
-
-        loginEvent.getDetails().get(Details.CODE_ID);
-
-        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
-
-        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.removeRole(appRealm.getRole("tmp-role"));
-            }
-        });
-
-        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-
-        Assert.assertEquals(200, response.getStatusCode());
-
-        AccessToken token = oauth.verifyToken(response.getAccessToken());
-        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
-        Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
-
-        events.clear();
-    }
-
-    @Test
-    public void accessTokenCodeHasRequiredAction() {
-        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
-                UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
-                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
-            }
-        });
-
-        oauth.doLogin("test-user@localhost", "password");
-
-        String code = driver.getPageSource().split("code=")[1].split("&")[0].split("\"")[0];
-
-        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
-        Assert.assertEquals(400, response.getStatusCode());
-
-        Event event = events.poll();
-        assertNotNull(event.getDetails().get(Details.CODE_ID));
-
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                manager.getSession().users().getUserByUsername("test-user@localhost", appRealm).removeRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
-            }
-        });
-    }
-
-    @Test
-    public void testValidateAccessToken() throws Exception {
-        Client client = ClientBuilder.newClient();
-        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
-        WebTarget grantTarget = client.target(grantUri);
-        builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI validateUri = OIDCLoginProtocolService.validateAccessTokenUrl(builder).build("test");
-        WebTarget validateTarget = client.target(validateUri);
-
-        {
-            Response response = validateTarget.queryParam("access_token", "bad token").request().get();
-            Assert.assertEquals(400, response.getStatus());
-            HashMap<String, String> error = response.readEntity(new GenericType <HashMap<String, String>>() {});
-            Assert.assertNotNull(error.get("error"));
-        }
-
-
-        org.keycloak.representations.AccessTokenResponse tokenResponse = null;
-        {
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(200, response.getStatus());
-            tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
-            response.close();
-        }
-
-        {
-            Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
-            Assert.assertEquals(200, response.getStatus());
-            AccessToken token = response.readEntity(AccessToken.class);
-            Assert.assertNotNull(token);
-            response.close();
-        }
-        {
-            builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-            URI logoutUri = OIDCLoginProtocolService.logoutUrl(builder).build("test");
-            String header = BasicAuthHelper.createHeader("test-app", "password");
-            Form form = new Form();
-            form.param("refresh_token", tokenResponse.getRefreshToken());
-            Response response = client.target(logoutUri).request()
-                    .header(HttpHeaders.AUTHORIZATION, header)
-                    .post(Entity.form(form));
-            Assert.assertEquals(204, response.getStatus());
-            response.close();
-        }
-        {
-            Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
-            Assert.assertEquals(400, response.getStatus());
-            HashMap<String, String> error = response.readEntity(new GenericType <HashMap<String, String>>() {});
-            Assert.assertNotNull(error.get("error"));
-        }
-
-        client.close();
-        events.clear();
-
-    }
-
-    @Test
-    public void testGrantAccessToken() throws Exception {
-        Client client = ClientBuilder.newClient();
-        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
-        WebTarget grantTarget = client.target(grantUri);
-
-        {   // test checkSsl
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                realm.setSslRequired(SslRequired.ALL);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(403, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                realm.setSslRequired(SslRequired.EXTERNAL);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-
-        {   // test null username
-            String header = BasicAuthHelper.createHeader("test-app", "password");
-            Form form = new Form();
-            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
-            form.param("password", "password");
-            Response response = grantTarget.request()
-                    .header(HttpHeaders.AUTHORIZATION, header)
-                    .post(Entity.form(form));
-            Assert.assertEquals(401, response.getStatus());
-            response.close();
-        }
-
-        {   // test no password
-            String header = BasicAuthHelper.createHeader("test-app", "password");
-            Form form = new Form();
-            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
-            form.param("username", "test-user@localhost");
-            Response response = grantTarget.request()
-                    .header(HttpHeaders.AUTHORIZATION, header)
-                    .post(Entity.form(form));
-            Assert.assertEquals(401, response.getStatus());
-            response.close();
-        }
-
-        {   // test invalid password
-            String header = BasicAuthHelper.createHeader("test-app", "password");
-            Form form = new Form();
-            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
-            form.param("username", "test-user@localhost");
-            form.param("password", "invalid");
-            Response response = grantTarget.request()
-                    .header(HttpHeaders.AUTHORIZATION, header)
-                    .post(Entity.form(form));
-            Assert.assertEquals(401, response.getStatus());
-            response.close();
-        }
-        {   // test no password
-            String header = BasicAuthHelper.createHeader("test-app", "password");
-            Form form = new Form();
-            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
-            form.param("username", "test-user@localhost");
-            Response response = grantTarget.request()
-                    .header(HttpHeaders.AUTHORIZATION, header)
-                    .post(Entity.form(form));
-            Assert.assertEquals(401, response.getStatus());
-            response.close();
-        }
-
-        {   // test bearer-only
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.getClientByClientId("test-app");
-                clientModel.setBearerOnly(true);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(400, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.getClientByClientId("test-app");
-                clientModel.setBearerOnly(false);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-
-        {   // test realm disabled
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                realm.setEnabled(false);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(403, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                realm.setEnabled(true);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-
-        {   // test application disabled
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.getClientByClientId("test-app");
-                clientModel.setEnabled(false);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(400, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.getClientByClientId("test-app");
-                clientModel.setEnabled(true);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-
-        {   // test user action required
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
-                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(400, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
-                user.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-        {   // test user disabled
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
-                user.setEnabled(false);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(400, response.getStatus());
-            response.close();
-
-            {
-                KeycloakSession session = keycloakRule.startSession();
-                RealmModel realm = session.realms().getRealmByName("test");
-                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
-                user.setEnabled(true);
-                session.getTransaction().commit();
-                session.close();
-            }
-
-        }
-
-
-        {
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(200, response.getStatus());
-            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
-            response.close();
-        }
-
-        client.close();
-        events.clear();
-
-    }
-
-    @Test
-    public void testTokenMapping() throws Exception {
-        Client client = ClientBuilder.newClient();
-        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
-        WebTarget grantTarget = client.target(grantUri);
-        {
-            KeycloakSession session = keycloakRule.startSession();
-            RealmModel realm = session.realms().getRealmByName("test");
-            UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
-            user.setSingleAttribute("street", "5 Yawkey Way");
-            user.setSingleAttribute("locality", "Boston");
-            user.setSingleAttribute("region", "MA");
-            user.setSingleAttribute("postal_code", "02115");
-            user.setSingleAttribute("country", "USA");
-            user.setSingleAttribute("phone", "617-777-6666");
-            List<String> departments = Arrays.asList("finance", "development");
-            user.setAttribute("departments", departments);
-            ClientModel app = realm.getClientByClientId("test-app");
-            ProtocolMapperModel mapper = AddressMapper.createAddressMapper(true, true);
-            app.addProtocolMapper(mapper);
-            app.addProtocolMapper(HardcodedClaim.create("hard", "hard", "coded", "String", false, null, true, true));
-            app.addProtocolMapper(HardcodedClaim.create("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
-            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
-            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
-            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
-            app.addProtocolMapper(HardcodedRole.create("hard-realm", "hardcoded"));
-            app.addProtocolMapper(HardcodedRole.create("hard-app", "app.hardcoded"));
-            app.addProtocolMapper(RoleNameMapper.create("rename-app-role", "test-app.customer-user", "realm-user"));
-            session.getTransaction().commit();
-            session.close();
-        }
-
-        {
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            Assert.assertEquals(200, response.getStatus());
-            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
-            IDToken idToken = getIdToken(tokenResponse);
-            Assert.assertNotNull(idToken.getAddress());
-            Assert.assertEquals(idToken.getName(), "Tom Brady");
-            Assert.assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
-            Assert.assertEquals(idToken.getAddress().getLocality(), "Boston");
-            Assert.assertEquals(idToken.getAddress().getRegion(), "MA");
-            Assert.assertEquals(idToken.getAddress().getPostalCode(), "02115");
-            Assert.assertEquals(idToken.getAddress().getCountry(), "USA");
-            Assert.assertNotNull(idToken.getOtherClaims().get("home_phone"));
-            Assert.assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
-            Assert.assertEquals("coded", idToken.getOtherClaims().get("hard"));
-            Map nested = (Map)idToken.getOtherClaims().get("nested");
-            Assert.assertEquals("coded-nested", nested.get("hard"));
-            nested = (Map)idToken.getOtherClaims().get("home");
-            Assert.assertEquals("617-777-6666", nested.get("phone"));
-            List<String> departments = (List<String>)idToken.getOtherClaims().get("department");
-            Assert.assertEquals(2, departments.size());
-            Assert.assertTrue(departments.contains("finance") && departments.contains("development"));
-
-            AccessToken accessToken = getAccessToken(tokenResponse);
-            Assert.assertEquals(accessToken.getName(), "Tom Brady");
-            Assert.assertNotNull(accessToken.getAddress());
-            Assert.assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
-            Assert.assertEquals(accessToken.getAddress().getLocality(), "Boston");
-            Assert.assertEquals(accessToken.getAddress().getRegion(), "MA");
-            Assert.assertEquals(accessToken.getAddress().getPostalCode(), "02115");
-            Assert.assertEquals(accessToken.getAddress().getCountry(), "USA");
-            Assert.assertNotNull(accessToken.getOtherClaims().get("home_phone"));
-            Assert.assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
-            Assert.assertEquals("coded", accessToken.getOtherClaims().get("hard"));
-            nested = (Map)accessToken.getOtherClaims().get("nested");
-            Assert.assertEquals("coded-nested", nested.get("hard"));
-            nested = (Map)accessToken.getOtherClaims().get("home");
-            Assert.assertEquals("617-777-6666", nested.get("phone"));
-            departments = (List<String>)idToken.getOtherClaims().get("department");
-            Assert.assertEquals(2, departments.size());
-            Assert.assertTrue(departments.contains("finance") && departments.contains("development"));
-            Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
-            Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
-            Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
-            Assert.assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
-
-
-            response.close();
-        }
-        client.close();
-
-        // undo mappers
-        {
-            KeycloakSession session = keycloakRule.startSession();
-            RealmModel realm = session.realms().getRealmByName("test");
-            ClientModel app = realm.getClientByClientId("test-app");
-            for (ProtocolMapperModel model : app.getProtocolMappers()) {
-                if (model.getName().equals("address")
-                        || model.getName().equals("hard")
-                        || model.getName().equals("hard-nested")
-                        || model.getName().equals("custom phone")
-                        || model.getName().equals("nested phone")
-                        || model.getName().equals("rename-app-role")
-                        || model.getName().equals("hard-realm")
-                        || model.getName().equals("hard-app")
-                        )   {
-                    app.removeProtocolMapper(model);
-                }
-            }
-            session.getTransaction().commit();
-            session.close();
-        }
-
-
-        events.clear();
-
-    }
-
-    private IDToken getIdToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException {
-        JWSInput input = new JWSInput(tokenResponse.getIdToken());
-        IDToken idToken = null;
-        try {
-            idToken = input.readJsonContent(IDToken.class);
-        } catch (IOException e) {
-            throw new VerificationException();
-        }
-        return idToken;
-    }
-
-    private AccessToken getAccessToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException {
-        JWSInput input = new JWSInput(tokenResponse.getToken());
-        AccessToken idToken = null;
-        try {
-            idToken = input.readJsonContent(AccessToken.class);
-        } catch (IOException e) {
-            throw new VerificationException();
-        }
-        return idToken;
-    }
-
-    protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) {
-        String header = BasicAuthHelper.createHeader("test-app", "password");
-        Form form = new Form();
-        form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
-                .param("username", "test-user@localhost")
-                .param("password", "password");
-        return grantTarget.request()
-                .header(HttpHeaders.AUTHORIZATION, header)
-                .post(Entity.form(form));
-    }
-
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.oauth;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.VerificationException;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.Event;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.protocol.oidc.mappers.AddressMapper;
+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.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.util.BasicAuthHelper;
+import org.keycloak.util.Time;
+import org.openqa.selenium.WebDriver;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AccessTokenTest {
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule();
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @Rule
+    public AssertEvents events = new AssertEvents(keycloakRule);
+
+    @Test
+    public void accessTokenRequest() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+
+        String sessionId = loginEvent.getSessionId();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
+        Assert.assertThat(response.getRefreshExpiresIn(), allOf(greaterThanOrEqualTo(1750), lessThanOrEqualTo(1800)));
+
+        Assert.assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        Assert.assertEquals(keycloakRule.getUser("test", "test-user@localhost").getId(), token.getSubject());
+        Assert.assertNotEquals("test-user@localhost", token.getSubject());
+
+        Assert.assertEquals(sessionId, token.getSessionState());
+
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
+
+        Assert.assertEquals(1, token.getResourceAccess(oauth.getClientId()).getRoles().size());
+        Assert.assertTrue(token.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
+
+        Event event = events.expectCodeToToken(codeId, sessionId).assertEvent();
+        Assert.assertEquals(token.getId(), event.getDetails().get(Details.TOKEN_ID));
+        Assert.assertEquals(oauth.verifyRefreshToken(response.getRefreshToken()).getId(), event.getDetails().get(Details.REFRESH_TOKEN_ID));
+        Assert.assertEquals(sessionId, token.getSessionState());
+
+    }
+
+    @Test
+    public void accessTokenInvalidClientCredentials() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "invalid");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_client_credentials").clearDetails().user((String) null).session((String) null);
+        expectedEvent.assertEvent();
+    }
+
+    @Test
+    public void accessTokenInvalidRedirectUri() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        oauth.redirectUri("http://invalid");
+
+        AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+        Assert.assertEquals("invalid_grant", response.getError());
+        Assert.assertEquals("Incorrect redirect_uri", response.getErrorDescription());
+
+        events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).assertEvent();
+    }
+
+    @Test
+    public void accessTokenUserSessionExpired() {
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        String sessionId = loginEvent.getSessionId();
+
+        keycloakRule.removeUserSession(sessionId);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
+        assertEquals(400, tokenResponse.getStatusCode());
+        assertNull(tokenResponse.getAccessToken());
+        assertNull(tokenResponse.getRefreshToken());
+
+        events.expectCodeToToken(codeId, sessionId).removeDetail(Details.TOKEN_ID).user((String) null).session((String) null).removeDetail(Details.REFRESH_TOKEN_ID).error(Errors.INVALID_CODE).assertEvent();
+
+        events.clear();
+    }
+
+    @Test
+    public void accessTokenCodeExpired() {
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setAccessCodeLifespan(1);
+            }
+        });
+
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        loginEvent.getSessionId();
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        Time.setOffset(2);
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
+        expectedEvent.error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).user((String) null);
+        expectedEvent.assertEvent();
+
+        events.clear();
+
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setAccessCodeLifespan(60);
+            }
+        });
+
+        Time.setOffset(0);
+    }
+
+    @Test
+    public void accessTokenCodeUsed() {
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        loginEvent.getSessionId();
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(200, response.getStatusCode());
+
+        events.clear();
+
+        response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
+        expectedEvent.error("invalid_code").removeDetail(Details.TOKEN_ID).removeDetail(Details.REFRESH_TOKEN_ID).user((String) null);
+        expectedEvent.assertEvent();
+
+        events.clear();
+
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.setAccessCodeLifespan(60);
+            }
+        });
+    }
+
+    @Test
+    public void accessTokenCodeRoleMissing() {
+        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                RoleModel role = appRealm.addRole("tmp-role");
+                session.users().getUserByUsername("test-user@localhost", appRealm).grantRole(role);
+            }
+        });
+
+        oauth.doLogin("test-user@localhost", "password");
+
+        Event loginEvent = events.expectLogin().assertEvent();
+
+        loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                appRealm.removeRole(appRealm.getRole("tmp-role"));
+            }
+        });
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
+
+        events.clear();
+    }
+
+    @Test
+    public void accessTokenCodeHasRequiredAction() {
+        keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
+                UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
+                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
+            }
+        });
+
+        oauth.doLogin("test-user@localhost", "password");
+
+        String code = driver.getPageSource().split("code=")[1].split("&")[0].split("\"")[0];
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        Event event = events.poll();
+        assertNotNull(event.getDetails().get(Details.CODE_ID));
+
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                manager.getSession().users().getUserByUsername("test-user@localhost", appRealm).removeRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
+            }
+        });
+    }
+
+    @Test
+    public void testValidateAccessToken() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI validateUri = OIDCLoginProtocolService.validateAccessTokenUrl(builder).build("test");
+        WebTarget validateTarget = client.target(validateUri);
+
+        {
+            Response response = validateTarget.queryParam("access_token", "bad token").request().get();
+            Assert.assertEquals(400, response.getStatus());
+            HashMap<String, String> error = response.readEntity(new GenericType <HashMap<String, String>>() {});
+            Assert.assertNotNull(error.get("error"));
+        }
+
+
+        org.keycloak.representations.AccessTokenResponse tokenResponse = null;
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(200, response.getStatus());
+            tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            response.close();
+        }
+
+        {
+            Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
+            Assert.assertEquals(200, response.getStatus());
+            AccessToken token = response.readEntity(AccessToken.class);
+            Assert.assertNotNull(token);
+            response.close();
+        }
+        {
+            builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+            URI logoutUri = OIDCLoginProtocolService.logoutUrl(builder).build("test");
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param("refresh_token", tokenResponse.getRefreshToken());
+            Response response = client.target(logoutUri).request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            Assert.assertEquals(204, response.getStatus());
+            response.close();
+        }
+        {
+            Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
+            Assert.assertEquals(400, response.getStatus());
+            HashMap<String, String> error = response.readEntity(new GenericType <HashMap<String, String>>() {});
+            Assert.assertNotNull(error.get("error"));
+        }
+
+        client.close();
+        events.clear();
+
+    }
+
+    @Test
+    public void testGrantAccessToken() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+
+        {   // test checkSsl
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                realm.setSslRequired(SslRequired.ALL);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(403, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                realm.setSslRequired(SslRequired.EXTERNAL);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+
+        {   // test null username
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("password", "password");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            Assert.assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   // test no password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            Assert.assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   // test invalid password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            form.param("password", "invalid");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            Assert.assertEquals(401, response.getStatus());
+            response.close();
+        }
+        {   // test no password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            Assert.assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   // test bearer-only
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
+                clientModel.setBearerOnly(true);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
+                clientModel.setBearerOnly(false);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+
+        {   // test realm disabled
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                realm.setEnabled(false);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(403, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                realm.setEnabled(true);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+
+        {   // test application disabled
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
+                clientModel.setEnabled(false);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
+                clientModel.setEnabled(true);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+
+        {   // test user action required
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
+                user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
+                user.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+        {   // test user disabled
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
+                user.setEnabled(false);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                KeycloakSession session = keycloakRule.startSession();
+                RealmModel realm = session.realms().getRealmByName("test");
+                UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
+                user.setEnabled(true);
+                session.getTransaction().commit();
+                session.close();
+            }
+
+        }
+
+
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            response.close();
+        }
+
+        client.close();
+        events.clear();
+
+    }
+
+    @Test
+    public void testTokenMapping() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        {
+            KeycloakSession session = keycloakRule.startSession();
+            RealmModel realm = session.realms().getRealmByName("test");
+            UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
+            user.setSingleAttribute("street", "5 Yawkey Way");
+            user.setSingleAttribute("locality", "Boston");
+            user.setSingleAttribute("region", "MA");
+            user.setSingleAttribute("postal_code", "02115");
+            user.setSingleAttribute("country", "USA");
+            user.setSingleAttribute("phone", "617-777-6666");
+            List<String> departments = Arrays.asList("finance", "development");
+            user.setAttribute("departments", departments);
+            ClientModel app = realm.getClientByClientId("test-app");
+            ProtocolMapperModel mapper = AddressMapper.createAddressMapper(true, true);
+            app.addProtocolMapper(mapper);
+            app.addProtocolMapper(HardcodedClaim.create("hard", "hard", "coded", "String", false, null, true, true));
+            app.addProtocolMapper(HardcodedClaim.create("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
+            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
+            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
+            app.addProtocolMapper(UserAttributeMapper.createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
+            app.addProtocolMapper(HardcodedRole.create("hard-realm", "hardcoded"));
+            app.addProtocolMapper(HardcodedRole.create("hard-app", "app.hardcoded"));
+            app.addProtocolMapper(RoleNameMapper.create("rename-app-role", "test-app.customer-user", "realm-user"));
+            session.getTransaction().commit();
+            session.close();
+        }
+
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            Assert.assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            IDToken idToken = getIdToken(tokenResponse);
+            Assert.assertNotNull(idToken.getAddress());
+            Assert.assertEquals(idToken.getName(), "Tom Brady");
+            Assert.assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            Assert.assertEquals(idToken.getAddress().getLocality(), "Boston");
+            Assert.assertEquals(idToken.getAddress().getRegion(), "MA");
+            Assert.assertEquals(idToken.getAddress().getPostalCode(), "02115");
+            Assert.assertEquals(idToken.getAddress().getCountry(), "USA");
+            Assert.assertNotNull(idToken.getOtherClaims().get("home_phone"));
+            Assert.assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
+            Assert.assertEquals("coded", idToken.getOtherClaims().get("hard"));
+            Map nested = (Map)idToken.getOtherClaims().get("nested");
+            Assert.assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map)idToken.getOtherClaims().get("home");
+            Assert.assertEquals("617-777-6666", nested.get("phone"));
+            List<String> departments = (List<String>)idToken.getOtherClaims().get("department");
+            Assert.assertEquals(2, departments.size());
+            Assert.assertTrue(departments.contains("finance") && departments.contains("development"));
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            Assert.assertEquals(accessToken.getName(), "Tom Brady");
+            Assert.assertNotNull(accessToken.getAddress());
+            Assert.assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            Assert.assertEquals(accessToken.getAddress().getLocality(), "Boston");
+            Assert.assertEquals(accessToken.getAddress().getRegion(), "MA");
+            Assert.assertEquals(accessToken.getAddress().getPostalCode(), "02115");
+            Assert.assertEquals(accessToken.getAddress().getCountry(), "USA");
+            Assert.assertNotNull(accessToken.getOtherClaims().get("home_phone"));
+            Assert.assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
+            Assert.assertEquals("coded", accessToken.getOtherClaims().get("hard"));
+            nested = (Map)accessToken.getOtherClaims().get("nested");
+            Assert.assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map)accessToken.getOtherClaims().get("home");
+            Assert.assertEquals("617-777-6666", nested.get("phone"));
+            departments = (List<String>)idToken.getOtherClaims().get("department");
+            Assert.assertEquals(2, departments.size());
+            Assert.assertTrue(departments.contains("finance") && departments.contains("development"));
+            Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
+            Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
+            Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
+            Assert.assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
+
+
+            response.close();
+        }
+        client.close();
+
+        // undo mappers
+        {
+            KeycloakSession session = keycloakRule.startSession();
+            RealmModel realm = session.realms().getRealmByName("test");
+            ClientModel app = realm.getClientByClientId("test-app");
+            for (ProtocolMapperModel model : app.getProtocolMappers()) {
+                if (model.getName().equals("address")
+                        || model.getName().equals("hard")
+                        || model.getName().equals("hard-nested")
+                        || model.getName().equals("custom phone")
+                        || model.getName().equals("nested phone")
+                        || model.getName().equals("rename-app-role")
+                        || model.getName().equals("hard-realm")
+                        || model.getName().equals("hard-app")
+                        )   {
+                    app.removeProtocolMapper(model);
+                }
+            }
+            session.getTransaction().commit();
+            session.close();
+        }
+
+
+        events.clear();
+
+    }
+
+    private IDToken getIdToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException {
+        JWSInput input = new JWSInput(tokenResponse.getIdToken());
+        IDToken idToken = null;
+        try {
+            idToken = input.readJsonContent(IDToken.class);
+        } catch (IOException e) {
+            throw new VerificationException();
+        }
+        return idToken;
+    }
+
+    private AccessToken getAccessToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException {
+        JWSInput input = new JWSInput(tokenResponse.getToken());
+        AccessToken idToken = null;
+        try {
+            idToken = input.readJsonContent(AccessToken.class);
+        } catch (IOException e) {
+            throw new VerificationException();
+        }
+        return idToken;
+    }
+
+    protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) {
+        String header = BasicAuthHelper.createHeader("test-app", "password");
+        Form form = new Form();
+        form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
+                .param("username", "test-user@localhost")
+                .param("password", "password");
+        return grantTarget.request()
+                .header(HttpHeaders.AUTHORIZATION, header)
+                .post(Entity.form(form));
+    }
+
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
index ce9a574..6b739ba 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
@@ -1,131 +1,131 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.oidc;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.UserInfo;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.util.BasicAuthHelper;
-import org.openqa.selenium.WebDriver;
-
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriBuilder;
-import java.net.URI;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * @author pedroigor
- */
-public class UserInfoTest {
-
-    private static RealmModel realm;
-
-    @ClassRule
-    public static KeycloakRule keycloakRule = new KeycloakRule();
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @Test
-    public void testSuccessfulUserInfoRequest() throws Exception {
-        Client client = ClientBuilder.newClient();
-        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
-        WebTarget grantTarget = client.target(grantUri);
-        AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
-        Response response = executeUserInfoRequest(accessTokenResponse.getToken());
-
-        assertEquals(Status.OK.getStatusCode(), response.getStatus());
-
-        UserInfo userInfo = response.readEntity(UserInfo.class);
-
-        response.close();
-
-        assertNotNull(userInfo);
-        assertNotNull(userInfo.getSubject());
-        assertEquals("test-user@localhost", userInfo.getEmail());
-        assertEquals("test-user@localhost", userInfo.getPreferredUsername());
-
-        client.close();
-    }
-
-    @Test
-    public void testUnsuccessfulUserInfoRequest() throws Exception {
-        Response response = executeUserInfoRequest("bad");
-
-        response.close();
-
-        assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
-    }
-
-    private AccessTokenResponse executeGrantAccessTokenRequest(WebTarget grantTarget) {
-        String header = BasicAuthHelper.createHeader("test-app", "password");
-        Form form = new Form();
-        form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
-                .param("username", "test-user@localhost")
-                .param("password", "password");
-
-        Response response = grantTarget.request()
-                .header(HttpHeaders.AUTHORIZATION, header)
-                .post(Entity.form(form));
-
-        assertEquals(200, response.getStatus());
-
-        AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
-
-        response.close();
-
-        return accessTokenResponse;
-    }
-
-    private Response executeUserInfoRequest(String accessToken) {
-        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
-        URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
-        Client client = ClientBuilder.newClient();
-        WebTarget userInfoTarget = client.target(userInfoUri);
-
-        return userInfoTarget.request()
-                .header(HttpHeaders.AUTHORIZATION, "bearer " + accessToken)
-                .get();
-    }
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.oidc;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.models.RealmModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.UserInfo;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.util.BasicAuthHelper;
+import org.openqa.selenium.WebDriver;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author pedroigor
+ */
+public class UserInfoTest {
+
+    private static RealmModel realm;
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule();
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @Test
+    public void testSuccessfulUserInfoRequest() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
+        Response response = executeUserInfoRequest(accessTokenResponse.getToken());
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        UserInfo userInfo = response.readEntity(UserInfo.class);
+
+        response.close();
+
+        assertNotNull(userInfo);
+        assertNotNull(userInfo.getSubject());
+        assertEquals("test-user@localhost", userInfo.getEmail());
+        assertEquals("test-user@localhost", userInfo.getPreferredUsername());
+
+        client.close();
+    }
+
+    @Test
+    public void testUnsuccessfulUserInfoRequest() throws Exception {
+        Response response = executeUserInfoRequest("bad");
+
+        response.close();
+
+        assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
+    }
+
+    private AccessTokenResponse executeGrantAccessTokenRequest(WebTarget grantTarget) {
+        String header = BasicAuthHelper.createHeader("test-app", "password");
+        Form form = new Form();
+        form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
+                .param("username", "test-user@localhost")
+                .param("password", "password");
+
+        Response response = grantTarget.request()
+                .header(HttpHeaders.AUTHORIZATION, header)
+                .post(Entity.form(form));
+
+        assertEquals(200, response.getStatus());
+
+        AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
+
+        response.close();
+
+        return accessTokenResponse;
+    }
+
+    private Response executeUserInfoRequest(String accessToken) {
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
+        URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
+        Client client = ClientBuilder.newClient();
+        WebTarget userInfoTarget = client.target(userInfoUri);
+
+        return userInfoTarget.request()
+                .header(HttpHeaders.AUTHORIZATION, "bearer " + accessToken)
+                .get();
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index 257b7aa..d18b615 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -1,355 +1,355 @@
-package org.keycloak.testsuite.rule;
-
-import io.undertow.servlet.api.DeploymentInfo;
-import io.undertow.servlet.api.LoginConfig;
-import io.undertow.servlet.api.SecurityConstraint;
-import io.undertow.servlet.api.SecurityInfo;
-import io.undertow.servlet.api.ServletInfo;
-import io.undertow.servlet.api.WebResourceCollection;
-import org.jboss.resteasy.spi.ResteasyDeployment;
-import org.junit.rules.ExternalResource;
-import org.junit.rules.TemporaryFolder;
-import org.keycloak.Config;
-import org.keycloak.adapters.KeycloakConfigResolver;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakTransaction;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.Retry;
-import org.keycloak.testsuite.KeycloakServer;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.Time;
-
-import javax.servlet.Servlet;
-import javax.ws.rs.core.Application;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class AbstractKeycloakRule extends ExternalResource {
-
-    protected TemporaryFolder temporaryFolder;
-
-    protected KeycloakServer server;
-
-    protected void before() throws Throwable {
-        temporaryFolder = new TemporaryFolder();
-        temporaryFolder.create();
-        System.setProperty("keycloak.tmp.dir", temporaryFolder.newFolder().getAbsolutePath());
-
-        server = new KeycloakServer();
-
-        configureServer(server);
-
-        server.start();
-
-        removeTestRealms();
-
-        setupKeycloak();
-    }
-
-    protected void configureServer(KeycloakServer server) {
-
-    }
-
-    public UserRepresentation getUser(String realm, String name) {
-        KeycloakSession session = server.getSessionFactory().create();
-        session.getTransaction().begin();
-        try {
-            RealmModel realmByName = session.realms().getRealmByName(realm);
-            UserModel user = session.users().getUserByUsername(name, realmByName);
-            UserRepresentation userRep = user != null ? ModelToRepresentation.toRepresentation(user) : null;
-            session.getTransaction().commit();
-            return userRep;
-        } finally {
-            session.close();
-        }
-    }
-
-    public UserRepresentation getUserById(String realm, String id) {
-        KeycloakSession session = server.getSessionFactory().create();
-        session.getTransaction().begin();
-        try {
-            RealmModel realmByName = session.realms().getRealmByName(realm);
-            UserRepresentation userRep = ModelToRepresentation.toRepresentation(session.users().getUserById(id, realmByName));
-            session.getTransaction().commit();
-            return userRep;
-        } finally {
-            session.close();
-        }
-    }
-
-    protected void setupKeycloak() {
-        KeycloakSession session = server.getSessionFactory().create();
-        session.getTransaction().begin();
-
-        try {
-            RealmManager manager = new RealmManager(session);
-
-            RealmModel adminstrationRealm = manager.getRealm(Config.getAdminRealm());
-
-            configure(session, manager, adminstrationRealm);
-
-            session.getTransaction().commit();
-        } finally {
-            session.close();
-        }
-    }
-
-    public void update(KeycloakRule.KeycloakSetup configurer, String realmId) {
-        KeycloakSession session = server.getSessionFactory().create();
-        session.getTransaction().begin();
-
-        try {
-            RealmManager manager = new RealmManager(session);
-
-            RealmModel adminstrationRealm = manager.getRealm(Config.getAdminRealm());
-            RealmModel appRealm = manager.getRealm(realmId);
-
-            configurer.session = session;
-            configurer.config(manager, adminstrationRealm, appRealm);
-
-            session.getTransaction().commit();
-        } finally {
-            session.close();
-        }
-    }
-
-    protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-
-    }
-
-    public void deployServlet(String name, String contextPath, Class<? extends Servlet> servletClass) {
-        DeploymentInfo deploymentInfo = createDeploymentInfo(name, contextPath, servletClass);
-        server.getServer().deploy(deploymentInfo);
-    }
-
-
-    public DeploymentInfo createDeploymentInfo(String name, String contextPath, Class<? extends Servlet> servletClass) {
-        DeploymentInfo deploymentInfo = new DeploymentInfo();
-        deploymentInfo.setClassLoader(getClass().getClassLoader());
-        deploymentInfo.setDeploymentName(name);
-        deploymentInfo.setContextPath(contextPath);
-
-        ServletInfo servlet = new ServletInfo(servletClass.getSimpleName(), servletClass);
-        servlet.addMapping("/*");
-
-        deploymentInfo.addServlet(servlet);
-        return deploymentInfo;
-    }
-
-
-    public DeploymentBuilder createApplicationDeployment() {
-        return new DeploymentBuilder();
-    }
-
-    public void addErrorPage(DeploymentInfo di) {
-        ServletInfo servlet = new ServletInfo("Error Page", ErrorServlet.class);
-        servlet.addMapping("/error.html");
-        SecurityConstraint constraint = new SecurityConstraint();
-        WebResourceCollection collection = new WebResourceCollection();
-        collection.addUrlPattern("/error.html");
-        constraint.addWebResourceCollection(collection);
-        constraint.setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT);
-        di.addSecurityConstraint(constraint);
-        di.addServlet(servlet);
-    }
-
-    public void deployJaxrsApplication(String name, String contextPath, Class<? extends Application> applicationClass, Map<String,String> initParams) {
-        ResteasyDeployment deployment = new ResteasyDeployment();
-        deployment.setApplicationClass(applicationClass.getName());
-
-        DeploymentInfo di = server.getServer().undertowDeployment(deployment, "");
-        di.setClassLoader(getClass().getClassLoader());
-        di.setContextPath(contextPath);
-        di.setDeploymentName(name);
-
-        for (Map.Entry<String,String> param : initParams.entrySet()) {
-            di.addInitParameter(param.getKey(), param.getValue());
-        }
-
-        server.getServer().deploy(di);
-    }
-
-    @Override
-    protected void after() {
-        removeTestRealms();
-        stopServer();
-        Time.setOffset(0);
-
-        temporaryFolder.delete();
-        System.getProperties().remove("keycloak.tmp.dir");
-    }
-
-    protected void removeTestRealms() {
-        KeycloakSession session = server.getSessionFactory().create();
-        try {
-            session.getTransaction().begin();
-            RealmManager realmManager = new RealmManager(session);
-            for (String realmName : getTestRealms()) {
-                RealmModel realm = realmManager.getRealmByName(realmName);
-                if (realm != null) {
-                    realmManager.removeRealm(realm);
-                }
-            }
-            session.getTransaction().commit();
-        } finally {
-            session.close();
-        }
-    }
-
-    public RealmRepresentation loadJson(String path) throws IOException {
-        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        int c;
-        while ((c = is.read()) != -1) {
-            os.write(c);
-        }
-        byte[] bytes = os.toByteArray();
-        return JsonSerialization.readValue(bytes, RealmRepresentation.class);
-    }
-
-    public KeycloakSession startSession() {
-        KeycloakSession session = server.getSessionFactory().create();
-        session.getTransaction().begin();
-        return session;
-    }
-
-    public void stopSession(KeycloakSession session, boolean commit) {
-        KeycloakTransaction transaction = session.getTransaction();
-        if (commit && !transaction.getRollbackOnly()) {
-            transaction.commit();
-        } else {
-            transaction.rollback();
-        }
-        session.close();
-    }
-
-    public void restartServer() {
-        try {
-            stopServer();
-            server.start();
-        } catch (Throwable t) {
-            throw new RuntimeException(t);
-        }
-    }
-
-    private void stopServer() {
-        server.stop();
-
-        // Add some variable delay (Some windows envs have issues as server is not stopped immediately after server.stop)
-        try {
-            Retry.execute(new Runnable() {
-
-                @Override
-                public void run() {
-                    try {
-                        Socket s = new Socket(server.getConfig().getHost(), server.getConfig().getPort());
-                        s.close();
-                        throw new IllegalStateException("Server still running");
-                    } catch (IOException expected) {
-                    }
-                }
-
-            }, 10, 500);
-        } catch (InterruptedException ie) {
-            Thread.currentThread().interrupt();
-        }
-    }
-
-    protected String[] getTestRealms() {
-        return new String[]{"test", "demo"};
-    }
-
-    public class DeploymentBuilder {
-
-        private String name;
-        private String contextPath;
-        private Class<? extends Servlet> servletClass;
-        private String adapterConfigPath;
-        private String role;
-        private boolean isConstrained = true;
-        private Class<? extends KeycloakConfigResolver> keycloakConfigResolver;
-        private String constraintUrl = "/*";
-        private String errorPage = "/error.html";
-
-        public DeploymentBuilder name(String name) {
-            this.name = name;
-            return this;
-        }
-
-        public DeploymentBuilder contextPath(String contextPath) {
-            this.contextPath = contextPath;
-            return this;
-        }
-
-        public DeploymentBuilder servletClass(Class<? extends Servlet> servletClass) {
-            this.servletClass = servletClass;
-            return this;
-        }
-
-        public DeploymentBuilder adapterConfigPath(String adapterConfigPath) {
-            this.adapterConfigPath = adapterConfigPath;
-            return this;
-        }
-
-        public DeploymentBuilder role(String role) {
-            this.role = role;
-            return this;
-        }
-
-        public DeploymentBuilder isConstrained(boolean isConstrained) {
-            this.isConstrained = isConstrained;
-            return this;
-        }
-
-        public DeploymentBuilder keycloakConfigResolver(Class<? extends KeycloakConfigResolver> keycloakConfigResolver) {
-            this.keycloakConfigResolver = keycloakConfigResolver;
-            return this;
-        }
-
-        public DeploymentBuilder constraintUrl(String constraintUrl) {
-            this.constraintUrl = constraintUrl;
-            return this;
-        }
-
-        public DeploymentBuilder errorPage(String errorPage) {
-            this.errorPage = errorPage;
-            return this;
-        }
-
-        public void deployApplication() {
-            DeploymentInfo di = createDeploymentInfo(name, contextPath, servletClass);
-            if (null == keycloakConfigResolver) {
-                di.addInitParameter("keycloak.config.file", adapterConfigPath);
-            } else {
-                di.addInitParameter("keycloak.config.resolver", keycloakConfigResolver.getCanonicalName());
-            }
-            if (isConstrained) {
-                SecurityConstraint constraint = new SecurityConstraint();
-                WebResourceCollection collection = new WebResourceCollection();
-                collection.addUrlPattern(constraintUrl);
-                constraint.addWebResourceCollection(collection);
-                constraint.addRoleAllowed(role);
-                di.addSecurityConstraint(constraint);
-            }
-            LoginConfig loginConfig = new LoginConfig("KEYCLOAK", "demo", null, errorPage);
-            di.setLoginConfig(loginConfig);
-            addErrorPage(di);
-
-            server.getServer().deploy(di);
-        }
-
-    }
-
-}
+package org.keycloak.testsuite.rule;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.LoginConfig;
+import io.undertow.servlet.api.SecurityConstraint;
+import io.undertow.servlet.api.SecurityInfo;
+import io.undertow.servlet.api.ServletInfo;
+import io.undertow.servlet.api.WebResourceCollection;
+import org.jboss.resteasy.spi.ResteasyDeployment;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.TemporaryFolder;
+import org.keycloak.Config;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.Retry;
+import org.keycloak.testsuite.KeycloakServer;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.Time;
+
+import javax.servlet.Servlet;
+import javax.ws.rs.core.Application;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractKeycloakRule extends ExternalResource {
+
+    protected TemporaryFolder temporaryFolder;
+
+    protected KeycloakServer server;
+
+    protected void before() throws Throwable {
+        temporaryFolder = new TemporaryFolder();
+        temporaryFolder.create();
+        System.setProperty("keycloak.tmp.dir", temporaryFolder.newFolder().getAbsolutePath());
+
+        server = new KeycloakServer();
+
+        configureServer(server);
+
+        server.start();
+
+        removeTestRealms();
+
+        setupKeycloak();
+    }
+
+    protected void configureServer(KeycloakServer server) {
+
+    }
+
+    public UserRepresentation getUser(String realm, String name) {
+        KeycloakSession session = server.getSessionFactory().create();
+        session.getTransaction().begin();
+        try {
+            RealmModel realmByName = session.realms().getRealmByName(realm);
+            UserModel user = session.users().getUserByUsername(name, realmByName);
+            UserRepresentation userRep = user != null ? ModelToRepresentation.toRepresentation(user) : null;
+            session.getTransaction().commit();
+            return userRep;
+        } finally {
+            session.close();
+        }
+    }
+
+    public UserRepresentation getUserById(String realm, String id) {
+        KeycloakSession session = server.getSessionFactory().create();
+        session.getTransaction().begin();
+        try {
+            RealmModel realmByName = session.realms().getRealmByName(realm);
+            UserRepresentation userRep = ModelToRepresentation.toRepresentation(session.users().getUserById(id, realmByName));
+            session.getTransaction().commit();
+            return userRep;
+        } finally {
+            session.close();
+        }
+    }
+
+    protected void setupKeycloak() {
+        KeycloakSession session = server.getSessionFactory().create();
+        session.getTransaction().begin();
+
+        try {
+            RealmManager manager = new RealmManager(session);
+
+            RealmModel adminstrationRealm = manager.getRealm(Config.getAdminRealm());
+
+            configure(session, manager, adminstrationRealm);
+
+            session.getTransaction().commit();
+        } finally {
+            session.close();
+        }
+    }
+
+    public void update(KeycloakRule.KeycloakSetup configurer, String realmId) {
+        KeycloakSession session = server.getSessionFactory().create();
+        session.getTransaction().begin();
+
+        try {
+            RealmManager manager = new RealmManager(session);
+
+            RealmModel adminstrationRealm = manager.getRealm(Config.getAdminRealm());
+            RealmModel appRealm = manager.getRealm(realmId);
+
+            configurer.session = session;
+            configurer.config(manager, adminstrationRealm, appRealm);
+
+            session.getTransaction().commit();
+        } finally {
+            session.close();
+        }
+    }
+
+    protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+
+    }
+
+    public void deployServlet(String name, String contextPath, Class<? extends Servlet> servletClass) {
+        DeploymentInfo deploymentInfo = createDeploymentInfo(name, contextPath, servletClass);
+        server.getServer().deploy(deploymentInfo);
+    }
+
+
+    public DeploymentInfo createDeploymentInfo(String name, String contextPath, Class<? extends Servlet> servletClass) {
+        DeploymentInfo deploymentInfo = new DeploymentInfo();
+        deploymentInfo.setClassLoader(getClass().getClassLoader());
+        deploymentInfo.setDeploymentName(name);
+        deploymentInfo.setContextPath(contextPath);
+
+        ServletInfo servlet = new ServletInfo(servletClass.getSimpleName(), servletClass);
+        servlet.addMapping("/*");
+
+        deploymentInfo.addServlet(servlet);
+        return deploymentInfo;
+    }
+
+
+    public DeploymentBuilder createApplicationDeployment() {
+        return new DeploymentBuilder();
+    }
+
+    public void addErrorPage(DeploymentInfo di) {
+        ServletInfo servlet = new ServletInfo("Error Page", ErrorServlet.class);
+        servlet.addMapping("/error.html");
+        SecurityConstraint constraint = new SecurityConstraint();
+        WebResourceCollection collection = new WebResourceCollection();
+        collection.addUrlPattern("/error.html");
+        constraint.addWebResourceCollection(collection);
+        constraint.setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT);
+        di.addSecurityConstraint(constraint);
+        di.addServlet(servlet);
+    }
+
+    public void deployJaxrsApplication(String name, String contextPath, Class<? extends Application> applicationClass, Map<String,String> initParams) {
+        ResteasyDeployment deployment = new ResteasyDeployment();
+        deployment.setApplicationClass(applicationClass.getName());
+
+        DeploymentInfo di = server.getServer().undertowDeployment(deployment, "");
+        di.setClassLoader(getClass().getClassLoader());
+        di.setContextPath(contextPath);
+        di.setDeploymentName(name);
+
+        for (Map.Entry<String,String> param : initParams.entrySet()) {
+            di.addInitParameter(param.getKey(), param.getValue());
+        }
+
+        server.getServer().deploy(di);
+    }
+
+    @Override
+    protected void after() {
+        removeTestRealms();
+        stopServer();
+        Time.setOffset(0);
+
+        temporaryFolder.delete();
+        System.getProperties().remove("keycloak.tmp.dir");
+    }
+
+    protected void removeTestRealms() {
+        KeycloakSession session = server.getSessionFactory().create();
+        try {
+            session.getTransaction().begin();
+            RealmManager realmManager = new RealmManager(session);
+            for (String realmName : getTestRealms()) {
+                RealmModel realm = realmManager.getRealmByName(realmName);
+                if (realm != null) {
+                    realmManager.removeRealm(realm);
+                }
+            }
+            session.getTransaction().commit();
+        } finally {
+            session.close();
+        }
+    }
+
+    public RealmRepresentation loadJson(String path) throws IOException {
+        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        int c;
+        while ((c = is.read()) != -1) {
+            os.write(c);
+        }
+        byte[] bytes = os.toByteArray();
+        return JsonSerialization.readValue(bytes, RealmRepresentation.class);
+    }
+
+    public KeycloakSession startSession() {
+        KeycloakSession session = server.getSessionFactory().create();
+        session.getTransaction().begin();
+        return session;
+    }
+
+    public void stopSession(KeycloakSession session, boolean commit) {
+        KeycloakTransaction transaction = session.getTransaction();
+        if (commit && !transaction.getRollbackOnly()) {
+            transaction.commit();
+        } else {
+            transaction.rollback();
+        }
+        session.close();
+    }
+
+    public void restartServer() {
+        try {
+            stopServer();
+            server.start();
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    private void stopServer() {
+        server.stop();
+
+        // Add some variable delay (Some windows envs have issues as server is not stopped immediately after server.stop)
+        try {
+            Retry.execute(new Runnable() {
+
+                @Override
+                public void run() {
+                    try {
+                        Socket s = new Socket(server.getConfig().getHost(), server.getConfig().getPort());
+                        s.close();
+                        throw new IllegalStateException("Server still running");
+                    } catch (IOException expected) {
+                    }
+                }
+
+            }, 10, 500);
+        } catch (InterruptedException ie) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    protected String[] getTestRealms() {
+        return new String[]{"test", "demo"};
+    }
+
+    public class DeploymentBuilder {
+
+        private String name;
+        private String contextPath;
+        private Class<? extends Servlet> servletClass;
+        private String adapterConfigPath;
+        private String role;
+        private boolean isConstrained = true;
+        private Class<? extends KeycloakConfigResolver> keycloakConfigResolver;
+        private String constraintUrl = "/*";
+        private String errorPage = "/error.html";
+
+        public DeploymentBuilder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        public DeploymentBuilder contextPath(String contextPath) {
+            this.contextPath = contextPath;
+            return this;
+        }
+
+        public DeploymentBuilder servletClass(Class<? extends Servlet> servletClass) {
+            this.servletClass = servletClass;
+            return this;
+        }
+
+        public DeploymentBuilder adapterConfigPath(String adapterConfigPath) {
+            this.adapterConfigPath = adapterConfigPath;
+            return this;
+        }
+
+        public DeploymentBuilder role(String role) {
+            this.role = role;
+            return this;
+        }
+
+        public DeploymentBuilder isConstrained(boolean isConstrained) {
+            this.isConstrained = isConstrained;
+            return this;
+        }
+
+        public DeploymentBuilder keycloakConfigResolver(Class<? extends KeycloakConfigResolver> keycloakConfigResolver) {
+            this.keycloakConfigResolver = keycloakConfigResolver;
+            return this;
+        }
+
+        public DeploymentBuilder constraintUrl(String constraintUrl) {
+            this.constraintUrl = constraintUrl;
+            return this;
+        }
+
+        public DeploymentBuilder errorPage(String errorPage) {
+            this.errorPage = errorPage;
+            return this;
+        }
+
+        public void deployApplication() {
+            DeploymentInfo di = createDeploymentInfo(name, contextPath, servletClass);
+            if (null == keycloakConfigResolver) {
+                di.addInitParameter("keycloak.config.file", adapterConfigPath);
+            } else {
+                di.addInitParameter("keycloak.config.resolver", keycloakConfigResolver.getCanonicalName());
+            }
+            if (isConstrained) {
+                SecurityConstraint constraint = new SecurityConstraint();
+                WebResourceCollection collection = new WebResourceCollection();
+                collection.addUrlPattern(constraintUrl);
+                constraint.addWebResourceCollection(collection);
+                constraint.addRoleAllowed(role);
+                di.addSecurityConstraint(constraint);
+            }
+            LoginConfig loginConfig = new LoginConfig("KEYCLOAK", "demo", null, errorPage);
+            di.setLoginConfig(loginConfig);
+            addErrorPage(di);
+
+            server.getServer().deploy(di);
+        }
+
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java
index 1f8534d..47f7135 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java
@@ -1,28 +1,28 @@
-package org.keycloak.testsuite.rule;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ErrorServlet extends HttpServlet {
-
-    @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-
-
-        resp.setContentType("text/html");
-        PrintWriter pw = resp.getWriter();
-        pw.printf("<html><head><title>%s</title></head><body>", "Error Page");
-        pw.print("<h1>There was an error</h1></body></html>");
-        pw.flush();
-
-
-    }
-}
+package org.keycloak.testsuite.rule;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ErrorServlet extends HttpServlet {
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+
+        resp.setContentType("text/html");
+        PrintWriter pw = resp.getWriter();
+        pw.printf("<html><head><title>%s</title></head><body>", "Error Page");
+        pw.print("<h1>There was an error</h1></body></html>");
+        pw.flush();
+
+
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
index 01e4cd5..d556a83 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
@@ -1,510 +1,510 @@
-package org.keycloak.testsuite.saml;
-
-import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.Config;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
-import org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper;
-import org.keycloak.protocol.saml.mappers.HardcodedRole;
-import org.keycloak.protocol.saml.mappers.RoleListMapper;
-import org.keycloak.protocol.saml.mappers.RoleNameMapper;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.admin.AdminRoot;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.openqa.selenium.WebDriver;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
-import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.ClientRequestContext;
-import javax.ws.rs.client.ClientRequestFilter;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class SamlBindingTest {
-
-    @ClassRule
-    public static SamlKeycloakRule keycloakRule = new SamlKeycloakRule() {
-        @Override
-        public void initWars() {
-             ClassLoader classLoader = SamlBindingTest.class.getClassLoader();
-
-            initializeSamlSecuredWar("/saml/simple-post", "/sales-post",  "post.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-post", "/sales-post-sig",  "post-sig.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
-            //initializeSamlSecuredWar("/saml/simple-get", "/employee",  "employee.war", classLoader);
-            initializeSamlSecuredWar("/saml/signed-front-get", "/employee-sig-front",  "employee-sig-front.war", classLoader);
-            initializeSamlSecuredWar("/saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
-            initializeSamlSecuredWar("/saml/bad-realm-signed-post", "/bad-realm-sales-post-sig",  "bad-realm-post-sig.war", classLoader);
-            initializeSamlSecuredWar("/saml/encrypted-post", "/sales-post-enc",  "post-enc.war", classLoader);
-            uploadSP();
-            server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
-
-
-
-        }
-
-        @Override
-        public String getRealmJson() {
-            return "/saml/testsaml.json";
-        }
-    };
-
-    public static class SamlSPFacade extends HttpServlet {
-        public static String samlResponse;
-        public static String RELAY_STATE = "http://test.com/foo/bar";
-        public static String sentRelayState;
-
-        @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-            handler(req, resp);
-        }
-
-        @Override
-        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-            handler(req, resp);
-        }
-
-        private void handler(HttpServletRequest req, HttpServletResponse resp) {
-            System.out.println("********* HERE ******");
-            if (req.getParameterMap().isEmpty()) {
-                System.out.println("redirecting");
-                resp.setStatus(302);
-                // Redirect
-                // UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVLRTsIwFP2Vpe%2BjG4wxG0YyWYxL0BBAH3wx3XYnTbp29nYof%2B8YEvEBNOlD03vOveec2ynyWjYsae1WreC9BbTOZy0Vsr4Qk9YopjkKZIrXgMwWbJ08LNhw4LHGaKsLLcmRch3MEcFYoRVxktN1rhW2NZg1mJ0o4Gm1iMnW2oZRKnXB5VajZZEX%2BRTqRuo9ACVO2mkUih%2F4l9C8s0MNcFkjLaHW9KSUHlwR506bAnrPMam4RCBOlsYkS1%2BD3MvLcDJxAx9KN4jCkXszrG5cP%2BCVH4y8IM8PYFx2dsQOfuiILWQKLVc2JkPPH7te6HrRxh%2BzUdidwSSIXoiz%2FBZyK1Qp1Nv1yPIjCNn9ZrN0V1AKA4UlzjMY7N13IDKbHjyxXoA5291%2FtzH7I%2FApPet%2FHNawx65hli61FMXeSaTUH%2FMubtvlYU0LfcA1t5cl%2BAO%2FfxGlW%2FVQ1ipsoBCVgJLQ2XHo7385%2BwI%3D");
-                UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVJbT8IwFP4rS99HuwluNIwEIUYSLwugD76Y2h2kSdfOng7l31uGRn0ATfrQ9HznfJfTEYpaN3zS%2Bo1ZwGsL6KP3WhvkXaEgrTPcClTIjagBuZd8Obm55mmP8cZZb6XV5NByGiwQwXllDYkmX9epNdjW4JbgtkrC%2FeK6IBvvG06ptlLojUXPc5YnFOpG2x0AJdEsaFRG7PuPoUWwQx0IXSOtoLb0SynduyLRpXUSOs8FWQuNQKL5rCDz2VO%2FymEgIY2zlJ3H%2FSx9jkU%2BzOK0ys8yNmSSsUEAYxnsqC18tyO2MDfohfEFSVkyiNlZzM5XacrDSbJePug%2Fkqj8FHKhTKXMy%2BnIng8g5FerVRmXd8sViR7AYec8AMh4tPfDO3L3Y2%2F%2F3cT4j7BH9Mf8A1nDb8PA%2Bay0WsldNNHavk1D1D5k4V0LXbi18MclJL2ke1FVvO6gvDXYgFRrBRWh4wPp7z85%2FgA%3D");
-                builder.queryParam("RelayState", RELAY_STATE);
-                resp.setHeader("Location", builder.build().toString());
-                return;
-            }
-            System.out.println("received response");
-            samlResponse = req.getParameter("SAMLResponse");
-            sentRelayState = req.getParameter("RelayState");
-        }
-    }
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-    @WebResource
-    protected WebDriver driver;
-    @WebResource
-    protected LoginPage loginPage;
-
-    protected void checkLoggedOut(String mainUrl) {
-        String pageSource = driver.getPageSource();
-        System.out.println("*** logout pagesouce ***");
-        System.out.println(pageSource);
-        System.out.println("driver url: " + driver.getCurrentUrl());
-        Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
-        driver.navigate().to(mainUrl);
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-    }
-
-    //@Test
-    public void ideTesting() throws Exception {
-        Thread.sleep(100000000);
-    }
-
-    @Test
-    public void testPostSimpleLoginLogout() {
-        driver.navigate().to("http://localhost:8081/sales-post/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
-        System.out.println(driver.getPageSource());
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post/");
-    }
-    @Test
-    public void testPostSimpleLoginLogoutIdpInitiated() {
-        driver.navigate().to("http://localhost:8081/auth/realms/demo/protocol/saml/clients/sales-post");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
-        System.out.println(driver.getPageSource());
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post/");
-    }
-
-    @Test
-    public void testPostSignedLoginLogout() {
-        driver.navigate().to("http://localhost:8081/sales-post-sig/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/sales-post-sig?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post-sig/");
-
-    }
-    @Test
-    public void testPostSignedLoginLogoutTransientNameID() {
-        driver.navigate().to("http://localhost:8081/sales-post-sig-transient/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-transient/");
-        System.out.println(driver.getPageSource());
-        Assert.assertFalse(driver.getPageSource().contains("bburke"));
-        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
-        driver.navigate().to("http://localhost:8081/sales-post-sig-transient?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post-sig-transient/");
-
-    }
-    @Test
-    public void testPostSignedLoginLogoutPersistentNameID() {
-        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-persistent/");
-        System.out.println(driver.getPageSource());
-        Assert.assertFalse(driver.getPageSource().contains("bburke"));
-        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
-        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post-sig-persistent/");
-
-    }
-    @Test
-    public void testPostSignedLoginLogoutEmailNameID() {
-        driver.navigate().to("http://localhost:8081/sales-post-sig-email/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-email/");
-        System.out.println(driver.getPageSource());
-        Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
-        driver.navigate().to("http://localhost:8081/sales-post-sig-email?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post-sig-email/");
-
-    }
-
-    @Test
-    public void testRelayStateEncoding() throws Exception {
-        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
-        // at the relay state
-        SamlSPFacade.samlResponse = null;
-        driver.navigate().to("http://localhost:8081/employee/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-        System.out.println(driver.getCurrentUrl());
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
-        Assert.assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
-        Assert.assertNotNull(SamlSPFacade.samlResponse);
-
-    }
-
-
-    @Test
-    public void testAttributes() throws Exception {
-        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
-        // at the assertions sent.  This is because Picketlink, AFAICT, does not give you any way to get access to
-        // the assertion.
-
-        {
-            SamlSPFacade.samlResponse = null;
-            driver.navigate().to("http://localhost:8081/employee/");
-            Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-            System.out.println(driver.getCurrentUrl());
-            loginPage.login("bburke", "password");
-            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
-            Assert.assertNotNull(SamlSPFacade.samlResponse);
-            SAML2Response saml2Response = new SAML2Response();
-            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
-            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
-            Assert.assertTrue(rt.getAssertions().size() == 1);
-            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
-
-            // test attributes and roles
-
-            boolean email = false;
-            boolean phone = false;
-            boolean userRole = false;
-            boolean managerRole = false;
-            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                    AttributeType attr = choice.getAttribute();
-                    if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attr.getFriendlyName())) {
-                        Assert.assertEquals(X500SAMLProfileConstants.EMAIL.get(), attr.getName());
-                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(), attr.getNameFormat());
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "bburke@redhat.com");
-                        email = true;
-                    } else if (attr.getName().equals("phone")) {
-                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC.get(), attr.getNameFormat());
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "617");
-                        phone = true;
-                    } else if (attr.getName().equals("Role")) {
-                        if (attr.getAttributeValue().get(0).equals("manager")) managerRole = true;
-                        if (attr.getAttributeValue().get(0).equals("user")) userRole = true;
-                    }
-                }
-
-            }
-
-            Assert.assertTrue(email);
-            Assert.assertTrue(phone);
-            Assert.assertTrue(userRole);
-            Assert.assertTrue(managerRole);
-        }
-
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee/");
-                for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
-                    if (mapper.getName().equals("role-list")) {
-                        app.removeProtocolMapper(mapper);
-                        mapper.setId(null);
-                        mapper.getConfig().put(RoleListMapper.SINGLE_ROLE_ATTRIBUTE, "true");
-                        mapper.getConfig().put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "memberOf");
-                        app.addProtocolMapper(mapper);
-                    }
-                }
-                app.addProtocolMapper(HardcodedAttributeMapper.create("hardcoded-attribute", "hardcoded-attribute", "Basic", null, "hard", false, null));
-                app.addProtocolMapper(HardcodedRole.create("hardcoded-role", "hardcoded-role"));
-                app.addProtocolMapper(RoleNameMapper.create("renamed-role", "manager", "el-jefe"));
-                app.addProtocolMapper(RoleNameMapper.create("renamed-employee-role", "http://localhost:8081/employee/.employee", "pee-on"));
-            }
-        }, "demo");
-
-        System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
-
-        {
-            SamlSPFacade.samlResponse = null;
-            driver.navigate().to("http://localhost:8081/employee/");
-            System.out.println(driver.getCurrentUrl());
-            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
-            Assert.assertNotNull(SamlSPFacade.samlResponse);
-            SAML2Response saml2Response = new SAML2Response();
-            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
-            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
-            Assert.assertTrue(rt.getAssertions().size() == 1);
-            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
-
-            // test attributes and roles
-
-            boolean userRole = false;
-            boolean managerRole = false;
-            boolean single = false;
-            boolean hardcodedRole = false;
-            boolean hardcodedAttribute = false;
-            boolean peeOn = false;
-            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                    AttributeType attr = choice.getAttribute();
-                    if (attr.getName().equals("memberOf")) {
-                        if (single) Assert.fail("too many role attributes");
-                        single = true;
-                        for (Object value : attr.getAttributeValue()) {
-                            if (value.equals("el-jefe")) managerRole = true;
-                            if (value.equals("user")) userRole = true;
-                            if (value.equals("hardcoded-role")) hardcodedRole = true;
-                            if (value.equals("pee-on")) peeOn = true;
-                        }
-                    } else if (attr.getName().equals("hardcoded-attribute")) {
-                        hardcodedAttribute = true;
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "hard");
-                    }
-                }
-
-            }
-
-            Assert.assertTrue(single);
-            Assert.assertTrue(hardcodedAttribute);
-            Assert.assertTrue(hardcodedRole);
-            Assert.assertTrue(peeOn);
-            Assert.assertTrue(userRole);
-            Assert.assertTrue(managerRole);
-        }
-    }
-
-    @Test
-    public void testRedirectSignedLoginLogout() {
-        driver.navigate().to("http://localhost:8081/employee-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
-        checkLoggedOut("http://localhost:8081/employee-sig/");
-
-    }
-
-    @Test
-    public void testRedirectSignedLoginLogoutFrontNoSSO() {
-        driver.navigate().to("http://localhost:8081/employee-sig-front/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/employee-sig-front?GLO=true");
-        checkLoggedOut("http://localhost:8081/employee-sig-front/");
-
-    }
-
-    @Test
-    public void testRedirectSignedLoginLogoutFront() {
-        // visit 1st app an logg in
-        System.out.println("visit 1st app ");
-        driver.navigate().to("http://localhost:8081/employee-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-        System.out.println("login to form");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-
-        // visit 2nd app
-        System.out.println("visit 2nd app ");
-        driver.navigate().to("http://localhost:8081/employee-sig-front/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-
-        // visit 3rd app
-        System.out.println("visit 3rd app ");
-        driver.navigate().to("http://localhost:8081/sales-post-sig/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-
-        // logout of first app
-        System.out.println("GLO");
-        driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
-        checkLoggedOut("http://localhost:8081/employee-sig/");
-        driver.navigate().to("http://localhost:8081/employee-sig-front/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-        driver.navigate().to("http://localhost:8081/sales-post-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-
-    }
-
-    @Test
-    public void testPostEncryptedLoginLogout() {
-        driver.navigate().to("http://localhost:8081/sales-post-enc/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-enc/");
-        Assert.assertTrue(driver.getPageSource().contains("bburke"));
-        driver.navigate().to("http://localhost:8081/sales-post-enc?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-post-enc/");
-
-    }
-    @Test
-    public void testPostBadClientSignature() {
-        driver.navigate().to("http://localhost:8081/bad-client-sales-post-sig/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        Assert.assertEquals(driver.getTitle(), "We're sorry...");
-
-    }
-
-    @Test
-    public void testPostBadRealmSignature() {
-        driver.navigate().to("http://localhost:8081/bad-realm-sales-post-sig/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/bad-realm-sales-post-sig/");
-        Assert.assertTrue(driver.getPageSource().contains("null"));
-    }
-
-    private static String createToken() {
-        KeycloakSession session = keycloakRule.startSession();
-        try {
-            RealmManager manager = new RealmManager(session);
-
-            RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
-            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
-            TokenManager tm = new TokenManager();
-            UserModel admin = session.users().getUserByUsername("admin", adminRealm);
-            ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
-            clientSession.setNote(OIDCLoginProtocol.ISSUER, "http://localhost:8081/auth/realms/master");
-            UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null);
-            AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession);
-            return tm.encodeToken(adminRealm, token);
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-    }
-
-
-    @Test
-    public void testMetadataPostSignedLoginLogout() throws Exception {
-
-        driver.navigate().to("http://localhost:8081/sales-metadata/");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
-        loginPage.login("bburke", "password");
-        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-metadata/");
-        String pageSource = driver.getPageSource();
-        Assert.assertTrue(pageSource.contains("bburke"));
-        driver.navigate().to("http://localhost:8081/sales-metadata?GLO=true");
-        checkLoggedOut("http://localhost:8081/sales-metadata/");
-
-    }
-
-    public static void uploadSP() {
-        String token = createToken();
-        final String authHeader = "Bearer " + token;
-        ClientRequestFilter authFilter = new ClientRequestFilter() {
-            @Override
-            public void filter(ClientRequestContext requestContext) throws IOException {
-                requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
-            }
-        };
-        Client client = ClientBuilder.newBuilder().register(authFilter).build();
-        UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
-        WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
-
-
-        MultipartFormDataOutput formData = new MultipartFormDataOutput();
-        InputStream is = SamlBindingTest.class.getResourceAsStream("/saml/sp-metadata.xml");
-        Assert.assertNotNull(is);
-        formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
-
-        WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
-        System.out.println(upload.getUri());
-        Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
-        Assert.assertEquals(204, response.getStatus());
-        response.close();
-        client.close();
-    }
-
-
-}
+package org.keycloak.testsuite.saml;
+
+import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.Config;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
+import org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper;
+import org.keycloak.protocol.saml.mappers.HardcodedRole;
+import org.keycloak.protocol.saml.mappers.RoleListMapper;
+import org.keycloak.protocol.saml.mappers.RoleNameMapper;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.resources.admin.AdminRoot;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SamlBindingTest {
+
+    @ClassRule
+    public static SamlKeycloakRule keycloakRule = new SamlKeycloakRule() {
+        @Override
+        public void initWars() {
+             ClassLoader classLoader = SamlBindingTest.class.getClassLoader();
+
+            initializeSamlSecuredWar("/saml/simple-post", "/sales-post",  "post.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post", "/sales-post-sig",  "post-sig.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
+            //initializeSamlSecuredWar("/saml/simple-get", "/employee",  "employee.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-front-get", "/employee-sig-front",  "employee-sig-front.war", classLoader);
+            initializeSamlSecuredWar("/saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
+            initializeSamlSecuredWar("/saml/bad-realm-signed-post", "/bad-realm-sales-post-sig",  "bad-realm-post-sig.war", classLoader);
+            initializeSamlSecuredWar("/saml/encrypted-post", "/sales-post-enc",  "post-enc.war", classLoader);
+            uploadSP();
+            server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
+
+
+
+        }
+
+        @Override
+        public String getRealmJson() {
+            return "/saml/testsaml.json";
+        }
+    };
+
+    public static class SamlSPFacade extends HttpServlet {
+        public static String samlResponse;
+        public static String RELAY_STATE = "http://test.com/foo/bar";
+        public static String sentRelayState;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            handler(req, resp);
+        }
+
+        @Override
+        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            handler(req, resp);
+        }
+
+        private void handler(HttpServletRequest req, HttpServletResponse resp) {
+            System.out.println("********* HERE ******");
+            if (req.getParameterMap().isEmpty()) {
+                System.out.println("redirecting");
+                resp.setStatus(302);
+                // Redirect
+                // UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVLRTsIwFP2Vpe%2BjG4wxG0YyWYxL0BBAH3wx3XYnTbp29nYof%2B8YEvEBNOlD03vOveec2ynyWjYsae1WreC9BbTOZy0Vsr4Qk9YopjkKZIrXgMwWbJ08LNhw4LHGaKsLLcmRch3MEcFYoRVxktN1rhW2NZg1mJ0o4Gm1iMnW2oZRKnXB5VajZZEX%2BRTqRuo9ACVO2mkUih%2F4l9C8s0MNcFkjLaHW9KSUHlwR506bAnrPMam4RCBOlsYkS1%2BD3MvLcDJxAx9KN4jCkXszrG5cP%2BCVH4y8IM8PYFx2dsQOfuiILWQKLVc2JkPPH7te6HrRxh%2BzUdidwSSIXoiz%2FBZyK1Qp1Nv1yPIjCNn9ZrN0V1AKA4UlzjMY7N13IDKbHjyxXoA5291%2FtzH7I%2FApPet%2FHNawx65hli61FMXeSaTUH%2FMubtvlYU0LfcA1t5cl%2BAO%2FfxGlW%2FVQ1ipsoBCVgJLQ2XHo7385%2BwI%3D");
+                UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVJbT8IwFP4rS99HuwluNIwEIUYSLwugD76Y2h2kSdfOng7l31uGRn0ATfrQ9HznfJfTEYpaN3zS%2Bo1ZwGsL6KP3WhvkXaEgrTPcClTIjagBuZd8Obm55mmP8cZZb6XV5NByGiwQwXllDYkmX9epNdjW4JbgtkrC%2FeK6IBvvG06ptlLojUXPc5YnFOpG2x0AJdEsaFRG7PuPoUWwQx0IXSOtoLb0SynduyLRpXUSOs8FWQuNQKL5rCDz2VO%2FymEgIY2zlJ3H%2FSx9jkU%2BzOK0ys8yNmSSsUEAYxnsqC18tyO2MDfohfEFSVkyiNlZzM5XacrDSbJePug%2Fkqj8FHKhTKXMy%2BnIng8g5FerVRmXd8sViR7AYec8AMh4tPfDO3L3Y2%2F%2F3cT4j7BH9Mf8A1nDb8PA%2Bay0WsldNNHavk1D1D5k4V0LXbi18MclJL2ke1FVvO6gvDXYgFRrBRWh4wPp7z85%2FgA%3D");
+                builder.queryParam("RelayState", RELAY_STATE);
+                resp.setHeader("Location", builder.build().toString());
+                return;
+            }
+            System.out.println("received response");
+            samlResponse = req.getParameter("SAMLResponse");
+            sentRelayState = req.getParameter("RelayState");
+        }
+    }
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+    @WebResource
+    protected WebDriver driver;
+    @WebResource
+    protected LoginPage loginPage;
+
+    protected void checkLoggedOut(String mainUrl) {
+        String pageSource = driver.getPageSource();
+        System.out.println("*** logout pagesouce ***");
+        System.out.println(pageSource);
+        System.out.println("driver url: " + driver.getCurrentUrl());
+        Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
+        driver.navigate().to(mainUrl);
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+    }
+
+    //@Test
+    public void ideTesting() throws Exception {
+        Thread.sleep(100000000);
+    }
+
+    @Test
+    public void testPostSimpleLoginLogout() {
+        driver.navigate().to("http://localhost:8081/sales-post/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
+        System.out.println(driver.getPageSource());
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post/");
+    }
+    @Test
+    public void testPostSimpleLoginLogoutIdpInitiated() {
+        driver.navigate().to("http://localhost:8081/auth/realms/demo/protocol/saml/clients/sales-post");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
+        System.out.println(driver.getPageSource());
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post/");
+    }
+
+    @Test
+    public void testPostSignedLoginLogout() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post-sig/");
+
+    }
+    @Test
+    public void testPostSignedLoginLogoutTransientNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-transient/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-transient/");
+        System.out.println(driver.getPageSource());
+        Assert.assertFalse(driver.getPageSource().contains("bburke"));
+        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-transient?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post-sig-transient/");
+
+    }
+    @Test
+    public void testPostSignedLoginLogoutPersistentNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-persistent/");
+        System.out.println(driver.getPageSource());
+        Assert.assertFalse(driver.getPageSource().contains("bburke"));
+        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post-sig-persistent/");
+
+    }
+    @Test
+    public void testPostSignedLoginLogoutEmailNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-email/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-email/");
+        System.out.println(driver.getPageSource());
+        Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-email?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post-sig-email/");
+
+    }
+
+    @Test
+    public void testRelayStateEncoding() throws Exception {
+        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
+        // at the relay state
+        SamlSPFacade.samlResponse = null;
+        driver.navigate().to("http://localhost:8081/employee/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        System.out.println(driver.getCurrentUrl());
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
+        Assert.assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
+        Assert.assertNotNull(SamlSPFacade.samlResponse);
+
+    }
+
+
+    @Test
+    public void testAttributes() throws Exception {
+        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
+        // at the assertions sent.  This is because Picketlink, AFAICT, does not give you any way to get access to
+        // the assertion.
+
+        {
+            SamlSPFacade.samlResponse = null;
+            driver.navigate().to("http://localhost:8081/employee/");
+            Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+            System.out.println(driver.getCurrentUrl());
+            loginPage.login("bburke", "password");
+            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
+            Assert.assertNotNull(SamlSPFacade.samlResponse);
+            SAML2Response saml2Response = new SAML2Response();
+            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
+            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
+            Assert.assertTrue(rt.getAssertions().size() == 1);
+            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
+
+            // test attributes and roles
+
+            boolean email = false;
+            boolean phone = false;
+            boolean userRole = false;
+            boolean managerRole = false;
+            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+                    AttributeType attr = choice.getAttribute();
+                    if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attr.getFriendlyName())) {
+                        Assert.assertEquals(X500SAMLProfileConstants.EMAIL.get(), attr.getName());
+                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(), attr.getNameFormat());
+                        Assert.assertEquals(attr.getAttributeValue().get(0), "bburke@redhat.com");
+                        email = true;
+                    } else if (attr.getName().equals("phone")) {
+                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC.get(), attr.getNameFormat());
+                        Assert.assertEquals(attr.getAttributeValue().get(0), "617");
+                        phone = true;
+                    } else if (attr.getName().equals("Role")) {
+                        if (attr.getAttributeValue().get(0).equals("manager")) managerRole = true;
+                        if (attr.getAttributeValue().get(0).equals("user")) userRole = true;
+                    }
+                }
+
+            }
+
+            Assert.assertTrue(email);
+            Assert.assertTrue(phone);
+            Assert.assertTrue(userRole);
+            Assert.assertTrue(managerRole);
+        }
+
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee/");
+                for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
+                    if (mapper.getName().equals("role-list")) {
+                        app.removeProtocolMapper(mapper);
+                        mapper.setId(null);
+                        mapper.getConfig().put(RoleListMapper.SINGLE_ROLE_ATTRIBUTE, "true");
+                        mapper.getConfig().put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "memberOf");
+                        app.addProtocolMapper(mapper);
+                    }
+                }
+                app.addProtocolMapper(HardcodedAttributeMapper.create("hardcoded-attribute", "hardcoded-attribute", "Basic", null, "hard", false, null));
+                app.addProtocolMapper(HardcodedRole.create("hardcoded-role", "hardcoded-role"));
+                app.addProtocolMapper(RoleNameMapper.create("renamed-role", "manager", "el-jefe"));
+                app.addProtocolMapper(RoleNameMapper.create("renamed-employee-role", "http://localhost:8081/employee/.employee", "pee-on"));
+            }
+        }, "demo");
+
+        System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
+
+        {
+            SamlSPFacade.samlResponse = null;
+            driver.navigate().to("http://localhost:8081/employee/");
+            System.out.println(driver.getCurrentUrl());
+            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
+            Assert.assertNotNull(SamlSPFacade.samlResponse);
+            SAML2Response saml2Response = new SAML2Response();
+            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
+            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
+            Assert.assertTrue(rt.getAssertions().size() == 1);
+            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
+
+            // test attributes and roles
+
+            boolean userRole = false;
+            boolean managerRole = false;
+            boolean single = false;
+            boolean hardcodedRole = false;
+            boolean hardcodedAttribute = false;
+            boolean peeOn = false;
+            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+                    AttributeType attr = choice.getAttribute();
+                    if (attr.getName().equals("memberOf")) {
+                        if (single) Assert.fail("too many role attributes");
+                        single = true;
+                        for (Object value : attr.getAttributeValue()) {
+                            if (value.equals("el-jefe")) managerRole = true;
+                            if (value.equals("user")) userRole = true;
+                            if (value.equals("hardcoded-role")) hardcodedRole = true;
+                            if (value.equals("pee-on")) peeOn = true;
+                        }
+                    } else if (attr.getName().equals("hardcoded-attribute")) {
+                        hardcodedAttribute = true;
+                        Assert.assertEquals(attr.getAttributeValue().get(0), "hard");
+                    }
+                }
+
+            }
+
+            Assert.assertTrue(single);
+            Assert.assertTrue(hardcodedAttribute);
+            Assert.assertTrue(hardcodedRole);
+            Assert.assertTrue(peeOn);
+            Assert.assertTrue(userRole);
+            Assert.assertTrue(managerRole);
+        }
+    }
+
+    @Test
+    public void testRedirectSignedLoginLogout() {
+        driver.navigate().to("http://localhost:8081/employee-sig/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
+        checkLoggedOut("http://localhost:8081/employee-sig/");
+
+    }
+
+    @Test
+    public void testRedirectSignedLoginLogoutFrontNoSSO() {
+        driver.navigate().to("http://localhost:8081/employee-sig-front/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/employee-sig-front?GLO=true");
+        checkLoggedOut("http://localhost:8081/employee-sig-front/");
+
+    }
+
+    @Test
+    public void testRedirectSignedLoginLogoutFront() {
+        // visit 1st app an logg in
+        System.out.println("visit 1st app ");
+        driver.navigate().to("http://localhost:8081/employee-sig/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        System.out.println("login to form");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+
+        // visit 2nd app
+        System.out.println("visit 2nd app ");
+        driver.navigate().to("http://localhost:8081/employee-sig-front/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+
+        // visit 3rd app
+        System.out.println("visit 3rd app ");
+        driver.navigate().to("http://localhost:8081/sales-post-sig/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+
+        // logout of first app
+        System.out.println("GLO");
+        driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
+        checkLoggedOut("http://localhost:8081/employee-sig/");
+        driver.navigate().to("http://localhost:8081/employee-sig-front/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig/");
+        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+
+    }
+
+    @Test
+    public void testPostEncryptedLoginLogout() {
+        driver.navigate().to("http://localhost:8081/sales-post-enc/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-enc/");
+        Assert.assertTrue(driver.getPageSource().contains("bburke"));
+        driver.navigate().to("http://localhost:8081/sales-post-enc?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-post-enc/");
+
+    }
+    @Test
+    public void testPostBadClientSignature() {
+        driver.navigate().to("http://localhost:8081/bad-client-sales-post-sig/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        Assert.assertEquals(driver.getTitle(), "We're sorry...");
+
+    }
+
+    @Test
+    public void testPostBadRealmSignature() {
+        driver.navigate().to("http://localhost:8081/bad-realm-sales-post-sig/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/bad-realm-sales-post-sig/");
+        Assert.assertTrue(driver.getPageSource().contains("null"));
+    }
+
+    private static String createToken() {
+        KeycloakSession session = keycloakRule.startSession();
+        try {
+            RealmManager manager = new RealmManager(session);
+
+            RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
+            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
+            TokenManager tm = new TokenManager();
+            UserModel admin = session.users().getUserByUsername("admin", adminRealm);
+            ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
+            clientSession.setNote(OIDCLoginProtocol.ISSUER, "http://localhost:8081/auth/realms/master");
+            UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null);
+            AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession);
+            return tm.encodeToken(adminRealm, token);
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+    }
+
+
+    @Test
+    public void testMetadataPostSignedLoginLogout() throws Exception {
+
+        driver.navigate().to("http://localhost:8081/sales-metadata/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-metadata/");
+        String pageSource = driver.getPageSource();
+        Assert.assertTrue(pageSource.contains("bburke"));
+        driver.navigate().to("http://localhost:8081/sales-metadata?GLO=true");
+        checkLoggedOut("http://localhost:8081/sales-metadata/");
+
+    }
+
+    public static void uploadSP() {
+        String token = createToken();
+        final String authHeader = "Bearer " + token;
+        ClientRequestFilter authFilter = new ClientRequestFilter() {
+            @Override
+            public void filter(ClientRequestContext requestContext) throws IOException {
+                requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
+            }
+        };
+        Client client = ClientBuilder.newBuilder().register(authFilter).build();
+        UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
+        WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
+
+
+        MultipartFormDataOutput formData = new MultipartFormDataOutput();
+        InputStream is = SamlBindingTest.class.getResourceAsStream("/saml/sp-metadata.xml");
+        Assert.assertNotNull(is);
+        formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
+
+        WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
+        System.out.println(upload.getUri());
+        Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
+        Assert.assertEquals(204, response.getStatus());
+        response.close();
+        client.close();
+    }
+
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
index 90f6d44..0e6cb6c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
@@ -1,166 +1,166 @@
-package org.keycloak.testsuite.saml;
-
-import io.undertow.security.idm.Account;
-import io.undertow.security.idm.Credential;
-import io.undertow.security.idm.IdentityManager;
-import io.undertow.server.handlers.resource.Resource;
-import io.undertow.server.handlers.resource.ResourceChangeListener;
-import io.undertow.server.handlers.resource.ResourceManager;
-import io.undertow.server.handlers.resource.URLResource;
-import io.undertow.servlet.api.DeploymentInfo;
-import io.undertow.servlet.api.LoginConfig;
-import io.undertow.servlet.api.SecurityConstraint;
-import io.undertow.servlet.api.ServletInfo;
-import io.undertow.servlet.api.WebResourceCollection;
-import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.URL;
-import java.security.Principal;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
-
-    public static class SendUsernameServlet extends HttpServlet {
-        @Override
-        protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
-            resp.setContentType("text/plain");
-            OutputStream stream = resp.getOutputStream();
-            Principal principal = req.getUserPrincipal();
-            stream.write("request-path: ".getBytes());
-            stream.write(req.getPathInfo().getBytes());
-            stream.write("\n".getBytes());
-            stream.write("principal=".getBytes());
-            if (principal == null) {
-                stream.write("null".getBytes());
-                return;
-            }
-            String name = principal.getName();
-            stream.write(name.getBytes());
-        }
-        @Override
-        protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
-            resp.setContentType("text/plain");
-            OutputStream stream = resp.getOutputStream();
-            Principal principal = req.getUserPrincipal();
-            stream.write("request-path: ".getBytes());
-            stream.write(req.getPathInfo().getBytes());
-            stream.write("\n".getBytes());
-            stream.write("principal=".getBytes());
-            if (principal == null) {
-                stream.write("null".getBytes());
-                return;
-            }
-            String name = principal.getName();
-            stream.write(name.getBytes());
-        }
-    }
-
-    public static class TestResourceManager implements ResourceManager {
-
-        private final String basePath;
-
-        public TestResourceManager(String basePath){
-            this.basePath = basePath;
-        }
-
-        @Override
-        public Resource getResource(String path) throws IOException {
-            String temp = path;
-            String fullPath = basePath + temp;
-            URL url = getClass().getResource(fullPath);
-            if (url == null) {
-                System.out.println("url is null: " + fullPath);
-            }
-            return new URLResource(url, url.openConnection(), path);
-        }
-
-        @Override
-        public boolean isResourceChangeListenerSupported() {
-            throw new RuntimeException();
-        }
-
-        @Override
-        public void registerResourceChangeListener(ResourceChangeListener listener) {
-            throw new RuntimeException();
-        }
-
-        @Override
-        public void removeResourceChangeListener(ResourceChangeListener listener) {
-            throw new RuntimeException();
-        }
-
-        @Override
-        public void close() throws IOException {
-            throw new RuntimeException();
-        }
-    }
-
-    public static class TestIdentityManager implements IdentityManager {
-        @Override
-        public Account verify(Account account) {
-            return account;
-        }
-
-        @Override
-        public Account verify(String userName, Credential credential) {
-            throw new RuntimeException("WTF");
-        }
-
-        @Override
-        public Account verify(Credential credential) {
-            throw new RuntimeException();
-        }
-    }
-
-    @Override
-    protected void setupKeycloak() {
-        String realmJson = getRealmJson();
-        server.importRealm(getClass().getResourceAsStream(realmJson));
-        initWars();
-    }
-
-    public abstract void initWars();
-
-    public void initializeSamlSecuredWar(String warResourcePath, String contextPath, String warDeploymentName, ClassLoader classLoader) {
-
-        ServletInfo regularServletInfo = new ServletInfo("servlet", SendUsernameServlet.class)
-                .addMapping("/*");
-
-        SecurityConstraint constraint = new SecurityConstraint();
-        WebResourceCollection collection = new WebResourceCollection();
-        collection.addUrlPattern("/*");
-        constraint.addWebResourceCollection(collection);
-        constraint.addRoleAllowed("manager");
-        LoginConfig loginConfig = new LoginConfig("FORM", "Test Realm");
-
-        ResourceManager resourceManager = new TestResourceManager(warResourcePath);
-
-        DeploymentInfo deploymentInfo = new DeploymentInfo()
-                .setClassLoader(classLoader)
-                .setIdentityManager(new TestIdentityManager())
-                .setContextPath(contextPath)
-                .setDeploymentName(warDeploymentName)
-                .setLoginConfig(loginConfig)
-                .setResourceManager(resourceManager)
-                .addServlets(regularServletInfo)
-                .addSecurityConstraint(constraint)
-                .addServletExtension(new SPServletExtension());
-        server.getServer().deploy(deploymentInfo);
-    }
-
-    public String getRealmJson() {
-        return "/saml/testsaml.json";
-    }
-
-
-}
+package org.keycloak.testsuite.saml;
+
+import io.undertow.security.idm.Account;
+import io.undertow.security.idm.Credential;
+import io.undertow.security.idm.IdentityManager;
+import io.undertow.server.handlers.resource.Resource;
+import io.undertow.server.handlers.resource.ResourceChangeListener;
+import io.undertow.server.handlers.resource.ResourceManager;
+import io.undertow.server.handlers.resource.URLResource;
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.LoginConfig;
+import io.undertow.servlet.api.SecurityConstraint;
+import io.undertow.servlet.api.ServletInfo;
+import io.undertow.servlet.api.WebResourceCollection;
+import org.keycloak.testsuite.rule.AbstractKeycloakRule;
+import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
+
+    public static class SendUsernameServlet extends HttpServlet {
+        @Override
+        protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+            resp.setContentType("text/plain");
+            OutputStream stream = resp.getOutputStream();
+            Principal principal = req.getUserPrincipal();
+            stream.write("request-path: ".getBytes());
+            stream.write(req.getPathInfo().getBytes());
+            stream.write("\n".getBytes());
+            stream.write("principal=".getBytes());
+            if (principal == null) {
+                stream.write("null".getBytes());
+                return;
+            }
+            String name = principal.getName();
+            stream.write(name.getBytes());
+        }
+        @Override
+        protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+            resp.setContentType("text/plain");
+            OutputStream stream = resp.getOutputStream();
+            Principal principal = req.getUserPrincipal();
+            stream.write("request-path: ".getBytes());
+            stream.write(req.getPathInfo().getBytes());
+            stream.write("\n".getBytes());
+            stream.write("principal=".getBytes());
+            if (principal == null) {
+                stream.write("null".getBytes());
+                return;
+            }
+            String name = principal.getName();
+            stream.write(name.getBytes());
+        }
+    }
+
+    public static class TestResourceManager implements ResourceManager {
+
+        private final String basePath;
+
+        public TestResourceManager(String basePath){
+            this.basePath = basePath;
+        }
+
+        @Override
+        public Resource getResource(String path) throws IOException {
+            String temp = path;
+            String fullPath = basePath + temp;
+            URL url = getClass().getResource(fullPath);
+            if (url == null) {
+                System.out.println("url is null: " + fullPath);
+            }
+            return new URLResource(url, url.openConnection(), path);
+        }
+
+        @Override
+        public boolean isResourceChangeListenerSupported() {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public void registerResourceChangeListener(ResourceChangeListener listener) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public void removeResourceChangeListener(ResourceChangeListener listener) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public void close() throws IOException {
+            throw new RuntimeException();
+        }
+    }
+
+    public static class TestIdentityManager implements IdentityManager {
+        @Override
+        public Account verify(Account account) {
+            return account;
+        }
+
+        @Override
+        public Account verify(String userName, Credential credential) {
+            throw new RuntimeException("WTF");
+        }
+
+        @Override
+        public Account verify(Credential credential) {
+            throw new RuntimeException();
+        }
+    }
+
+    @Override
+    protected void setupKeycloak() {
+        String realmJson = getRealmJson();
+        server.importRealm(getClass().getResourceAsStream(realmJson));
+        initWars();
+    }
+
+    public abstract void initWars();
+
+    public void initializeSamlSecuredWar(String warResourcePath, String contextPath, String warDeploymentName, ClassLoader classLoader) {
+
+        ServletInfo regularServletInfo = new ServletInfo("servlet", SendUsernameServlet.class)
+                .addMapping("/*");
+
+        SecurityConstraint constraint = new SecurityConstraint();
+        WebResourceCollection collection = new WebResourceCollection();
+        collection.addUrlPattern("/*");
+        constraint.addWebResourceCollection(collection);
+        constraint.addRoleAllowed("manager");
+        LoginConfig loginConfig = new LoginConfig("FORM", "Test Realm");
+
+        ResourceManager resourceManager = new TestResourceManager(warResourcePath);
+
+        DeploymentInfo deploymentInfo = new DeploymentInfo()
+                .setClassLoader(classLoader)
+                .setIdentityManager(new TestIdentityManager())
+                .setContextPath(contextPath)
+                .setDeploymentName(warDeploymentName)
+                .setLoginConfig(loginConfig)
+                .setResourceManager(resourceManager)
+                .addServlets(regularServletInfo)
+                .addSecurityConstraint(constraint)
+                .addServletExtension(new SPServletExtension());
+        server.getServer().deploy(deploymentInfo);
+    }
+
+    public String getRealmJson() {
+        return "/saml/testsaml.json";
+    }
+
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/utils/CredentialHelper.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/utils/CredentialHelper.java
index 6a03f3e..3beda6b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/utils/CredentialHelper.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/utils/CredentialHelper.java
@@ -1,80 +1,80 @@
-package org.keycloak.testsuite.utils;
-
-import org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory;
-import org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory;
-import org.keycloak.authentication.authenticators.UsernamePasswordFormFactory;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.representations.idm.CredentialRepresentation;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CredentialHelper {
-
-    public static void setRequiredCredential(String type, RealmModel realm) {
-        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.REQUIRED;
-        setCredentialRequirement(type, realm, requirement);
-    }
-
-    public static void setAlternativeCredential(String type, RealmModel realm) {
-        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
-        setCredentialRequirement(type, realm, requirement);
-    }
-
-    public static void setCredentialRequirement(String type, RealmModel realm, AuthenticationExecutionModel.Requirement requirement) {
-        if (type.equals(CredentialRepresentation.TOTP)) {
-            String providerId = OTPFormAuthenticatorFactory.PROVIDER_ID;
-            String flowAlias = DefaultAuthenticationFlows.LOGIN_FORMS_FLOW;
-            authenticationRequirement(realm, providerId, flowAlias, requirement);
-        } else if (type.equals(CredentialRepresentation.KERBEROS)) {
-            String providerId = SpnegoAuthenticatorFactory.PROVIDER_ID;
-            String flowAlias = DefaultAuthenticationFlows.BROWSER_FLOW;
-            authenticationRequirement(realm, providerId, flowAlias, requirement);
-        } else if (type.equals(CredentialRepresentation.PASSWORD)) {
-            String providerId = UsernamePasswordFormFactory.PROVIDER_ID;
-            String flowAlias = DefaultAuthenticationFlows.LOGIN_FORMS_FLOW;
-            authenticationRequirement(realm, providerId, flowAlias, requirement);
-        }
-    }
-
-    public static AuthenticationExecutionModel.Requirement getRequirement(RealmModel realm, String authenticatorProviderId, String flowAlias) {
-        AuthenticationFlowModel flow =  findAuthenticatorFlowByAlias(realm, flowAlias);
-        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flow.getId(), authenticatorProviderId);
-        return execution.getRequirement();
-
-    }
-
-    public static void alternativeAuthentication(RealmModel realm, String authenticatorProviderId, String flowAlias) {
-        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
-        authenticationRequirement(realm, authenticatorProviderId, flowAlias, requirement);
-    }
-
-    public static void authenticationRequirement(RealmModel realm, String authenticatorProviderId, String flowAlias, AuthenticationExecutionModel.Requirement requirement) {
-        AuthenticationFlowModel flow =  findAuthenticatorFlowByAlias(realm, flowAlias);
-        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flow.getId(), authenticatorProviderId);
-        execution.setRequirement(requirement);
-        realm.updateAuthenticatorExecution(execution);
-    }
-
-    public static AuthenticationFlowModel findAuthenticatorFlowByAlias(RealmModel realm, String alias) {
-        for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) {
-            if (model.getAlias().equals(alias)) {
-                return model;
-            }
-        }
-        return null;
-    }
-    public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authId) {
-        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
-            if (model.getAuthenticator().equals(authId)) {
-                return model;
-            }
-        }
-        return null;
-
-    }
-}
+package org.keycloak.testsuite.utils;
+
+import org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory;
+import org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory;
+import org.keycloak.authentication.authenticators.UsernamePasswordFormFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.idm.CredentialRepresentation;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CredentialHelper {
+
+    public static void setRequiredCredential(String type, RealmModel realm) {
+        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.REQUIRED;
+        setCredentialRequirement(type, realm, requirement);
+    }
+
+    public static void setAlternativeCredential(String type, RealmModel realm) {
+        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
+        setCredentialRequirement(type, realm, requirement);
+    }
+
+    public static void setCredentialRequirement(String type, RealmModel realm, AuthenticationExecutionModel.Requirement requirement) {
+        if (type.equals(CredentialRepresentation.TOTP)) {
+            String providerId = OTPFormAuthenticatorFactory.PROVIDER_ID;
+            String flowAlias = DefaultAuthenticationFlows.LOGIN_FORMS_FLOW;
+            authenticationRequirement(realm, providerId, flowAlias, requirement);
+        } else if (type.equals(CredentialRepresentation.KERBEROS)) {
+            String providerId = SpnegoAuthenticatorFactory.PROVIDER_ID;
+            String flowAlias = DefaultAuthenticationFlows.BROWSER_FLOW;
+            authenticationRequirement(realm, providerId, flowAlias, requirement);
+        } else if (type.equals(CredentialRepresentation.PASSWORD)) {
+            String providerId = UsernamePasswordFormFactory.PROVIDER_ID;
+            String flowAlias = DefaultAuthenticationFlows.LOGIN_FORMS_FLOW;
+            authenticationRequirement(realm, providerId, flowAlias, requirement);
+        }
+    }
+
+    public static AuthenticationExecutionModel.Requirement getRequirement(RealmModel realm, String authenticatorProviderId, String flowAlias) {
+        AuthenticationFlowModel flow =  findAuthenticatorFlowByAlias(realm, flowAlias);
+        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flow.getId(), authenticatorProviderId);
+        return execution.getRequirement();
+
+    }
+
+    public static void alternativeAuthentication(RealmModel realm, String authenticatorProviderId, String flowAlias) {
+        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
+        authenticationRequirement(realm, authenticatorProviderId, flowAlias, requirement);
+    }
+
+    public static void authenticationRequirement(RealmModel realm, String authenticatorProviderId, String flowAlias, AuthenticationExecutionModel.Requirement requirement) {
+        AuthenticationFlowModel flow =  findAuthenticatorFlowByAlias(realm, flowAlias);
+        AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flow.getId(), authenticatorProviderId);
+        execution.setRequirement(requirement);
+        realm.updateAuthenticatorExecution(execution);
+    }
+
+    public static AuthenticationFlowModel findAuthenticatorFlowByAlias(RealmModel realm, String alias) {
+        for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) {
+            if (model.getAlias().equals(alias)) {
+                return model;
+            }
+        }
+        return null;
+    }
+    public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authId) {
+        for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
+            if (model.getAuthenticator().equals(authId)) {
+                return model;
+            }
+        }
+        return null;
+
+    }
+}
diff --git a/testsuite/integration/src/test/resources/adapter-test/demorealm.json b/testsuite/integration/src/test/resources/adapter-test/demorealm.json
index c0b6003..0e47e0c 100755
--- a/testsuite/integration/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/integration/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/customer-portal",
-            "baseUrl": "http://localhost:8081/customer-portal",
-            "redirectUris": [
-                "http://localhost:8081/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8081/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8081/customer-portal-js",
-            "baseUrl": "http://localhost:8081/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/product-portal",
-            "baseUrl": "http://localhost:8081/product-portal",
-            "redirectUris": [
-                "http://localhost:8081/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/secure-portal",
-            "baseUrl": "http://localhost:8081/secure-portal",
-            "redirectUris": [
-                "http://localhost:8081/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/session-portal",
-            "baseUrl": "http://localhost:8081/session-portal",
-            "redirectUris": [
-                "http://localhost:8081/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/input-portal",
-            "baseUrl": "http://localhost:8081/input-portal",
-            "redirectUris": [
-                "http://localhost:8081/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8081/oauth-client/*",
-                "http://localhost:8081/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/customer-portal",
+            "baseUrl": "http://localhost:8081/customer-portal",
+            "redirectUris": [
+                "http://localhost:8081/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8081/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8081/customer-portal-js",
+            "baseUrl": "http://localhost:8081/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/product-portal",
+            "baseUrl": "http://localhost:8081/product-portal",
+            "redirectUris": [
+                "http://localhost:8081/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/secure-portal",
+            "baseUrl": "http://localhost:8081/secure-portal",
+            "redirectUris": [
+                "http://localhost:8081/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/session-portal",
+            "baseUrl": "http://localhost:8081/session-portal",
+            "redirectUris": [
+                "http://localhost:8081/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/input-portal",
+            "baseUrl": "http://localhost:8081/input-portal",
+            "redirectUris": [
+                "http://localhost:8081/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8081/oauth-client/*",
+                "http://localhost:8081/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json b/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json
index 0c1c38a..76886be 100755
--- a/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json
+++ b/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json
@@ -1,107 +1,107 @@
-{
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "/customer-portal",
-            "baseUrl": "/customer-portal",
-            "redirectUris": [
-                "/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "baseUrl": "/customer-portal-js",
-            "redirectUris": [
-                "/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "/product-portal",
-            "baseUrl": "/product-portal",
-            "redirectUris": [
-                "/product-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "/oauth-client/*",
-                "/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "/customer-portal",
+            "baseUrl": "/customer-portal",
+            "redirectUris": [
+                "/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "/customer-portal-js",
+            "redirectUris": [
+                "/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "/product-portal",
+            "baseUrl": "/product-portal",
+            "redirectUris": [
+                "/product-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "/oauth-client/*",
+                "/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/integration/src/test/resources/adapter-test/tenant1-realm.json b/testsuite/integration/src/test/resources/adapter-test/tenant1-realm.json
index 8f0adda..06a5f41 100644
--- a/testsuite/integration/src/test/resources/adapter-test/tenant1-realm.json
+++ b/testsuite/integration/src/test/resources/adapter-test/tenant1-realm.json
@@ -1,72 +1,72 @@
-{
-    "id": "tenant1",
-    "realm": "tenant1",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        },
-        {
-            "username" : "user-tenant1",
-            "enabled": true,
-            "email" : "user-tenant1@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "user-tenant1" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "multi-tenant",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "multi-tenant",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/multi-tenant",
-            "baseUrl": "http://localhost:8081/multi-tenant",
-            "redirectUris": [
-                "http://localhost:8081/multi-tenant/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "tenant1",
+    "realm": "tenant1",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        },
+        {
+            "username" : "user-tenant1",
+            "enabled": true,
+            "email" : "user-tenant1@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant1" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "multi-tenant",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "multi-tenant",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/multi-tenant",
+            "baseUrl": "http://localhost:8081/multi-tenant",
+            "redirectUris": [
+                "http://localhost:8081/multi-tenant/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/integration/src/test/resources/adapter-test/tenant2-realm.json b/testsuite/integration/src/test/resources/adapter-test/tenant2-realm.json
index a1b0357..4f03b5c 100644
--- a/testsuite/integration/src/test/resources/adapter-test/tenant2-realm.json
+++ b/testsuite/integration/src/test/resources/adapter-test/tenant2-realm.json
@@ -1,72 +1,72 @@
-{
-    "id": "tenant2",
-    "realm": "tenant2",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        },
-        {
-            "username" : "user-tenant2",
-            "enabled": true,
-            "email" : "user-tenant2@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "user-tenant2" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "multi-tenant": [ "user" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "multi-tenant",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "multi-tenant",
-            "enabled": true,
-            "adminUrl": "http://localhost:8081/multi-tenant",
-            "baseUrl": "http://localhost:8081/multi-tenant",
-            "redirectUris": [
-                "http://localhost:8081/multi-tenant/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "tenant2",
+    "realm": "tenant2",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        },
+        {
+            "username" : "user-tenant2",
+            "enabled": true,
+            "email" : "user-tenant2@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant2" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "multi-tenant": [ "user" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "multi-tenant",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "multi-tenant",
+            "enabled": true,
+            "adminUrl": "http://localhost:8081/multi-tenant",
+            "baseUrl": "http://localhost:8081/multi-tenant",
+            "redirectUris": [
+                "http://localhost:8081/multi-tenant/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/integration/src/test/resources/admin-test/testrealm.json b/testsuite/integration/src/test/resources/admin-test/testrealm.json
index e4adb40..bc5b2a7 100755
--- a/testsuite/integration/src/test/resources/admin-test/testrealm.json
+++ b/testsuite/integration/src/test/resources/admin-test/testrealm.json
@@ -1,99 +1,99 @@
-{
-    "realm": "admin-test-1",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "registrationEmailAsUsername": true,
-    "resetPasswordAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "user" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "test-user@localhost",
-            "enabled": true,
-            "email" : "test-user@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["user"],
-            "applicationRoles": {
-                "test-app": [ "customer-user" ],
-                "account": [ "view-profile", "manage-account" ]
-            }
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "test-app",
-            "roles": ["user"]
-        }
-    ],
-    "applications": [
-        {
-            "name": "test-app",
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "Have User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Have Administrator privileges"
-            }
-        ],
-        "application" : {
-            "test-app" : [
-                {
-                    "name": "customer-user",
-                    "description": "Have Customer User privileges"
-                },
-                {
-                    "name": "customer-admin",
-                    "description": "Have Customer Admin privileges"
-                }
-            ]
-        }
-
-    },
-
-    "applicationScopeMappings": {
-        "test-app": [
-            {
-                "client": "third-party",
-                "roles": ["customer-user"]
-            }
-        ]
-    }
-}
+{
+    "realm": "admin-test-1",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "registrationEmailAsUsername": true,
+    "resetPasswordAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "user" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "test-user@localhost",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["user"],
+            "applicationRoles": {
+                "test-app": [ "customer-user" ],
+                "account": [ "view-profile", "manage-account" ]
+            }
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "test-app",
+            "roles": ["user"]
+        }
+    ],
+    "applications": [
+        {
+            "name": "test-app",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "Have User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Have Administrator privileges"
+            }
+        ],
+        "application" : {
+            "test-app" : [
+                {
+                    "name": "customer-user",
+                    "description": "Have Customer User privileges"
+                },
+                {
+                    "name": "customer-admin",
+                    "description": "Have Customer Admin privileges"
+                }
+            ]
+        }
+
+    },
+
+    "applicationScopeMappings": {
+        "test-app": [
+            {
+                "client": "third-party",
+                "roles": ["customer-user"]
+            }
+        ]
+    }
+}
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 d3688a8..767ab44 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
@@ -1,165 +1,165 @@
-{
-    "id": "realm-with-oidc-identity-provider",
-    "realm": "realm-with-oidc-identity-provider",
-    "enabled": true,
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "foo", "bar" ],
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "clients" : [
-      {
-        "clientId": "broker-app",
-        "consentRequired": "false",
-        "enabled": true,
-        "secret": "secret",
-        "redirectUris": [
-          "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-oidc-idp/endpoint/*"
-        ],
-        "protocolMappers": [
-            {
-                "name": "mobile",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-usermodel-attribute-mapper",
-                "consentRequired": false,
-                "config": {
-                    "user.attribute": "mobile",
-                    "claim.name": "mobile",
-                    "Claim JSON Type": "String",
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            },
-            {
-                "name": "username",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-usermodel-property-mapper",
-                "consentRequired": false,
-                "config": {
-                    "user.attribute": "username",
-                    "claim.name": "preferred_username",
-                    "Claim JSON Type": "String",
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            },
-            {
-                "name": "email",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-usermodel-property-mapper",
-                "consentRequired": false,
-                "config": {
-                    "user.attribute": "email",
-                    "claim.name": "email",
-                    "Claim JSON Type": "String",
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            },
-            {
-                "name": "given name",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-usermodel-property-mapper",
-                "consentRequired": false,
-                "config": {
-                    "user.attribute": "firstName",
-                    "claim.name": "given_name",
-                    "Claim JSON Type": "String",
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            },
-            {
-                "name": "family name",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-usermodel-property-mapper",
-                "consentRequired": false,
-                "config": {
-                    "user.attribute": "lastName",
-                    "claim.name": "family_name",
-                    "Claim JSON Type": "String",
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            },
-            {
-                "name": "full name",
-                "protocol": "openid-connect",
-                "protocolMapper": "oidc-full-name-mapper",
-                "consentRequired": false,
-                "config": {
-                    "access.token.claim": "true",
-                    "id.token.claim": "true"
-
-                }
-            }
-
-        ]
-      }
-    ],
-    "scopeMappings": [
-        {
-            "client": "broker-app",
-            "roles": ["manager"]
-        }
-    ],
-    "users": [
-        {
-            "username" : "test-user",
-            "enabled": true,
-            "email" : "test-user@localhost",
-            "firstName" : "Test",
-            "lastName" : "User",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["manager"],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            },
-            "attributes": {
-                "mobile": "617-666-7777"
-            }
-        },
-        {
-            "username" : "test-user-noemail",
-            "enabled": true,
-            "firstName" : "Test",
-            "lastName" : "User",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["manager"],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-          "username" : "pedroigor",
-          "enabled": true,
-          "email" : "psilva@redhat.com",
-          "credentials" : [
-            { "type" : "password",
-              "value" : "password" }
-          ],
-          "realmRoles": ["manager"],
-          "applicationRoles": {
-              "account": [ "manage-account" ]
-          }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            }
-        ]
-    }
+{
+    "id": "realm-with-oidc-identity-provider",
+    "realm": "realm-with-oidc-identity-provider",
+    "enabled": true,
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "foo", "bar" ],
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "clients" : [
+      {
+        "clientId": "broker-app",
+        "consentRequired": "false",
+        "enabled": true,
+        "secret": "secret",
+        "redirectUris": [
+          "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-oidc-idp/endpoint/*"
+        ],
+        "protocolMappers": [
+            {
+                "name": "mobile",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-usermodel-attribute-mapper",
+                "consentRequired": false,
+                "config": {
+                    "user.attribute": "mobile",
+                    "claim.name": "mobile",
+                    "Claim JSON Type": "String",
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            },
+            {
+                "name": "username",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-usermodel-property-mapper",
+                "consentRequired": false,
+                "config": {
+                    "user.attribute": "username",
+                    "claim.name": "preferred_username",
+                    "Claim JSON Type": "String",
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            },
+            {
+                "name": "email",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-usermodel-property-mapper",
+                "consentRequired": false,
+                "config": {
+                    "user.attribute": "email",
+                    "claim.name": "email",
+                    "Claim JSON Type": "String",
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            },
+            {
+                "name": "given name",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-usermodel-property-mapper",
+                "consentRequired": false,
+                "config": {
+                    "user.attribute": "firstName",
+                    "claim.name": "given_name",
+                    "Claim JSON Type": "String",
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            },
+            {
+                "name": "family name",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-usermodel-property-mapper",
+                "consentRequired": false,
+                "config": {
+                    "user.attribute": "lastName",
+                    "claim.name": "family_name",
+                    "Claim JSON Type": "String",
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            },
+            {
+                "name": "full name",
+                "protocol": "openid-connect",
+                "protocolMapper": "oidc-full-name-mapper",
+                "consentRequired": false,
+                "config": {
+                    "access.token.claim": "true",
+                    "id.token.claim": "true"
+
+                }
+            }
+
+        ]
+      }
+    ],
+    "scopeMappings": [
+        {
+            "client": "broker-app",
+            "roles": ["manager"]
+        }
+    ],
+    "users": [
+        {
+            "username" : "test-user",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "firstName" : "Test",
+            "lastName" : "User",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["manager"],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            },
+            "attributes": {
+                "mobile": "617-666-7777"
+            }
+        },
+        {
+            "username" : "test-user-noemail",
+            "enabled": true,
+            "firstName" : "Test",
+            "lastName" : "User",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["manager"],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+          "username" : "pedroigor",
+          "enabled": true,
+          "email" : "psilva@redhat.com",
+          "credentials" : [
+            { "type" : "password",
+              "value" : "password" }
+          ],
+          "realmRoles": ["manager"],
+          "applicationRoles": {
+              "account": [ "manage-account" ]
+          }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            }
+        ]
+    }
 }
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
index 1fba984..50511d5 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
@@ -1,112 +1,112 @@
-{
-    "id": "realm-with-saml-idp-basic",
-    "realm": "realm-with-saml-idp-basic",
-    "enabled": true,
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "foo", "bar" ],
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "clients": [
-        {
-            "clientId": "http://localhost:8081/auth/realms/realm-with-broker",
-            "enabled": true,
-            "protocol": "saml",
-            "redirectUris": [
-                "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint"
-            ],
-            "attributes": {
-                "saml.authnstatement": "true",
-                "saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
-                "saml_assertion_consumer_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
-                "saml_force_name_id_format": "true",
-                "saml_name_id_format": "username"
-
-            },
-            "protocolMappers": [
-                {
-                    "name": "role list",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-role-list-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "attribute.name": "Role",
-                        "attribute.nameformat": "Basic",
-                        "single": "false"
-
-                    }
-                },
-                {
-                    "name": "mobile",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-attribute-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "mobile",
-                        "attribute.name": "mobile",
-                        "attribute.nameformat": "Basic"
-                    }
-                },
-                {
-                    "name": "email",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-property-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "email",
-                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
-                        "attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
-                        "friendly.name": "email"
-                    }
-                }
-
-            ]
-
-        }
-    ],
-    "users": [
-      {
-        "username" : "test-user",
-        "enabled": true,
-        "email" : "test-user@localhost",
-        "firstName" : "Test",
-        "lastName" : "User",
-        "credentials" : [
-          { "type" : "password",
-            "value" : "password" }
-        ],
-        "realmRoles": ["manager"],
-          "attributes": {
-              "mobile": "617-666-7777"
-          }
-      },
-      {
-            "username" : "test-user-noemail",
-            "enabled": true,
-            "firstName" : "Test",
-            "lastName" : "User",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["manager"]
-      },
-      {
-        "username" : "pedroigor",
-        "enabled": true,
-        "email" : "psilva@redhat.com",
-        "credentials" : [
-          { "type" : "password",
-            "value" : "password" }
-        ],
-        "realmRoles": ["manager"]
-      }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            }
-        ]
-    }
+{
+    "id": "realm-with-saml-idp-basic",
+    "realm": "realm-with-saml-idp-basic",
+    "enabled": true,
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "foo", "bar" ],
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "clients": [
+        {
+            "clientId": "http://localhost:8081/auth/realms/realm-with-broker",
+            "enabled": true,
+            "protocol": "saml",
+            "redirectUris": [
+                "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true",
+                "saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
+                "saml_assertion_consumer_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
+                "saml_force_name_id_format": "true",
+                "saml_name_id_format": "username"
+
+            },
+            "protocolMappers": [
+                {
+                    "name": "role list",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-role-list-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "attribute.name": "Role",
+                        "attribute.nameformat": "Basic",
+                        "single": "false"
+
+                    }
+                },
+                {
+                    "name": "mobile",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-attribute-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "mobile",
+                        "attribute.name": "mobile",
+                        "attribute.nameformat": "Basic"
+                    }
+                },
+                {
+                    "name": "email",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-property-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "email",
+                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
+                        "attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                        "friendly.name": "email"
+                    }
+                }
+
+            ]
+
+        }
+    ],
+    "users": [
+      {
+        "username" : "test-user",
+        "enabled": true,
+        "email" : "test-user@localhost",
+        "firstName" : "Test",
+        "lastName" : "User",
+        "credentials" : [
+          { "type" : "password",
+            "value" : "password" }
+        ],
+        "realmRoles": ["manager"],
+          "attributes": {
+              "mobile": "617-666-7777"
+          }
+      },
+      {
+            "username" : "test-user-noemail",
+            "enabled": true,
+            "firstName" : "Test",
+            "lastName" : "User",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["manager"]
+      },
+      {
+        "username" : "pedroigor",
+        "enabled": true,
+        "email" : "psilva@redhat.com",
+        "credentials" : [
+          { "type" : "password",
+            "value" : "password" }
+        ],
+        "realmRoles": ["manager"]
+      }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            }
+        ]
+    }
 }
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
index d377254..d101a41 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
@@ -1,116 +1,116 @@
-{
-    "id": "realm-with-saml-signed-idp",
-    "realm": "realm-with-saml-signed-idp",
-    "enabled": true,
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "foo", "bar" ],
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "clients": [
-        {
-            "clientId": "http://localhost:8081/auth/realms/realm-with-broker",
-            "protocol": "saml",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint"
-            ],
-            "attributes": {
-                "saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
-                "saml_assertion_consumer_url_post":    "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
-                "saml_force_name_id_format": "true",
-                "saml_name_id_format": "username",
-                "saml.assertion.signature": "true",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"
-            },
-            "protocolMappers": [
-                {
-                    "name": "role list",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-role-list-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "attribute.name": "Role",
-                        "attribute.nameformat": "Basic",
-                        "single": "false"
-
-                    }
-                },
-                {
-                    "name": "mobile",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-attribute-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "mobile",
-                        "attribute.name": "mobile",
-                        "attribute.nameformat": "Basic"
-                    }
-                },
-                {
-                    "name": "email",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-property-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "email",
-                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
-                        "attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
-                        "friendly.name": "email"
-                    }
-                }
-
-            ]
-        }
-    ],
-    "users": [
-      {
-        "username" : "test-user",
-        "enabled": true,
-        "email" : "test-user@localhost",
-        "firstName" : "Test",
-        "lastName" : "User",
-        "credentials" : [
-          { "type" : "password",
-            "value" : "password" }
-        ],
-        "realmRoles": ["manager"],
-          "attributes": {
-              "mobile": "617-666-7777"
-          }
-      },
-      {
-            "username" : "test-user-noemail",
-            "enabled": true,
-            "firstName" : "Test",
-            "lastName" : "User",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["manager"]
-      },
-      {
-        "username" : "pedroigor",
-        "enabled": true,
-        "email" : "psilva@redhat.com",
-        "credentials" : [
-          { "type" : "password",
-            "value" : "password" }
-        ],
-        "realmRoles": ["manager"]
-      }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            }
-        ]
-    }
+{
+    "id": "realm-with-saml-signed-idp",
+    "realm": "realm-with-saml-signed-idp",
+    "enabled": true,
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "foo", "bar" ],
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "clients": [
+        {
+            "clientId": "http://localhost:8081/auth/realms/realm-with-broker",
+            "protocol": "saml",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint"
+            ],
+            "attributes": {
+                "saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
+                "saml_assertion_consumer_url_post":    "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
+                "saml_force_name_id_format": "true",
+                "saml_name_id_format": "username",
+                "saml.assertion.signature": "true",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"
+            },
+            "protocolMappers": [
+                {
+                    "name": "role list",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-role-list-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "attribute.name": "Role",
+                        "attribute.nameformat": "Basic",
+                        "single": "false"
+
+                    }
+                },
+                {
+                    "name": "mobile",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-attribute-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "mobile",
+                        "attribute.name": "mobile",
+                        "attribute.nameformat": "Basic"
+                    }
+                },
+                {
+                    "name": "email",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-property-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "email",
+                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
+                        "attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                        "friendly.name": "email"
+                    }
+                }
+
+            ]
+        }
+    ],
+    "users": [
+      {
+        "username" : "test-user",
+        "enabled": true,
+        "email" : "test-user@localhost",
+        "firstName" : "Test",
+        "lastName" : "User",
+        "credentials" : [
+          { "type" : "password",
+            "value" : "password" }
+        ],
+        "realmRoles": ["manager"],
+          "attributes": {
+              "mobile": "617-666-7777"
+          }
+      },
+      {
+            "username" : "test-user-noemail",
+            "enabled": true,
+            "firstName" : "Test",
+            "lastName" : "User",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["manager"]
+      },
+      {
+        "username" : "pedroigor",
+        "enabled": true,
+        "email" : "psilva@redhat.com",
+        "credentials" : [
+          { "type" : "password",
+            "value" : "password" }
+        ],
+        "realmRoles": ["manager"]
+      }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            }
+        ]
+    }
 }
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
index a6ace52..410d373 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
@@ -1,304 +1,304 @@
-{
-    "id": "realm-with-broker",
-    "realm": "realm-with-broker",
-    "enabled": true,
-    "requiredCredentials": [ "password" ],
-    "resetPasswordAllowed": true,
-    "registrationAllowed": true,
-    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
-    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "identityProviders" : [
-        {
-            "alias" : "model-google",
-            "providerId" : "google",
-            "enabled": true,
-            "updateProfileFirstLogin" : "true",
-            "trustEmail" : "true",
-            "storeToken": "true",
-            "config": {
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-            "alias" : "model-facebook",
-            "providerId" : "facebook",
-            "enabled": true,
-            "updateProfileFirstLogin" : "false",
-            "config": {
-                "authorizationUrl": "authorizationUrl",
-                "tokenUrl": "tokenUrl",
-                "userInfoUrl": "userInfoUrl",
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-            "alias" : "model-github",
-            "providerId" : "github",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
-            "storeToken": "false",
-            "config": {
-                "authorizationUrl": "authorizationUrl",
-                "tokenUrl": "tokenUrl",
-                "userInfoUrl": "userInfoUrl",
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-            "alias" : "model-twitter",
-            "providerId" : "twitter",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
-            "storeToken": true,
-            "config": {
-                "authorizationUrl": "authorizationUrl",
-                "tokenUrl": "tokenUrl",
-                "userInfoUrl": "userInfoUrl",
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-            "alias" : "model-linkedin",
-            "providerId" : "linkedin",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "missing",
-            "storeToken": false,
-            "config": {
-                "authorizationUrl": "authorizationUrl",
-                "tokenUrl": "tokenUrl",
-                "userInfoUrl": "userInfoUrl",
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-            "alias" : "model-stackoverflow",
-            "providerId" : "stackoverflow",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
-            "storeToken": false,
-            "config": {
-                "key": "keyValue",
-                "authorizationUrl": "authorizationUrl",
-                "tokenUrl": "tokenUrl",
-                "userInfoUrl": "userInfoUrl",
-                "clientId": "clientId",
-                "clientSecret": "clientSecret"
-            }
-        },
-        {
-          "alias" : "model-saml-signed-idp",
-          "providerId" : "saml",
-          "enabled": true,
-          "updateProfileFirstLoginMode" : "on",
-          "config": {
-            "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml",
-            "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
-            "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
-            "wantAuthnRequestsSigned": true,
-            "forceAuthn": true,
-            "validateSignature": true,
-            "postBindingResponse": true,
-            "postBindingAuthnRequest": true
-          }
-        },
-        {
-            "alias" : "kc-saml-signed-idp",
-            "providerId" : "saml",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
-            "addReadTokenRoleOnCreate": true,
-            "config": {
-                "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
-                "singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
-                "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
-                "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
-                "wantAuthnRequestsSigned": true,
-                "forceAuthn": true,
-                "validateSignature": true,
-                "postBindingResponse": true,
-                "postBindingAuthnRequest": true,
-                "backchannelSupported": true
-            }
-        },
-        {
-            "alias" : "kc-saml-idp-basic",
-            "providerId" : "saml",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
-            "trustEmail" : false,
-            "addReadTokenRoleOnCreate": true,
-            "config": {
-                "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
-                "singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
-                "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
-                "forceAuthn": true,
-                "postBindingResponse": true,
-                "postBindingAuthnRequest": true
-            }
-        },
-        {
-            "alias" : "model-oidc-idp",
-            "providerId" : "oidc",
-            "enabled": false,
-            "updateProfileFirstLoginMode" : "off",
-            "authenticateByDefault" : "false",
-            "config": {
-                "clientId": "clientId",
-                "clientSecret": "clientSecret",
-                "prompt": "prompt",
-                "authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
-                "tokenUrl": "http://localhost:8081/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
-                "userInfoUrl": "http://localhost:8081/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
-                "defaultScope": "email profile"
-            }
-        },
-        {
-            "alias" : "kc-oidc-idp",
-            "providerId" : "keycloak-oidc",
-            "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
-            "storeToken" : true,
-            "addReadTokenRoleOnCreate": true,
-            "config": {
-                "clientId": "broker-app",
-                "clientSecret": "secret",
-                "prompt": "login",
-                "authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
-                "tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
-                "userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
-                "logoutUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/logout",
-                "defaultScope": "email profile",
-                "backchannelSupported": "true"
-            }
-        }
-    ],
-    "identityProviderMappers": [
-        {
-            "name": "manager-mapper",
-            "identityProviderAlias": "kc-oidc-idp",
-            "identityProviderMapper": "oidc-role-idp-mapper",
-            "config": {
-                "role": "manager",
-                "claim": "realm_access.roles",
-                "claim.value": "manager"
-            }
-
-        },
-        {
-            "name": "mobile-mapper",
-            "identityProviderAlias": "kc-oidc-idp",
-            "identityProviderMapper": "oidc-user-attribute-idp-mapper",
-            "config": {
-                "user.attribute": "mobile",
-                "claim": "mobile"
-            }
-        },
-        {
-            "name": "manager-mapper",
-            "identityProviderAlias": "kc-saml-idp-basic",
-            "identityProviderMapper": "saml-role-idp-mapper",
-            "config": {
-                "role": "manager",
-                "attribute.name": "Role",
-                "attribute.value": "manager"
-            }
-
-        },
-        {
-            "name": "mobile-mapper",
-            "identityProviderAlias": "kc-saml-idp-basic",
-            "identityProviderMapper": "saml-user-attribute-idp-mapper",
-            "config": {
-                "user.attribute": "mobile",
-                "attribute.name": "mobile"
-            }
-        },
-        {
-            "name": "manager-mapper",
-            "identityProviderAlias": "kc-saml-signed-idp",
-            "identityProviderMapper": "saml-role-idp-mapper",
-            "config": {
-                "role": "manager",
-                "attribute.name": "Role",
-                "attribute.value": "manager"
-            }
-
-        },
-        {
-            "name": "mobile-mapper",
-            "identityProviderAlias": "kc-saml-signed-idp",
-            "identityProviderMapper": "saml-user-attribute-idp-mapper",
-            "config": {
-                "user.attribute": "mobile",
-                "attribute.name": "mobile"
-            }
-        }
-    ],
-    "users": [
-        {
-            "username" : "pedroigor",
-            "enabled": true,
-            "email" : "psilva@redhat.com",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["manager"],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "applications": [
-        {
-            "name": "test-app",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8081/test-app",
-            "baseUrl": "http://localhost:8081/test-app",
-            "redirectUris": [
-                "/test-app/*"
-            ],
-            "webOrigins": []
-        },
-        {
-          "name": "test-app-with-allowed-providers",
-          "enabled": true,
-          "publicClient": true,
-          "adminUrl": "http://localhost:8081/auth",
-          "baseUrl": "http://localhost:8081/auth",
-          "redirectUris": [
-            "/test-app/*"
-          ],
-          "webOrigins": []
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8081/third-party/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            }
-        ]
-    }
-}
+{
+    "id": "realm-with-broker",
+    "realm": "realm-with-broker",
+    "enabled": true,
+    "requiredCredentials": [ "password" ],
+    "resetPasswordAllowed": true,
+    "registrationAllowed": true,
+    "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
+    "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "identityProviders" : [
+        {
+            "alias" : "model-google",
+            "providerId" : "google",
+            "enabled": true,
+            "updateProfileFirstLogin" : "true",
+            "trustEmail" : "true",
+            "storeToken": "true",
+            "config": {
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+            "alias" : "model-facebook",
+            "providerId" : "facebook",
+            "enabled": true,
+            "updateProfileFirstLogin" : "false",
+            "config": {
+                "authorizationUrl": "authorizationUrl",
+                "tokenUrl": "tokenUrl",
+                "userInfoUrl": "userInfoUrl",
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+            "alias" : "model-github",
+            "providerId" : "github",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "on",
+            "storeToken": "false",
+            "config": {
+                "authorizationUrl": "authorizationUrl",
+                "tokenUrl": "tokenUrl",
+                "userInfoUrl": "userInfoUrl",
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+            "alias" : "model-twitter",
+            "providerId" : "twitter",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "off",
+            "storeToken": true,
+            "config": {
+                "authorizationUrl": "authorizationUrl",
+                "tokenUrl": "tokenUrl",
+                "userInfoUrl": "userInfoUrl",
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+            "alias" : "model-linkedin",
+            "providerId" : "linkedin",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "missing",
+            "storeToken": false,
+            "config": {
+                "authorizationUrl": "authorizationUrl",
+                "tokenUrl": "tokenUrl",
+                "userInfoUrl": "userInfoUrl",
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+            "alias" : "model-stackoverflow",
+            "providerId" : "stackoverflow",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "off",
+            "storeToken": false,
+            "config": {
+                "key": "keyValue",
+                "authorizationUrl": "authorizationUrl",
+                "tokenUrl": "tokenUrl",
+                "userInfoUrl": "userInfoUrl",
+                "clientId": "clientId",
+                "clientSecret": "clientSecret"
+            }
+        },
+        {
+          "alias" : "model-saml-signed-idp",
+          "providerId" : "saml",
+          "enabled": true,
+          "updateProfileFirstLoginMode" : "on",
+          "config": {
+            "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml",
+            "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
+            "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
+            "wantAuthnRequestsSigned": true,
+            "forceAuthn": true,
+            "validateSignature": true,
+            "postBindingResponse": true,
+            "postBindingAuthnRequest": true
+          }
+        },
+        {
+            "alias" : "kc-saml-signed-idp",
+            "providerId" : "saml",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "on",
+            "addReadTokenRoleOnCreate": true,
+            "config": {
+                "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
+                "singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
+                "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
+                "signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
+                "wantAuthnRequestsSigned": true,
+                "forceAuthn": true,
+                "validateSignature": true,
+                "postBindingResponse": true,
+                "postBindingAuthnRequest": true,
+                "backchannelSupported": true
+            }
+        },
+        {
+            "alias" : "kc-saml-idp-basic",
+            "providerId" : "saml",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "on",
+            "trustEmail" : false,
+            "addReadTokenRoleOnCreate": true,
+            "config": {
+                "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
+                "singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
+                "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
+                "forceAuthn": true,
+                "postBindingResponse": true,
+                "postBindingAuthnRequest": true
+            }
+        },
+        {
+            "alias" : "model-oidc-idp",
+            "providerId" : "oidc",
+            "enabled": false,
+            "updateProfileFirstLoginMode" : "off",
+            "authenticateByDefault" : "false",
+            "config": {
+                "clientId": "clientId",
+                "clientSecret": "clientSecret",
+                "prompt": "prompt",
+                "authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
+                "tokenUrl": "http://localhost:8081/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
+                "userInfoUrl": "http://localhost:8081/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
+                "defaultScope": "email profile"
+            }
+        },
+        {
+            "alias" : "kc-oidc-idp",
+            "providerId" : "keycloak-oidc",
+            "enabled": true,
+            "updateProfileFirstLoginMode" : "off",
+            "storeToken" : true,
+            "addReadTokenRoleOnCreate": true,
+            "config": {
+                "clientId": "broker-app",
+                "clientSecret": "secret",
+                "prompt": "login",
+                "authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
+                "tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
+                "userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
+                "logoutUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/logout",
+                "defaultScope": "email profile",
+                "backchannelSupported": "true"
+            }
+        }
+    ],
+    "identityProviderMappers": [
+        {
+            "name": "manager-mapper",
+            "identityProviderAlias": "kc-oidc-idp",
+            "identityProviderMapper": "oidc-role-idp-mapper",
+            "config": {
+                "role": "manager",
+                "claim": "realm_access.roles",
+                "claim.value": "manager"
+            }
+
+        },
+        {
+            "name": "mobile-mapper",
+            "identityProviderAlias": "kc-oidc-idp",
+            "identityProviderMapper": "oidc-user-attribute-idp-mapper",
+            "config": {
+                "user.attribute": "mobile",
+                "claim": "mobile"
+            }
+        },
+        {
+            "name": "manager-mapper",
+            "identityProviderAlias": "kc-saml-idp-basic",
+            "identityProviderMapper": "saml-role-idp-mapper",
+            "config": {
+                "role": "manager",
+                "attribute.name": "Role",
+                "attribute.value": "manager"
+            }
+
+        },
+        {
+            "name": "mobile-mapper",
+            "identityProviderAlias": "kc-saml-idp-basic",
+            "identityProviderMapper": "saml-user-attribute-idp-mapper",
+            "config": {
+                "user.attribute": "mobile",
+                "attribute.name": "mobile"
+            }
+        },
+        {
+            "name": "manager-mapper",
+            "identityProviderAlias": "kc-saml-signed-idp",
+            "identityProviderMapper": "saml-role-idp-mapper",
+            "config": {
+                "role": "manager",
+                "attribute.name": "Role",
+                "attribute.value": "manager"
+            }
+
+        },
+        {
+            "name": "mobile-mapper",
+            "identityProviderAlias": "kc-saml-signed-idp",
+            "identityProviderMapper": "saml-user-attribute-idp-mapper",
+            "config": {
+                "user.attribute": "mobile",
+                "attribute.name": "mobile"
+            }
+        }
+    ],
+    "users": [
+        {
+            "username" : "pedroigor",
+            "enabled": true,
+            "email" : "psilva@redhat.com",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["manager"],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "applications": [
+        {
+            "name": "test-app",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8081/test-app",
+            "baseUrl": "http://localhost:8081/test-app",
+            "redirectUris": [
+                "/test-app/*"
+            ],
+            "webOrigins": []
+        },
+        {
+          "name": "test-app-with-allowed-providers",
+          "enabled": true,
+          "publicClient": true,
+          "adminUrl": "http://localhost:8081/auth",
+          "baseUrl": "http://localhost:8081/auth",
+          "redirectUris": [
+            "/test-app/*"
+          ],
+          "webOrigins": []
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8081/third-party/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            }
+        ]
+    }
+}
diff --git a/testsuite/integration/src/test/resources/model/testcomposites.json b/testsuite/integration/src/test/resources/model/testcomposites.json
index 45a2f30..740a4e1 100755
--- a/testsuite/integration/src/test/resources/model/testcomposites.json
+++ b/testsuite/integration/src/test/resources/model/testcomposites.json
@@ -1,191 +1,191 @@
-{
-    "id": "TestComposites",
-    "realm": "TestComposites",
-    "enabled": true,
-    "accessTokenLifespan": 600,
-    "accessCodeLifespan": 600,
-    "accessCodeLifespanUserAction": 600,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "resetPasswordAllowed": true,
-    "requiredCredentials": [ "password" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "REALM_COMPOSITE_1_USER",
-            "enabled": true,
-            "email" : "test-user1@localhost",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "REALM_COMPOSITE_1" ]
-        },
-        {
-            "username" : "REALM_ROLE_1_USER",
-            "enabled": true,
-            "email" : "test-user2@localhost",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "REALM_ROLE_1"]
-        },
-        {
-            "username" : "REALM_APP_COMPOSITE_USER",
-            "enabled": true,
-            "email" : "test-user3@localhost",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "REALM_APP_COMPOSITE_ROLE" ]
-        },
-        {
-            "username" : "REALM_APP_ROLE_USER",
-            "enabled": true,
-            "email" : "test-user4@localhost",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "applicationRoles": {
-                "APP_ROLE_APPLICATION": [ "APP_ROLE_2" ]
-            }
-        },
-        {
-            "username" : "APP_COMPOSITE_USER",
-            "enabled": true,
-            "email" : "test-user5@localhost",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": ["REALM_APP_COMPOSITE_ROLE", "REALM_COMPOSITE_1"]
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "secret": "password"
-        }
-    ],
-    "scopeMappings": [
-        {
-            "client": "REALM_COMPOSITE_1_APPLICATION",
-            "roles": ["REALM_COMPOSITE_1"]
-        },
-        {
-            "client": "REALM_ROLE_1_APPLICATION",
-            "roles": ["REALM_ROLE_1"]
-        }
-    ],
-    "applications": [
-        {
-            "name": "REALM_COMPOSITE_1_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-         },
-        {
-            "name": "REALM_ROLE_1_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-        },
-        {
-            "name": "APP_ROLE_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-        },
-        {
-            "name": "APP_COMPOSITE_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "REALM_ROLE_1"
-            },
-            {
-                "name": "REALM_ROLE_2"
-            },
-            {
-                "name": "REALM_ROLE_3"
-            },
-            {
-                "name": "REALM_COMPOSITE_1",
-                "composites": {
-                    "realm": ["REALM_ROLE_1"]
-                }
-            },
-            {
-                "name": "REALM_APP_COMPOSITE_ROLE",
-                "composites": {
-                    "application": {
-                        "APP_ROLE_APPLICATION" :[
-                            "APP_ROLE_1"
-                        ]
-                    }
-                }
-            }
-        ],
-        "application" : {
-            "APP_ROLE_APPLICATION" : [
-                {
-                    "name": "APP_ROLE_1"
-                },
-                {
-                    "name": "APP_ROLE_2"
-                }
-            ],
-            "APP_COMPOSITE_APPLICATION" : [
-                {
-                    "name": "APP_COMPOSITE_ROLE",
-                    "composites": {
-                        "realm" : [
-                            "REALM_ROLE_1",
-                            "REALM_ROLE_2",
-                            "REALM_ROLE_3"
-                        ],
-                        "application": {
-                            "APP_ROLE_APPLICATION" :[
-                                "APP_ROLE_1"
-                            ]
-                        }
-                    }
-                },
-                {
-                    "name": "APP_ROLE_2"
-                }
-            ]
-        }
-
-    },
-
-    "applicationScopeMappings": {
-        "APP_ROLE_APPLICATION": [
-            {
-                "client": "APP_COMPOSITE_APPLICATION",
-                "roles": ["APP_ROLE_2"]
-            }
-        ]
-    }
-}
+{
+    "id": "TestComposites",
+    "realm": "TestComposites",
+    "enabled": true,
+    "accessTokenLifespan": 600,
+    "accessCodeLifespan": 600,
+    "accessCodeLifespanUserAction": 600,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "resetPasswordAllowed": true,
+    "requiredCredentials": [ "password" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "REALM_COMPOSITE_1_USER",
+            "enabled": true,
+            "email" : "test-user1@localhost",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "REALM_COMPOSITE_1" ]
+        },
+        {
+            "username" : "REALM_ROLE_1_USER",
+            "enabled": true,
+            "email" : "test-user2@localhost",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "REALM_ROLE_1"]
+        },
+        {
+            "username" : "REALM_APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user3@localhost",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "REALM_APP_COMPOSITE_ROLE" ]
+        },
+        {
+            "username" : "REALM_APP_ROLE_USER",
+            "enabled": true,
+            "email" : "test-user4@localhost",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "applicationRoles": {
+                "APP_ROLE_APPLICATION": [ "APP_ROLE_2" ]
+            }
+        },
+        {
+            "username" : "APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user5@localhost",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": ["REALM_APP_COMPOSITE_ROLE", "REALM_COMPOSITE_1"]
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "secret": "password"
+        }
+    ],
+    "scopeMappings": [
+        {
+            "client": "REALM_COMPOSITE_1_APPLICATION",
+            "roles": ["REALM_COMPOSITE_1"]
+        },
+        {
+            "client": "REALM_ROLE_1_APPLICATION",
+            "roles": ["REALM_ROLE_1"]
+        }
+    ],
+    "applications": [
+        {
+            "name": "REALM_COMPOSITE_1_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+         },
+        {
+            "name": "REALM_ROLE_1_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+        },
+        {
+            "name": "APP_ROLE_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+        },
+        {
+            "name": "APP_COMPOSITE_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "REALM_ROLE_1"
+            },
+            {
+                "name": "REALM_ROLE_2"
+            },
+            {
+                "name": "REALM_ROLE_3"
+            },
+            {
+                "name": "REALM_COMPOSITE_1",
+                "composites": {
+                    "realm": ["REALM_ROLE_1"]
+                }
+            },
+            {
+                "name": "REALM_APP_COMPOSITE_ROLE",
+                "composites": {
+                    "application": {
+                        "APP_ROLE_APPLICATION" :[
+                            "APP_ROLE_1"
+                        ]
+                    }
+                }
+            }
+        ],
+        "application" : {
+            "APP_ROLE_APPLICATION" : [
+                {
+                    "name": "APP_ROLE_1"
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ],
+            "APP_COMPOSITE_APPLICATION" : [
+                {
+                    "name": "APP_COMPOSITE_ROLE",
+                    "composites": {
+                        "realm" : [
+                            "REALM_ROLE_1",
+                            "REALM_ROLE_2",
+                            "REALM_ROLE_3"
+                        ],
+                        "application": {
+                            "APP_ROLE_APPLICATION" :[
+                                "APP_ROLE_1"
+                            ]
+                        }
+                    }
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ]
+        }
+
+    },
+
+    "applicationScopeMappings": {
+        "APP_ROLE_APPLICATION": [
+            {
+                "client": "APP_COMPOSITE_APPLICATION",
+                "roles": ["APP_ROLE_2"]
+            }
+        ]
+    }
+}
diff --git a/testsuite/integration/src/test/resources/model/testrealm.json b/testsuite/integration/src/test/resources/model/testrealm.json
index 4512bad..340d9d3 100755
--- a/testsuite/integration/src/test/resources/model/testrealm.json
+++ b/testsuite/integration/src/test/resources/model/testrealm.json
@@ -1,227 +1,227 @@
-{
-    "realm": "test-realm",
-    "enabled": true,
-    "accessTokenLifespan": 6000,
-    "accessCodeLifespan": 30,
-    "accessCodeLifespanUserAction": 600,
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "foo", "bar" ],
-    "verifyEmail" : "true",
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "identityProviders" : [
-        {
-            "providerId" : "google",
-            "alias" : "google1",
-            "enabled": true,
-            "config": {
-                "clientId": "googleId",
-                "clientSecret": "googleSecret"
-            }
-        }
-    ],
-    "userFederationProviders": [
-        {
-            "displayName": "MyLDAPProvider1",
-            "providerName": "ldap",
-            "priority": 1,
-            "config": {
-                "connectionUrl": "ldap://foo"
-            }
-        },
-        {
-            "displayName": "MyLDAPProvider2",
-            "providerName": "ldap",
-            "priority": 2,
-            "config": {
-                "connectionUrl": "ldap://bar"
-            }
-        }
-    ],
-    "userFederationMappers": [
-        {
-            "name": "FullNameMapper",
-            "federationProviderDisplayName": "MyLDAPProvider1",
-            "federationMapperType": "full-name-ldap-mapper",
-            "config": {
-                "ldap.full.name.attribute": "cn"
-            }
-        }
-    ],
-    "users": [
-        {
-            "username": "wburke",
-            "enabled": true,
-            "createdTimestamp" : 123654,
-            "attributes": {
-                "email": "bburke@redhat.com"
-            },
-            "credentials": [
-                {
-                    "type": "password",
-                    "value": "userpassword"
-                }
-            ],
-            "applicationRoles": {
-                "Application": [ "app-user" ],
-                "OtherApp": [  "otherapp-user" ]
-            }
-        },
-        {
-            "username": "loginclient",
-            "createdTimestamp" : "123655",
-            "enabled": true,
-            "credentials": [
-                {
-                    "type": "password",
-                    "value": "clientpassword"
-                }
-            ]
-        },
-        {
-            "username": "admin",
-            "enabled": true,
-            "attributes": {
-                "key1": [
-                    "val1"
-                ],
-                "key2": [
-                    "val21",
-                    "val22"
-                ]
-            },
-            "credentials": [
-                {
-                    "type": "password",
-                    "value": "adminpassword"
-                }
-            ],
-            "realmRoles": [ "admin" ],
-            "applicationRoles": {
-                "Application": [ "app-admin" ],
-                "OtherApp": [  "otherapp-admin" ]
-            },
-            "clientConsents": [
-                {
-                    "clientId": "Application",
-                    "grantedRealmRoles": [ "admin" ],
-                    "grantedClientRoles": {
-                        "Application": [ "app-admin" ]
-                    }
-                },
-                {
-                    "clientId": "OtherApp",
-                    "grantedRealmRoles": [ "admin" ],
-                    "grantedProtocolMappers": {
-                        "openid-connect": [ "gss delegation credential" ]
-                    }
-                }
-            ]
-        },
-        {
-            "username": "mySocialUser",
-            "enabled": true,
-            "federatedIdentities": [
-                {
-                    "identityProvider": "facebook",
-                    "userId": "facebook1",
-                    "userName": "fbuser1"
-                },
-                {
-                    "identityProvider": "twitter",
-                    "userId": "twitter1",
-                    "userName": "twuser1"
-                },
-                {
-                    "identityProvider": "google",
-                    "userId": "google1",
-                    "userName": "mySocialUser@gmail.com"
-                }
-            ]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "Application",
-            "name": "Applicationn",
-            "enabled": true,
-            "nodeReRegistrationTimeout": 50,
-            "registeredNodes": {
-                "node1": 10,
-                "172.10.15.20": 20
-            }
-        },
-        {
-            "clientId": "OtherApp",
-            "name": "Other Application",
-            "enabled": true,
-            "protocolMappers" : [
-                {
-                    "name" : "gss delegation credential",
-                    "protocol" : "openid-connect",
-                    "protocolMapper" : "oidc-usersessionmodel-note-mapper",
-                    "consentRequired" : true,
-                    "consentText" : "gss delegation credential",
-                    "config" : {
-                        "user.session.note" : "gss_delegation_credential",
-                        "access.token.claim" : "true",
-                        "claim.name" : "gss_delegation_credential",
-                        "Claim JSON Type" : "String"
-                    }
-                }
-            ]
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "oauthclient",
-            "enabled": true,
-            "secret": "clientpassword"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "admin"
-            }
-        ],
-        "application" : {
-            "Application" : [
-                {
-                    "name": "app-admin"
-                },
-                {
-                    "name": "app-user"
-                }
-            ],
-            "OtherApp" : [
-                {
-                    "name": "otherapp-admin"
-                },
-                {
-                    "name": "otherapp-user"
-                }
-            ]
-        }
-    },
-    "scopeMappings": [
-        {
-            "client": "oauthclient",
-            "roles": ["admin"]
-        }
-    ],
-    "applicationScopeMappings": {
-        "Application": [
-            {
-                "client": "oauthclient",
-                "roles": ["app-user"]
-            }
-        ]
-
-    }
-
-
+{
+    "realm": "test-realm",
+    "enabled": true,
+    "accessTokenLifespan": 6000,
+    "accessCodeLifespan": 30,
+    "accessCodeLifespanUserAction": 600,
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "foo", "bar" ],
+    "verifyEmail" : "true",
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "identityProviders" : [
+        {
+            "providerId" : "google",
+            "alias" : "google1",
+            "enabled": true,
+            "config": {
+                "clientId": "googleId",
+                "clientSecret": "googleSecret"
+            }
+        }
+    ],
+    "userFederationProviders": [
+        {
+            "displayName": "MyLDAPProvider1",
+            "providerName": "ldap",
+            "priority": 1,
+            "config": {
+                "connectionUrl": "ldap://foo"
+            }
+        },
+        {
+            "displayName": "MyLDAPProvider2",
+            "providerName": "ldap",
+            "priority": 2,
+            "config": {
+                "connectionUrl": "ldap://bar"
+            }
+        }
+    ],
+    "userFederationMappers": [
+        {
+            "name": "FullNameMapper",
+            "federationProviderDisplayName": "MyLDAPProvider1",
+            "federationMapperType": "full-name-ldap-mapper",
+            "config": {
+                "ldap.full.name.attribute": "cn"
+            }
+        }
+    ],
+    "users": [
+        {
+            "username": "wburke",
+            "enabled": true,
+            "createdTimestamp" : 123654,
+            "attributes": {
+                "email": "bburke@redhat.com"
+            },
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "userpassword"
+                }
+            ],
+            "applicationRoles": {
+                "Application": [ "app-user" ],
+                "OtherApp": [  "otherapp-user" ]
+            }
+        },
+        {
+            "username": "loginclient",
+            "createdTimestamp" : "123655",
+            "enabled": true,
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "clientpassword"
+                }
+            ]
+        },
+        {
+            "username": "admin",
+            "enabled": true,
+            "attributes": {
+                "key1": [
+                    "val1"
+                ],
+                "key2": [
+                    "val21",
+                    "val22"
+                ]
+            },
+            "credentials": [
+                {
+                    "type": "password",
+                    "value": "adminpassword"
+                }
+            ],
+            "realmRoles": [ "admin" ],
+            "applicationRoles": {
+                "Application": [ "app-admin" ],
+                "OtherApp": [  "otherapp-admin" ]
+            },
+            "clientConsents": [
+                {
+                    "clientId": "Application",
+                    "grantedRealmRoles": [ "admin" ],
+                    "grantedClientRoles": {
+                        "Application": [ "app-admin" ]
+                    }
+                },
+                {
+                    "clientId": "OtherApp",
+                    "grantedRealmRoles": [ "admin" ],
+                    "grantedProtocolMappers": {
+                        "openid-connect": [ "gss delegation credential" ]
+                    }
+                }
+            ]
+        },
+        {
+            "username": "mySocialUser",
+            "enabled": true,
+            "federatedIdentities": [
+                {
+                    "identityProvider": "facebook",
+                    "userId": "facebook1",
+                    "userName": "fbuser1"
+                },
+                {
+                    "identityProvider": "twitter",
+                    "userId": "twitter1",
+                    "userName": "twuser1"
+                },
+                {
+                    "identityProvider": "google",
+                    "userId": "google1",
+                    "userName": "mySocialUser@gmail.com"
+                }
+            ]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "Application",
+            "name": "Applicationn",
+            "enabled": true,
+            "nodeReRegistrationTimeout": 50,
+            "registeredNodes": {
+                "node1": 10,
+                "172.10.15.20": 20
+            }
+        },
+        {
+            "clientId": "OtherApp",
+            "name": "Other Application",
+            "enabled": true,
+            "protocolMappers" : [
+                {
+                    "name" : "gss delegation credential",
+                    "protocol" : "openid-connect",
+                    "protocolMapper" : "oidc-usersessionmodel-note-mapper",
+                    "consentRequired" : true,
+                    "consentText" : "gss delegation credential",
+                    "config" : {
+                        "user.session.note" : "gss_delegation_credential",
+                        "access.token.claim" : "true",
+                        "claim.name" : "gss_delegation_credential",
+                        "Claim JSON Type" : "String"
+                    }
+                }
+            ]
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "oauthclient",
+            "enabled": true,
+            "secret": "clientpassword"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "admin"
+            }
+        ],
+        "application" : {
+            "Application" : [
+                {
+                    "name": "app-admin"
+                },
+                {
+                    "name": "app-user"
+                }
+            ],
+            "OtherApp" : [
+                {
+                    "name": "otherapp-admin"
+                },
+                {
+                    "name": "otherapp-user"
+                }
+            ]
+        }
+    },
+    "scopeMappings": [
+        {
+            "client": "oauthclient",
+            "roles": ["admin"]
+        }
+    ],
+    "applicationScopeMappings": {
+        "Application": [
+            {
+                "client": "oauthclient",
+                "roles": ["app-user"]
+            }
+        ]
+
+    }
+
+
 }
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/model/testrealm2.json b/testsuite/integration/src/test/resources/model/testrealm2.json
index 85fce1e..4e3d9fb 100755
--- a/testsuite/integration/src/test/resources/model/testrealm2.json
+++ b/testsuite/integration/src/test/resources/model/testrealm2.json
@@ -1,89 +1,89 @@
-{
-    "realm": "demo-delete",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": ["user"],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8080/customer-portal",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8080/product-portal",
-            "redirectUris": [
-                "http://localhost:8080/product-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8080/oauth-client/*",
-                "http://localhost:8080/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-
-}
+{
+    "realm": "demo-delete",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": ["user"],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8080/customer-portal",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8080/product-portal",
+            "redirectUris": [
+                "http://localhost:8080/product-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8080/oauth-client/*",
+                "http://localhost:8080/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+
+}
diff --git a/testsuite/integration/src/test/resources/model/testrealm-demo.json b/testsuite/integration/src/test/resources/model/testrealm-demo.json
index f089c9d..c98bbf7 100755
--- a/testsuite/integration/src/test/resources/model/testrealm-demo.json
+++ b/testsuite/integration/src/test/resources/model/testrealm-demo.json
@@ -1,63 +1,63 @@
-{
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 300,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 600,
-    "sslRequired": "external",
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "credentials" : [
-                { "type" : "Password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ]
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "Have User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Have Administrator privileges"
-            }
-        ]
-    },
-
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        }
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
-            "secret": "password"
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8080/product-portal/j_admin_request",
-            "secret": "password"
-        }
-    ]
-}
+{
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 300,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 600,
+    "sslRequired": "external",
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "credentials" : [
+                { "type" : "Password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ]
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "Have User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Have Administrator privileges"
+            }
+        ]
+    },
+
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        }
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
+            "secret": "password"
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8080/product-portal/j_admin_request",
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/integration/src/test/resources/saml/testsaml.json b/testsuite/integration/src/test/resources/saml/testsaml.json
index fd2c2e3..4db2adf 100755
--- a/testsuite/integration/src/test/resources/saml/testsaml.json
+++ b/testsuite/integration/src/test/resources/saml/testsaml.json
@@ -1,320 +1,320 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "resetPasswordAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "user" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "bburke",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "attributes" : {
-                "phone": "617"
-            },
-            "realmRoles": ["manager", "user"],
-            "applicationRoles": {
-                "http://localhost:8081/employee/": [ "employee" ]
-            }
-        }
-    ],
-    "applications": [
-        {
-            "name": "http://localhost:8081/sales-post/",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "protocol": "saml",
-            "baseUrl": "http://localhost:8081/sales-post",
-            "redirectUris": [
-                "http://localhost:8081/sales-post/*"
-            ],
-            "attributes": {
-                "saml.authnstatement": "true",
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post/",
-                "saml_idp_initiated_sso_url_name": "sales-post"
-            }
-        },
-        {
-            "name": "http://localhost:8081/sales-post-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/sales-post-sig",
-            "redirectUris": [
-                "http://localhost:8081/sales-post-sig/*"
-            ],
-            "attributes": {
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig/",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/sales-post-sig-transient/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/sales-post-sig-transient",
-            "adminUrl": "http://localhost:8081/sales-post-sig-transient",
-            "redirectUris": [
-                "http://localhost:8081/sales-post-sig-transient/*"
-            ],
-            "attributes": {
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-transient/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-transient/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-transient/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-transient/",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/sales-post-sig-persistent/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/sales-post-sig-persistent",
-            "redirectUris": [
-                "http://localhost:8081/sales-post-sig-persistent/*"
-            ],
-            "attributes": {
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-persistent/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-persistent/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-persistent/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-persistent/",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/sales-post-sig-email/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/sales-post-sig-email",
-            "adminUrl": "http://localhost:8081/sales-post-sig-email",
-            "redirectUris": [
-                "http://localhost:8081/sales-post-sig-email/*"
-            ],
-            "attributes": {
-                "saml_force_name_id_format": "true",
-                "saml_name_id_format": "email",
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-email/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-email/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-email/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-email/",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA256",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/bad-realm-sales-post-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/bad-realm-sales-post-sig/",
-            "adminUrl": "http://localhost:8081/bad-realm-sales-post-sig/",
-            "redirectUris": [
-                "http://localhost:8081/bad-realm-sales-post-sig/*"
-            ],
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/bad-client-sales-post-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/bad-client-sales-post-sig/",
-            "adminUrl": "http://localhost:8081/bad-client-sales-post-sig/",
-            "redirectUris": [
-                "http://localhost:8081/bad-client-sales-post-sig/*"
-            ],
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.client.signature": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/sales-post-enc/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/sales-post-enc",
-            "redirectUris": [
-                "http://localhost:8081/sales-post-enc/*"
-            ],
-            "attributes": {
-                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-enc/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-enc/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-enc/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-enc/",
-                "saml.server.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA512",
-                "saml.client.signature": "true",
-                "saml.encrypt": "true",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
-                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g==",
-                "saml.encryption.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
-                "saml.encryption.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
-            }
-        },
-        {
-            "name": "http://localhost:8081/employee-sig/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/employee-sig",
-            "redirectUris": [
-                "http://localhost:8081/employee-sig/*"
-            ],
-            "adminUrl": "http://localhost:8081/employee-sig/",
-            "attributes": {
-                "saml.server.signature": "true",
-                "saml.client.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA1",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
-                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
-            }
-        },
-        {
-            "name": "http://localhost:8081/employee/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/employee",
-            "redirectUris": [
-                "http://localhost:8081/employee/*"
-            ],
-            "adminUrl": "http://localhost:8081/employee/",
-            "attributes": {
-                "saml.authnstatement": "true"
-            },
-            "protocolMappers": [
-                {
-                    "name": "email",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-property-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "email",
-                        "friendly.name": "email",
-                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
-                        "attribute.nameformat": "URI Reference"
-                    }
-                },
-                {
-                    "name": "phone",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-user-attribute-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "user.attribute": "phone",
-                        "attribute.name": "phone",
-                        "attribute.nameformat": "Basic"
-                    }
-                },
-                {
-                    "name": "role-list",
-                    "protocol": "saml",
-                    "protocolMapper": "saml-role-list-mapper",
-                    "consentRequired": false,
-                    "config": {
-                        "attribute.name": "Role",
-                        "attribute.nameformat": "Basic",
-                        "single": "false"
-                    }
-                }
-            ]
-        },
-        {
-            "name": "http://localhost:8081/employee-sig-front/",
-            "enabled": true,
-            "protocol": "saml",
-            "fullScopeAllowed": true,
-            "frontchannelLogout": true,
-            "baseUrl": "http://localhost:8081/employee-sig-front/",
-            "redirectUris": [
-                "http://localhost:8081/employee-sig-front/*"
-            ],
-            "attributes": {
-                "saml_assertion_consumer_url_post": "http://localhost:8081/employee-sig-front/",
-                "saml_assertion_consumer_url_redirect": "http://localhost:8081/employee-sig-front/",
-                "saml_single_logout_service_url_post": "http://localhost:8081/employee-sig-front/",
-                "saml_single_logout_service_url_redirect": "http://localhost:8081/employee-sig-front/",
-                "saml.server.signature": "true",
-                "saml.client.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA1",
-                "saml.authnstatement": "true",
-                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
-                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "manager",
-                "description": "Have Manager privileges"
-            },
-            {
-                "name": "user",
-                "description": "Have User privileges"
-            }
-        ],
-        "application" : {
-            "http://localhost:8081/employee/" : [
-                {
-                    "name": "employee",
-                    "description": "Have Employee privileges"
-                }
-            ]
-        }
-    }
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "resetPasswordAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "user" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "bburke",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "attributes" : {
+                "phone": "617"
+            },
+            "realmRoles": ["manager", "user"],
+            "applicationRoles": {
+                "http://localhost:8081/employee/": [ "employee" ]
+            }
+        }
+    ],
+    "applications": [
+        {
+            "name": "http://localhost:8081/sales-post/",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "protocol": "saml",
+            "baseUrl": "http://localhost:8081/sales-post",
+            "redirectUris": [
+                "http://localhost:8081/sales-post/*"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true",
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post/",
+                "saml_idp_initiated_sso_url_name": "sales-post"
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig/",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig-transient/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-transient",
+            "adminUrl": "http://localhost:8081/sales-post-sig-transient",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-transient/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-transient/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-transient/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-transient/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-transient/",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig-persistent/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-persistent",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-persistent/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-persistent/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-persistent/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-persistent/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-persistent/",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig-email/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-email",
+            "adminUrl": "http://localhost:8081/sales-post-sig-email",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-email/*"
+            ],
+            "attributes": {
+                "saml_force_name_id_format": "true",
+                "saml_name_id_format": "email",
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-sig-email/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-sig-email/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-sig-email/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-sig-email/",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/bad-realm-sales-post-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/bad-realm-sales-post-sig/",
+            "adminUrl": "http://localhost:8081/bad-realm-sales-post-sig/",
+            "redirectUris": [
+                "http://localhost:8081/bad-realm-sales-post-sig/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/bad-client-sales-post-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/bad-client-sales-post-sig/",
+            "adminUrl": "http://localhost:8081/bad-client-sales-post-sig/",
+            "redirectUris": [
+                "http://localhost:8081/bad-client-sales-post-sig/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-enc/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-enc",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-enc/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8081/sales-post-enc/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/sales-post-enc/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/sales-post-enc/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/sales-post-enc/",
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA512",
+                "saml.client.signature": "true",
+                "saml.encrypt": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g==",
+                "saml.encryption.private.key": "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t",
+                "saml.encryption.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/employee-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/employee-sig",
+            "redirectUris": [
+                "http://localhost:8081/employee-sig/*"
+            ],
+            "adminUrl": "http://localhost:8081/employee-sig/",
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA1",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
+                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
+            }
+        },
+        {
+            "name": "http://localhost:8081/employee/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/employee",
+            "redirectUris": [
+                "http://localhost:8081/employee/*"
+            ],
+            "adminUrl": "http://localhost:8081/employee/",
+            "attributes": {
+                "saml.authnstatement": "true"
+            },
+            "protocolMappers": [
+                {
+                    "name": "email",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-property-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "email",
+                        "friendly.name": "email",
+                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
+                        "attribute.nameformat": "URI Reference"
+                    }
+                },
+                {
+                    "name": "phone",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-attribute-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "phone",
+                        "attribute.name": "phone",
+                        "attribute.nameformat": "Basic"
+                    }
+                },
+                {
+                    "name": "role-list",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-role-list-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "attribute.name": "Role",
+                        "attribute.nameformat": "Basic",
+                        "single": "false"
+                    }
+                }
+            ]
+        },
+        {
+            "name": "http://localhost:8081/employee-sig-front/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "frontchannelLogout": true,
+            "baseUrl": "http://localhost:8081/employee-sig-front/",
+            "redirectUris": [
+                "http://localhost:8081/employee-sig-front/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8081/employee-sig-front/",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8081/employee-sig-front/",
+                "saml_single_logout_service_url_post": "http://localhost:8081/employee-sig-front/",
+                "saml_single_logout_service_url_redirect": "http://localhost:8081/employee-sig-front/",
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA1",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICXQIBAAKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABAoGANU1efgc6ojIvwn7Lsf8GAKN9z2D6uS0T3I9nw1k2CtI+xWhgKAUltEANx5lEfBRYIdYclidRpqrk8DYgzASrDYTHXzqVBJfAk1VrAGpqyRq+TNMLUHkXiTiSDOQ6WqhX93UGMmAgQm1RsLa6+fy1BO/B2y85+Yf2OUylsKS6avECQQDslRDiNFdtEjdvyOL20tQ7+W+eKVxVxKAyQ3gFjIIDizELZt+Jq1Wz6XV9NhK1JFtlVugeD1tlW/+K16fEmDYXAkEAzqKoN/JeGb20rfQldAUWdQbb0jrQAYlgoSU/9fYH9YVJT8vnkfhPBTwIw9H9euf1//lRP/jHltHd5ch4230YyQJBAN3rOkoltPiABPZbpuLGgwS7BwOCYrWlWmurtBLoaTCvyVKbrgXybNL1pBrOtR+rufvGWLeRyja65Gs1vY6BBQMCQQCTsNq/MjJj/522f7yNUl2cw4w2lOa7Um+IflFbAcDqkZu2ty0Kvgns2d4B6INeZ5ECpjaWnMA7YkFRzZnkd2NRAkB8lEY56ScnNigoZkkjtEUd2ejdhZPYuS9SKfv9zHwN+I+DE2vVFZz8GPq/iLcMx13PkZaYaJNQ4FtQY/hRLSn5",
+                "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "manager",
+                "description": "Have Manager privileges"
+            },
+            {
+                "name": "user",
+                "description": "Have User privileges"
+            }
+        ],
+        "application" : {
+            "http://localhost:8081/employee/" : [
+                {
+                    "name": "employee",
+                    "description": "Have Employee privileges"
+                }
+            ]
+        }
+    }
+}
diff --git a/testsuite/integration/src/test/resources/testcomposite.json b/testsuite/integration/src/test/resources/testcomposite.json
index 5870eb0..83d5611 100755
--- a/testsuite/integration/src/test/resources/testcomposite.json
+++ b/testsuite/integration/src/test/resources/testcomposite.json
@@ -1,203 +1,203 @@
-{
-    "id": "test",
-    "realm": "test",
-    "enabled": true,
-    "accessTokenLifespan": 600,
-    "accessCodeLifespan": 600,
-    "accessCodeLifespanUserAction": 600,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "resetPasswordAllowed": true,
-    "requiredCredentials": [ "password" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "REALM_COMPOSITE_1_USER",
-            "enabled": true,
-            "email" : "test-user1@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "REALM_COMPOSITE_1" ]
-        },
-        {
-            "username" : "REALM_ROLE_1_USER",
-            "enabled": true,
-            "email" : "test-user2@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["REALM_ROLE_1"]
-        },
-        {
-            "username" : "REALM_APP_COMPOSITE_USER",
-            "enabled": true,
-            "email" : "test-user3@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["REALM_APP_COMPOSITE_ROLE"]
-        },
-        {
-            "username" : "REALM_APP_ROLE_USER",
-            "enabled": true,
-            "email" : "test-user4@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "applicationRoles": {
-                "APP_ROLE_APPLICATION": [ "APP_ROLE_2" ]
-            }
-        },
-        {
-            "username" : "APP_COMPOSITE_USER",
-            "enabled": true,
-            "email" : "test-user5@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["REALM_APP_COMPOSITE_ROLE", "REALM_COMPOSITE_1"]
-        }
-    ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "secret": "password"
-        }
-    ],
-    "scopeMappings": [
-        {
-            "client": "REALM_COMPOSITE_1_APPLICATION",
-            "roles": ["REALM_COMPOSITE_1"]
-        },
-        {
-            "client": "REALM_ROLE_1_APPLICATION",
-            "roles": ["REALM_ROLE_1"]
-        }
-    ],
-    "applications": [
-        {
-            "name": "REALM_COMPOSITE_1_APPLICATION",
-            "enabled": true,
-            "fullScopeAllowed": false,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-         },
-        {
-            "name": "REALM_ROLE_1_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "APP_ROLE_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "APP_COMPOSITE_APPLICATION",
-            "fullScopeAllowed": false,
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "adminUrl": "http://localhost:8081/app/logout",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "REALM_ROLE_1"
-            },
-            {
-                "name": "REALM_ROLE_2"
-            },
-            {
-                "name": "REALM_ROLE_3"
-            },
-            {
-                "name": "REALM_COMPOSITE_1",
-                "composites": {
-                    "realm": ["REALM_ROLE_1"]
-                }
-            },
-            {
-                "name": "REALM_APP_COMPOSITE_ROLE",
-                "composites": {
-                    "application": {
-                        "APP_ROLE_APPLICATION" :[
-                            "APP_ROLE_1"
-                        ]
-                    }
-                }
-            }
-        ],
-        "application" : {
-            "APP_ROLE_APPLICATION" : [
-                {
-                    "name": "APP_ROLE_1"
-                },
-                {
-                    "name": "APP_ROLE_2"
-                }
-            ],
-            "APP_COMPOSITE_APPLICATION" : [
-                {
-                    "name": "APP_COMPOSITE_ROLE",
-                    "composites": {
-                        "realm" : [
-                            "REALM_ROLE_1",
-                            "REALM_ROLE_2",
-                            "REALM_ROLE_3"
-                        ],
-                        "application": {
-                            "APP_ROLE_APPLICATION" :[
-                                "APP_ROLE_1"
-                            ]
-                        }
-                    }
-                },
-                {
-                    "name": "APP_ROLE_2"
-                }
-            ]
-        }
-
-    },
-
-    "applicationScopeMappings": {
-        "APP_ROLE_APPLICATION": [
-            {
-                "client": "APP_COMPOSITE_APPLICATION",
-                "roles": ["APP_ROLE_2"]
-            }
-        ]
-    }
-}
+{
+    "id": "test",
+    "realm": "test",
+    "enabled": true,
+    "accessTokenLifespan": 600,
+    "accessCodeLifespan": 600,
+    "accessCodeLifespanUserAction": 600,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "resetPasswordAllowed": true,
+    "requiredCredentials": [ "password" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "REALM_COMPOSITE_1_USER",
+            "enabled": true,
+            "email" : "test-user1@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "REALM_COMPOSITE_1" ]
+        },
+        {
+            "username" : "REALM_ROLE_1_USER",
+            "enabled": true,
+            "email" : "test-user2@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["REALM_ROLE_1"]
+        },
+        {
+            "username" : "REALM_APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user3@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["REALM_APP_COMPOSITE_ROLE"]
+        },
+        {
+            "username" : "REALM_APP_ROLE_USER",
+            "enabled": true,
+            "email" : "test-user4@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "applicationRoles": {
+                "APP_ROLE_APPLICATION": [ "APP_ROLE_2" ]
+            }
+        },
+        {
+            "username" : "APP_COMPOSITE_USER",
+            "enabled": true,
+            "email" : "test-user5@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["REALM_APP_COMPOSITE_ROLE", "REALM_COMPOSITE_1"]
+        }
+    ],
+    "oauthClients" : [
+        {
+            "name" : "third-party",
+            "enabled": true,
+            "secret": "password"
+        }
+    ],
+    "scopeMappings": [
+        {
+            "client": "REALM_COMPOSITE_1_APPLICATION",
+            "roles": ["REALM_COMPOSITE_1"]
+        },
+        {
+            "client": "REALM_ROLE_1_APPLICATION",
+            "roles": ["REALM_ROLE_1"]
+        }
+    ],
+    "applications": [
+        {
+            "name": "REALM_COMPOSITE_1_APPLICATION",
+            "enabled": true,
+            "fullScopeAllowed": false,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+         },
+        {
+            "name": "REALM_ROLE_1_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "APP_ROLE_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "APP_COMPOSITE_APPLICATION",
+            "fullScopeAllowed": false,
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "adminUrl": "http://localhost:8081/app/logout",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "REALM_ROLE_1"
+            },
+            {
+                "name": "REALM_ROLE_2"
+            },
+            {
+                "name": "REALM_ROLE_3"
+            },
+            {
+                "name": "REALM_COMPOSITE_1",
+                "composites": {
+                    "realm": ["REALM_ROLE_1"]
+                }
+            },
+            {
+                "name": "REALM_APP_COMPOSITE_ROLE",
+                "composites": {
+                    "application": {
+                        "APP_ROLE_APPLICATION" :[
+                            "APP_ROLE_1"
+                        ]
+                    }
+                }
+            }
+        ],
+        "application" : {
+            "APP_ROLE_APPLICATION" : [
+                {
+                    "name": "APP_ROLE_1"
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ],
+            "APP_COMPOSITE_APPLICATION" : [
+                {
+                    "name": "APP_COMPOSITE_ROLE",
+                    "composites": {
+                        "realm" : [
+                            "REALM_ROLE_1",
+                            "REALM_ROLE_2",
+                            "REALM_ROLE_3"
+                        ],
+                        "application": {
+                            "APP_ROLE_APPLICATION" :[
+                                "APP_ROLE_1"
+                            ]
+                        }
+                    }
+                },
+                {
+                    "name": "APP_ROLE_2"
+                }
+            ]
+        }
+
+    },
+
+    "applicationScopeMappings": {
+        "APP_ROLE_APPLICATION": [
+            {
+                "client": "APP_COMPOSITE_APPLICATION",
+                "roles": ["APP_ROLE_2"]
+            }
+        ]
+    }
+}
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index a20c18f..8ad29cc 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -1,119 +1,119 @@
-{
-    "id": "test",
-    "realm": "test",
-    "enabled": true,
-    "sslRequired": "external",
-    "registrationAllowed": true,
-    "resetPasswordAllowed": true,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "user" ],
-    "smtpServer": {
-        "from": "auto@keycloak.org",
-        "host": "localhost",
-        "port":"3025"
-    },
-    "users" : [
-        {
-            "username" : "test-user@localhost",
-            "enabled": true,
-            "email" : "test-user@localhost",
-            "firstName": "Tom",
-            "lastName": "Brady",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": ["user"],
-            "clientRoles": {
-                "test-app": [ "customer-user" ],
-                "account": [ "view-profile", "manage-account" ]
-            }
-        },
-        {
-            "username" : "keycloak-user@localhost",
-            "enabled": true,
-            "email" : "keycloak-user@localhost",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": ["user"],
-            "clientRoles": {
-                "test-app": [ "customer-user" ],
-                "account": [ "view-profile", "manage-account" ]
-            }
-        }
-    ],
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "test-app",
-            "roles": ["user"]
-        }
-    ],
-    "clients": [
-        {
-            "clientId": "test-app",
-            "enabled": true,
-            "baseUrl": "http://localhost:8081/app",
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "adminUrl": "http://localhost:8081/app/logout",
-            "secret": "password"
-        },
-        {
-            "clientId" : "third-party",
-            "enabled": true,
-            "consentRequired": true,
-
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "Have User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Have Administrator privileges"
-            }
-        ],
-        "client" : {
-            "test-app" : [
-                {
-                    "name": "customer-user",
-                    "description": "Have Customer User privileges"
-                },
-                {
-                    "name": "customer-admin",
-                    "description": "Have Customer Admin privileges"
-                }
-            ]
-        }
-
-    },
-
-    "clientScopeMappings": {
-        "test-app": [
-            {
-                "client": "third-party",
-                "roles": ["customer-user"]
-            }
-        ]
-    },
-
-    "internationalizationEnabled": true,
-    "supportedLocales": ["en", "de"],
-    "defaultLocale": "en"
-}
+{
+    "id": "test",
+    "realm": "test",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "resetPasswordAllowed": true,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "defaultRoles": [ "user" ],
+    "smtpServer": {
+        "from": "auto@keycloak.org",
+        "host": "localhost",
+        "port":"3025"
+    },
+    "users" : [
+        {
+            "username" : "test-user@localhost",
+            "enabled": true,
+            "email" : "test-user@localhost",
+            "firstName": "Tom",
+            "lastName": "Brady",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": ["user"],
+            "clientRoles": {
+                "test-app": [ "customer-user" ],
+                "account": [ "view-profile", "manage-account" ]
+            }
+        },
+        {
+            "username" : "keycloak-user@localhost",
+            "enabled": true,
+            "email" : "keycloak-user@localhost",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": ["user"],
+            "clientRoles": {
+                "test-app": [ "customer-user" ],
+                "account": [ "view-profile", "manage-account" ]
+            }
+        }
+    ],
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "test-app",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "test-app",
+            "enabled": true,
+            "baseUrl": "http://localhost:8081/app",
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "adminUrl": "http://localhost:8081/app/logout",
+            "secret": "password"
+        },
+        {
+            "clientId" : "third-party",
+            "enabled": true,
+            "consentRequired": true,
+
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "Have User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Have Administrator privileges"
+            }
+        ],
+        "client" : {
+            "test-app" : [
+                {
+                    "name": "customer-user",
+                    "description": "Have Customer User privileges"
+                },
+                {
+                    "name": "customer-admin",
+                    "description": "Have Customer Admin privileges"
+                }
+            ]
+        }
+
+    },
+
+    "clientScopeMappings": {
+        "test-app": [
+            {
+                "client": "third-party",
+                "roles": ["customer-user"]
+            }
+        ]
+    },
+
+    "internationalizationEnabled": true,
+    "supportedLocales": ["en", "de"],
+    "defaultLocale": "en"
+}
diff --git a/testsuite/jetty/jetty81/pom.xml b/testsuite/jetty/jetty81/pom.xml
index 0ec5e04..b4c6579 100755
--- a/testsuite/jetty/jetty81/pom.xml
+++ b/testsuite/jetty/jetty81/pom.xml
@@ -1,500 +1,500 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-jetty81</artifactId>
-    <name>Keycloak Jetty 8.1.x Integration TestSuite</name>
-    <properties>
-        <jetty9.version>8.1.16.v20140903</jetty9.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-jetty81-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-util</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-webapp</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-security</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-servlet</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-jetty81</artifactId>
+    <name>Keycloak Jetty 8.1.x Integration TestSuite</name>
+    <properties>
+        <jetty9.version>8.1.16.v20140903</jetty9.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-jetty81-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-util</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-webapp</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-security</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-servlet</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+     </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/demorealm.json b/testsuite/jetty/jetty81/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json b/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json
index 0efd923..d122c19 100755
--- a/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json
+++ b/testsuite/jetty/jetty81/src/test/resources/jetty-test/demorealm.json
@@ -1,55 +1,55 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user", "admin" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "adminUrl": "http://localhost:8080/customer-portal",
-            "baseUrl": "http://localhost:8080/customer-portal",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user", "admin" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "adminUrl": "http://localhost:8080/customer-portal",
+            "baseUrl": "http://localhost:8080/customer-portal",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json b/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
index 4e2fe1e..d9caa3f 100755
--- a/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
+++ b/testsuite/jetty/jetty81/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
@@ -1,10 +1,10 @@
-{
-    "realm": "demo",
-    "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "auth-server-url": "http://localhost:8081/auth",
-    "ssl-required" : "external",
-    "credentials": {
-        "secret": "password"
-    }
-}
+{
+    "realm": "demo",
+    "resource": "customer-portal",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "http://localhost:8081/auth",
+    "ssl-required" : "external",
+    "credentials": {
+        "secret": "password"
+    }
+}
diff --git a/testsuite/jetty/jetty91/pom.xml b/testsuite/jetty/jetty91/pom.xml
index 93f1ef2..b468581 100755
--- a/testsuite/jetty/jetty91/pom.xml
+++ b/testsuite/jetty/jetty91/pom.xml
@@ -1,500 +1,500 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-jetty91</artifactId>
-    <name>Keycloak Jetty 9.1.x Integration TestSuite</name>
-    <properties>
-        <jetty9.version>9.1.5.v20140505</jetty9.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-jetty91-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-util</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-webapp</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-security</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-servlet</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-jetty91</artifactId>
+    <name>Keycloak Jetty 9.1.x Integration TestSuite</name>
+    <properties>
+        <jetty9.version>9.1.5.v20140505</jetty9.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-jetty91-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-util</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-webapp</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-security</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-servlet</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+     </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/demorealm.json b/testsuite/jetty/jetty91/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty91/src/test/resources/jetty-test/demorealm.json b/testsuite/jetty/jetty91/src/test/resources/jetty-test/demorealm.json
index 0efd923..d122c19 100755
--- a/testsuite/jetty/jetty91/src/test/resources/jetty-test/demorealm.json
+++ b/testsuite/jetty/jetty91/src/test/resources/jetty-test/demorealm.json
@@ -1,55 +1,55 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user", "admin" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "adminUrl": "http://localhost:8080/customer-portal",
-            "baseUrl": "http://localhost:8080/customer-portal",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user", "admin" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "adminUrl": "http://localhost:8080/customer-portal",
+            "baseUrl": "http://localhost:8080/customer-portal",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/jetty/jetty91/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json b/testsuite/jetty/jetty91/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
index 4e2fe1e..d9caa3f 100755
--- a/testsuite/jetty/jetty91/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
+++ b/testsuite/jetty/jetty91/src/test/resources/jetty-test/webapp/WEB-INF/keycloak.json
@@ -1,10 +1,10 @@
-{
-    "realm": "demo",
-    "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "auth-server-url": "http://localhost:8081/auth",
-    "ssl-required" : "external",
-    "credentials": {
-        "secret": "password"
-    }
-}
+{
+    "realm": "demo",
+    "resource": "customer-portal",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "http://localhost:8081/auth",
+    "ssl-required" : "external",
+    "credentials": {
+        "secret": "password"
+    }
+}
diff --git a/testsuite/jetty/jetty92/pom.xml b/testsuite/jetty/jetty92/pom.xml
index 352c387..1f9d5f3 100755
--- a/testsuite/jetty/jetty92/pom.xml
+++ b/testsuite/jetty/jetty92/pom.xml
@@ -1,507 +1,507 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-jetty92</artifactId>
-    <name>Keycloak Jetty 9.2.x Integration TestSuite</name>
-    <properties>
-        <jetty9.version>9.2.4.v20141103</jetty9.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>1.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-jetty92-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-jaas</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-util</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-webapp</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-security</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.eclipse.jetty</groupId>
-           <artifactId>jetty-servlet</artifactId>
-           <version>${jetty9.version}</version>
-           <scope>provided</scope>
-       </dependency>
-
-     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-jetty92</artifactId>
+    <name>Keycloak Jetty 9.2.x Integration TestSuite</name>
+    <properties>
+        <jetty9.version>9.2.4.v20141103</jetty9.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-jetty92-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-jaas</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-util</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-webapp</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-security</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.eclipse.jetty</groupId>
+           <artifactId>jetty-servlet</artifactId>
+           <version>${jetty9.version}</version>
+           <scope>provided</scope>
+       </dependency>
+
+     </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-db-error-page/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/demorealm.json b/testsuite/jetty/jetty92/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/input-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/product-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/secure-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
index 1ec566d..bd84fd0 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/session-portal/WEB-INF/jetty-web.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-<Configure class="org.eclipse.jetty.webapp.WebAppContext">
-    <Get name="securityHandler">
-        <Set name="authenticator">
-            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
-                <!--
-                <Set name="adapterConfig">
-                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
-                        <Set name="realm">tomcat</Set>
-                        <Set name="resource">customer-portal</Set>
-                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
-                        <Set name="sslRequired">external</Set>
-                        <Set name="credentials">
-                            <Map>
-                                <Entry>
-                                    <Item>secret</Item>
-                                    <Item>password</Item>
-                                </Entry>
-                            </Map>
-                        </Set>
-                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
-                    </New>
-                </Set>
-                -->
-            </New>
-        </Set>
-    </Get>
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+    <Get name="securityHandler">
+        <Set name="authenticator">
+            <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+                <!--
+                <Set name="adapterConfig">
+                    <New class="org.keycloak.representations.adapters.config.AdapterConfig">
+                        <Set name="realm">tomcat</Set>
+                        <Set name="resource">customer-portal</Set>
+                        <Set name="authServerUrl">http://localhost:8081/auth</Set>
+                        <Set name="sslRequired">external</Set>
+                        <Set name="credentials">
+                            <Map>
+                                <Entry>
+                                    <Item>secret</Item>
+                                    <Item>password</Item>
+                                </Entry>
+                            </Map>
+                        </Set>
+                        <Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB</Set>
+                    </New>
+                </Set>
+                -->
+            </New>
+        </Set>
+    </Get>
 </Configure>
\ No newline at end of file

testsuite/pom.xml 176(+88 -88)

diff --git a/testsuite/pom.xml b/testsuite/pom.xml
index 091d0ec..2801612 100755
--- a/testsuite/pom.xml
+++ b/testsuite/pom.xml
@@ -1,88 +1,88 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<parent>
-		<artifactId>keycloak-parent</artifactId>
-		<groupId>org.keycloak</groupId>
-		<version>1.4.0.Final-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<modelVersion>4.0.0</modelVersion>
-
-	<artifactId>keycloak-testsuite-pom</artifactId>
-    <packaging>pom</packaging>
-    <name>Keycloak TestSuite</name>
-	<description />
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>jaxrs-api</artifactId>
-                <version>${resteasy.latest.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-jaxrs</artifactId>
-                <version>${resteasy.latest.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-multipart-provider</artifactId>
-                <version>${resteasy.latest.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>resteasy-jackson-provider</artifactId>
-                <version>${resteasy.latest.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jboss.resteasy</groupId>
-                <artifactId>async-http-servlet-3.0</artifactId>
-                <version>${resteasy.latest.version}</version>
-                <scope>test</scope>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <modules>
-        <module>integration</module>
-        <module>proxy</module>
-        <module>tomcat6</module>
-        <module>tomcat7</module>
-        <module>tomcat8</module>
-        <module>jetty/jetty81</module>
-        <module>jetty/jetty92</module>
-        <module>jetty/jetty91</module>
-        <module>performance</module>
-        <!--<module>docker-cluster</module>-->
-    </modules>
-
-    <profiles>
-        <profile>
-            <id>jboss-release</id>
-            <modules>
-                <module>docker-cluster</module>
-            </modules>
-        </profile>
-    </profiles>
-        
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<artifactId>keycloak-parent</artifactId>
+		<groupId>org.keycloak</groupId>
+		<version>1.4.0.Final-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>keycloak-testsuite-pom</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak TestSuite</name>
+	<description />
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>jaxrs-api</artifactId>
+                <version>${resteasy.latest.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-jaxrs</artifactId>
+                <version>${resteasy.latest.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-multipart-provider</artifactId>
+                <version>${resteasy.latest.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>resteasy-jackson-provider</artifactId>
+                <version>${resteasy.latest.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.resteasy</groupId>
+                <artifactId>async-http-servlet-3.0</artifactId>
+                <version>${resteasy.latest.version}</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <modules>
+        <module>integration</module>
+        <module>proxy</module>
+        <module>tomcat6</module>
+        <module>tomcat7</module>
+        <module>tomcat8</module>
+        <module>jetty/jetty81</module>
+        <module>jetty/jetty92</module>
+        <module>jetty/jetty91</module>
+        <module>performance</module>
+        <!--<module>docker-cluster</module>-->
+    </modules>
+
+    <profiles>
+        <profile>
+            <id>jboss-release</id>
+            <modules>
+                <module>docker-cluster</module>
+            </modules>
+        </profile>
+    </profiles>
+        
+</project>

testsuite/proxy/pom.xml 986(+493 -493)

diff --git a/testsuite/proxy/pom.xml b/testsuite/proxy/pom.xml
index de6e1a0..e39de07 100755
--- a/testsuite/proxy/pom.xml
+++ b/testsuite/proxy/pom.xml
@@ -1,493 +1,493 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-security-proxy</artifactId>
-    <name>Keycloak Security Proxy TestSuite</name>
-    <properties>
-        <!--<tomcat.version>8.0.14</tomcat.version>-->
-        <tomcat.version>7.0.54</tomcat.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-admin-client</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-proxy-server</artifactId>
-       </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-tomcat7-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-catalina</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-util</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat.embed</groupId>
-           <artifactId>tomcat-embed-core</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-security-proxy</artifactId>
+    <name>Keycloak Security Proxy TestSuite</name>
+    <properties>
+        <!--<tomcat.version>8.0.14</tomcat.version>-->
+        <tomcat.version>7.0.54</tomcat.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-admin-client</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-proxy-server</artifactId>
+       </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-tomcat7-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-catalina</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-util</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat.embed</groupId>
+           <artifactId>tomcat-embed-core</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/proxy/src/test/resources/demorealm.json b/testsuite/proxy/src/test/resources/demorealm.json
index bb66dc8..544bc1a 100755
--- a/testsuite/proxy/src/test/resources/demorealm.json
+++ b/testsuite/proxy/src/test/resources/demorealm.json
@@ -1,71 +1,71 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "admin",
-            "enabled": true,
-            "email" : "admin.burke@redhat.com",
-            "firstName": "Admin",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user", "admin" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "adminUrl": "http://localhost:8080/customer-portal",
-            "baseUrl": "http://localhost:8080/customer-portal",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal/*",
-                "https://localhost:8443/customer-portal/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "admin",
+            "enabled": true,
+            "email" : "admin.burke@redhat.com",
+            "firstName": "Admin",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user", "admin" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "adminUrl": "http://localhost:8080/customer-portal",
+            "baseUrl": "http://localhost:8080/customer-portal",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal/*",
+                "https://localhost:8443/customer-portal/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/proxy/src/test/resources/keycloak.json b/testsuite/proxy/src/test/resources/keycloak.json
index e49233f..b27fa4b 100755
--- a/testsuite/proxy/src/test/resources/keycloak.json
+++ b/testsuite/proxy/src/test/resources/keycloak.json
@@ -1,11 +1,11 @@
-{
-    "realm": "demo",
-    "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "auth-server-url": "http://localhost:8081/auth",
-    "ssl-required" : "external",
-    "principal-attribute": "name",
-    "credentials": {
-        "secret": "password"
-    }
-}
+{
+    "realm": "demo",
+    "resource": "customer-portal",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "http://localhost:8081/auth",
+    "ssl-required" : "external",
+    "principal-attribute": "name",
+    "credentials": {
+        "secret": "password"
+    }
+}
diff --git a/testsuite/proxy/src/test/resources/proxy-config.json b/testsuite/proxy/src/test/resources/proxy-config.json
index 06c9eda..1de7d61 100755
--- a/testsuite/proxy/src/test/resources/proxy-config.json
+++ b/testsuite/proxy/src/test/resources/proxy-config.json
@@ -1,64 +1,64 @@
-{
-    "bind-address": "localhost",
-    "http-port": "8080",
-    "https-port": "8443",
-    "keystore": "classpath:ssl.jks",
-    "keystore-password": "password",
-    "key-password": "password",
-    "target-url": "http://localhost:8082",
-    "send-access-token": true,
-    "applications": [
-        {
-            "base-path": "/customer-portal",
-            "error-page": "/error.html",
-            "adapter-config": {
-                "realm": "demo",
-                "resource": "customer-portal",
-                "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-                "auth-server-url": "http://localhost:8081/auth",
-                "ssl-required" : "external",
-                "principal-attribute": "name",
-                "credentials": {
-                    "secret": "password"
-                }
-            }
-            ,
-            "constraints": [
-                {
-                    "pattern": "/users/*",
-                    "roles-allowed": [
-                        "user"
-                    ]
-                },
-                {
-                    "pattern": "/call-bearer/*",
-                    "roles-allowed": [
-                        "user"
-                    ]
-                },
-                {
-                    "pattern": "/bearer/*",
-                    "roles-allowed": [
-                        "user"
-                    ]
-                },
-                {
-                    "pattern": "/admins/*",
-                    "roles-allowed": [
-                        "admin"
-                    ]
-                },
-                {
-                    "pattern": "/users/permit",
-                    "permit": true
-                },
-                {
-                    "pattern": "/users/deny",
-                    "deny": true
-                }
-            ]
-        }
-    ]
-
-
+{
+    "bind-address": "localhost",
+    "http-port": "8080",
+    "https-port": "8443",
+    "keystore": "classpath:ssl.jks",
+    "keystore-password": "password",
+    "key-password": "password",
+    "target-url": "http://localhost:8082",
+    "send-access-token": true,
+    "applications": [
+        {
+            "base-path": "/customer-portal",
+            "error-page": "/error.html",
+            "adapter-config": {
+                "realm": "demo",
+                "resource": "customer-portal",
+                "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+                "auth-server-url": "http://localhost:8081/auth",
+                "ssl-required" : "external",
+                "principal-attribute": "name",
+                "credentials": {
+                    "secret": "password"
+                }
+            }
+            ,
+            "constraints": [
+                {
+                    "pattern": "/users/*",
+                    "roles-allowed": [
+                        "user"
+                    ]
+                },
+                {
+                    "pattern": "/call-bearer/*",
+                    "roles-allowed": [
+                        "user"
+                    ]
+                },
+                {
+                    "pattern": "/bearer/*",
+                    "roles-allowed": [
+                        "user"
+                    ]
+                },
+                {
+                    "pattern": "/admins/*",
+                    "roles-allowed": [
+                        "admin"
+                    ]
+                },
+                {
+                    "pattern": "/users/permit",
+                    "permit": true
+                },
+                {
+                    "pattern": "/users/deny",
+                    "deny": true
+                }
+            ]
+        }
+    ]
+
+
 }
\ No newline at end of file

testsuite/tomcat6/pom.xml 970(+485 -485)

diff --git a/testsuite/tomcat6/pom.xml b/testsuite/tomcat6/pom.xml
index 22a0d83..fe817e8 100755
--- a/testsuite/tomcat6/pom.xml
+++ b/testsuite/tomcat6/pom.xml
@@ -1,485 +1,485 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-tomcat6</artifactId>
-    <name>Keycloak Tomcat 6 Integration TestSuite</name>
-    <properties>
-        <tomcat.version>6.0.41</tomcat.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-tomcat6-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>catalina</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>coyote</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>jasper</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>junit</groupId>
-           <artifactId>junit</artifactId>
-       </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-tomcat6</artifactId>
+    <name>Keycloak Tomcat 6 Integration TestSuite</name>
+    <properties>
+        <tomcat.version>6.0.41</tomcat.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-tomcat6-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>catalina</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>coyote</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>jasper</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>junit</groupId>
+           <artifactId>junit</artifactId>
+       </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatServer.java b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatServer.java
index c18aeae..7b41a05 100755
--- a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatServer.java
+++ b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatServer.java
@@ -1,114 +1,114 @@
-package org.keycloak.testsuite;
-
-import org.apache.catalina.Engine;
-import org.apache.catalina.Host;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.startup.Embedded;
-import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TomcatServer {
-    private Embedded server;
-    private int port;
-    private boolean isRunning;
-
-    private static final Logger LOG = LoggerFactory.getLogger(TomcatServer.class);
-    private static final boolean isInfo = LOG.isInfoEnabled();
-    private final Host host;
-
-
-    /**
-     * Create a new Tomcat embedded server instance. Setup looks like:
-     * <pre><Server>
-     *    <Service>
-     *        <Connector />
-     *        <Engine&gt
-     *            <Host>
-     *                <Context />
-     *            </Host>
-     *        </Engine>
-     *    </Service>
-     * </Server></pre>
-     * <Server> & <Service> will be created automcatically. We need to hook the remaining to an {@link Embedded} instnace
-     *
-     * @param port         Port number to be used for the embedded Tomcat server
-     * @param appBase      Path to the Application files (for Maven based web apps, in general: <code>/src/main/</code>)
-     * @throws Exception
-     */
-    public TomcatServer(int port, String appBase) {
-
-        this.port = port;
-
-        server = new Embedded();
-        server.setName("TomcatEmbeddedServer");
-        server.setCatalinaBase(TomcatTest.getBaseDirectory());
-
-        host = server.createHost("localhost", appBase);
-        host.setAutoDeploy(false);
-
-      }
-
-    public void deploy(String contextPath, String appDir) {
-        if (contextPath == null) {
-            throw new IllegalArgumentException("Context path or appbase should not be null");
-        }
-        if (!contextPath.startsWith("/")) {
-            contextPath = "/" + contextPath;
-        }
-        StandardContext rootContext = (StandardContext) server.createContext(contextPath, appDir);
-        KeycloakAuthenticatorValve valve = new KeycloakAuthenticatorValve();
-        rootContext.addValve(valve);
-        //rootContext.addLifecycleListener(valve);
-        rootContext.setDefaultWebXml("web.xml");
-        host.addChild(rootContext);
-    }
-
-    /**
-     * Start the tomcat embedded server
-     */
-    public void start() throws LifecycleException {
-        if (isRunning) {
-            LOG.warn("Tomcat server is already running @ port={}; ignoring the start", port);
-            return;
-        }
-
-        Engine engine = server.createEngine();
-        engine.setDefaultHost(host.getName());
-        engine.setName("TomcatEngine");
-        engine.addChild(host);
-
-        server.addEngine(engine);
-
-        Connector connector = server.createConnector(host.getName(), port, false);
-        server.addConnector(connector);
-
-        if (isInfo) LOG.info("Starting the Tomcat server @ port={}", port);
-
-        server.setAwait(true);
-        server.start();
-        isRunning = true;
-    }
-
-    /**
-     * Stop the tomcat embedded server
-     */
-    public void stop() throws LifecycleException {
-        if (!isRunning) {
-            LOG.warn("Tomcat server is not running @ port={}", port);
-            return;
-        }
-
-        if (isInfo) LOG.info("Stopping the Tomcat server");
-
-        server.stop();
-        isRunning = false;
-    }
-
-    public boolean isRunning() {
-        return isRunning;
-    }
-
+package org.keycloak.testsuite;
+
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.startup.Embedded;
+import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TomcatServer {
+    private Embedded server;
+    private int port;
+    private boolean isRunning;
+
+    private static final Logger LOG = LoggerFactory.getLogger(TomcatServer.class);
+    private static final boolean isInfo = LOG.isInfoEnabled();
+    private final Host host;
+
+
+    /**
+     * Create a new Tomcat embedded server instance. Setup looks like:
+     * <pre><Server>
+     *    <Service>
+     *        <Connector />
+     *        <Engine&gt
+     *            <Host>
+     *                <Context />
+     *            </Host>
+     *        </Engine>
+     *    </Service>
+     * </Server></pre>
+     * <Server> & <Service> will be created automcatically. We need to hook the remaining to an {@link Embedded} instnace
+     *
+     * @param port         Port number to be used for the embedded Tomcat server
+     * @param appBase      Path to the Application files (for Maven based web apps, in general: <code>/src/main/</code>)
+     * @throws Exception
+     */
+    public TomcatServer(int port, String appBase) {
+
+        this.port = port;
+
+        server = new Embedded();
+        server.setName("TomcatEmbeddedServer");
+        server.setCatalinaBase(TomcatTest.getBaseDirectory());
+
+        host = server.createHost("localhost", appBase);
+        host.setAutoDeploy(false);
+
+      }
+
+    public void deploy(String contextPath, String appDir) {
+        if (contextPath == null) {
+            throw new IllegalArgumentException("Context path or appbase should not be null");
+        }
+        if (!contextPath.startsWith("/")) {
+            contextPath = "/" + contextPath;
+        }
+        StandardContext rootContext = (StandardContext) server.createContext(contextPath, appDir);
+        KeycloakAuthenticatorValve valve = new KeycloakAuthenticatorValve();
+        rootContext.addValve(valve);
+        //rootContext.addLifecycleListener(valve);
+        rootContext.setDefaultWebXml("web.xml");
+        host.addChild(rootContext);
+    }
+
+    /**
+     * Start the tomcat embedded server
+     */
+    public void start() throws LifecycleException {
+        if (isRunning) {
+            LOG.warn("Tomcat server is already running @ port={}; ignoring the start", port);
+            return;
+        }
+
+        Engine engine = server.createEngine();
+        engine.setDefaultHost(host.getName());
+        engine.setName("TomcatEngine");
+        engine.addChild(host);
+
+        server.addEngine(engine);
+
+        Connector connector = server.createConnector(host.getName(), port, false);
+        server.addConnector(connector);
+
+        if (isInfo) LOG.info("Starting the Tomcat server @ port={}", port);
+
+        server.setAwait(true);
+        server.start();
+        isRunning = true;
+    }
+
+    /**
+     * Stop the tomcat embedded server
+     */
+    public void stop() throws LifecycleException {
+        if (!isRunning) {
+            LOG.warn("Tomcat server is not running @ port={}", port);
+            return;
+        }
+
+        if (isInfo) LOG.info("Stopping the Tomcat server");
+
+        server.stop();
+        isRunning = false;
+    }
+
+    public boolean isRunning() {
+        return isRunning;
+    }
+
 }
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/customer-db/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/customer-db/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/customer-db/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/customer-db/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
index 5066a55..aa10ca2 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-db-error-page">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-db-error-page">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/demorealm.json b/testsuite/tomcat6/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/input-portal/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/input-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/input-portal/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/input-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/product-portal/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/product-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/product-portal/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/product-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/secure-portal/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/session-portal/META-INF/context.xml b/testsuite/tomcat6/src/test/resources/adapter-test/session-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/session-portal/META-INF/context.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/session-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file

testsuite/tomcat7/pom.xml 978(+489 -489)

diff --git a/testsuite/tomcat7/pom.xml b/testsuite/tomcat7/pom.xml
index 8dc36b4..c3bc09e 100755
--- a/testsuite/tomcat7/pom.xml
+++ b/testsuite/tomcat7/pom.xml
@@ -1,489 +1,489 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-tomcat7</artifactId>
-    <name>Keycloak Tomcat 7 Integration TestSuite</name>
-    <properties>
-        <!--<tomcat.version>8.0.14</tomcat.version>-->
-        <tomcat.version>7.0.59</tomcat.version>
-    </properties>
-    <description />
-
-   <dependencies>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-catalina</artifactId>
-           <version>7.0.59</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-util</artifactId>
-           <version>7.0.59</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat.embed</groupId>
-           <artifactId>tomcat-embed-core</artifactId>
-           <version>7.0.59</version>
-       </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-tomcat7-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-tomcat7</artifactId>
+    <name>Keycloak Tomcat 7 Integration TestSuite</name>
+    <properties>
+        <!--<tomcat.version>8.0.14</tomcat.version>-->
+        <tomcat.version>7.0.59</tomcat.version>
+    </properties>
+    <description />
+
+   <dependencies>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-catalina</artifactId>
+           <version>7.0.59</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-util</artifactId>
+           <version>7.0.59</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat.embed</groupId>
+           <artifactId>tomcat-embed-core</artifactId>
+           <version>7.0.59</version>
+       </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-tomcat7-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/customer-db/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/customer-db/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/customer-db/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/customer-db/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
index 5066a55..aa10ca2 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-db-error-page">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-db-error-page">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/demorealm.json b/testsuite/tomcat7/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/input-portal/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/input-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/input-portal/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/input-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/product-portal/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/product-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/product-portal/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/product-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/secure-portal/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/session-portal/META-INF/context.xml b/testsuite/tomcat7/src/test/resources/adapter-test/session-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/session-portal/META-INF/context.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/session-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file

testsuite/tomcat8/pom.xml 976(+488 -488)

diff --git a/testsuite/tomcat8/pom.xml b/testsuite/tomcat8/pom.xml
index bf4c39a..a7cddbd 100755
--- a/testsuite/tomcat8/pom.xml
+++ b/testsuite/tomcat8/pom.xml
@@ -1,488 +1,488 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-tomcat8</artifactId>
-    <name>Keycloak Tomcat 8 Integration TestSuite</name>
-    <properties>
-        <tomcat.version>8.0.14</tomcat.version>
-    </properties>
-    <description />
-
-   <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-kerberos-federation</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-undertow-adapter</artifactId>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-tomcat8-adapter</artifactId>
-       </dependency>
-       <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.infinispan</groupId>
-            <artifactId>infinispan-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.wildfly</groupId>
-            <artifactId>wildfly-undertow</artifactId>
-            <version>${wildfly.version}</version>
-            <scope>test</scope>
-        </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <scope>test</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.keycloak</groupId>
-           <artifactId>keycloak-testsuite-integration</artifactId>
-           <type>test-jar</type>
-           <scope>test</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-catalina</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat</groupId>
-           <artifactId>tomcat-util</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-       <dependency>
-           <groupId>org.apache.tomcat.embed</groupId>
-           <artifactId>tomcat-embed-core</artifactId>
-           <version>${tomcat.version}</version>
-       </dependency>
-
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.2</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <profile>
-            <id>infinispan</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
-                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
-                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <profile>
-            <id>clean-jpa</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.liquibase</groupId>
-                        <artifactId>liquibase-maven-plugin</artifactId>
-                        <configuration>
-                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
-
-                            <url>${keycloak.connectionsJpa.url}</url>
-                            <driver>${keycloak.connectionsJpa.driver}</driver>
-                            <username>${keycloak.connectionsJpa.user}</username>
-                            <password>${keycloak.connectionsJpa.password}</password>
-
-                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-jpa</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>dropAll</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-tomcat8</artifactId>
+    <name>Keycloak Tomcat 8 Integration TestSuite</name>
+    <properties>
+        <tomcat.version>8.0.14</tomcat.version>
+    </properties>
+    <description />
+
+   <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-kerberos-federation</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-undertow-adapter</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-tomcat8-adapter</artifactId>
+       </dependency>
+       <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-undertow</artifactId>
+            <version>${wildfly.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <scope>test</scope>
+       </dependency>
+       <dependency>
+           <groupId>org.keycloak</groupId>
+           <artifactId>keycloak-testsuite-integration</artifactId>
+           <type>test-jar</type>
+           <scope>test</scope>
+       </dependency>
+
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-catalina</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat</groupId>
+           <artifactId>tomcat-util</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.tomcat.embed</groupId>
+           <artifactId>tomcat-embed-core</artifactId>
+           <version>${tomcat.version}</version>
+       </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testsuite.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.eventStore.provider>jpa</keycloak.eventStore.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <profile>
+            <id>infinispan</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.cache.provider>infinispan</keycloak.realm.cache.provider>
+                                <keycloak.user.cache.provider>infinispan</keycloak.user.cache.provider>
+                                <keycloak.userSessions.provider>infinispan</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
+            <id>clean-jpa</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.liquibase</groupId>
+                        <artifactId>liquibase-maven-plugin</artifactId>
+                        <configuration>
+                            <changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
+
+                            <url>${keycloak.connectionsJpa.url}</url>
+                            <driver>${keycloak.connectionsJpa.driver}</driver>
+                            <username>${keycloak.connectionsJpa.user}</username>
+                            <password>${keycloak.connectionsJpa.password}</password>
+
+                            <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>clean-jpa</id>
+                                <phase>clean</phase>
+                                <goals>
+                                    <goal>dropAll</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/customer-db/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/customer-db/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/customer-db/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/customer-db/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
index 5066a55..aa10ca2 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/customer-db-error-page/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-db-error-page">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-db-error-page">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/demorealm.json b/testsuite/tomcat8/src/test/resources/adapter-test/demorealm.json
index a21838e..a0ddce4 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/demorealm.json
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/demorealm.json
@@ -1,163 +1,163 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        },
-        {
-            "username" : "mposolda",
-            "enabled": true,
-            "email" : "mposolda@redhat.com",
-            "firstName": "Marek",
-            "lastName": "Posolda",
-            "credentials" : [
-                { "type" : "password",
-                  "value" : "password" }
-            ],
-            "realmRoles": [ "user" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "scopeMappings": [
-        {
-            "client": "third-party",
-            "roles": ["user"]
-        },
-        {
-            "client": "customer-portal",
-            "roles": ["user"]
-        },
-        {
-            "client": "product-portal",
-            "roles": ["user"]
-        }
-
-    ],
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/customer-portal",
-            "baseUrl": "http://localhost:8082/customer-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-cookie-portal",
-            "enabled": true,
-            "baseUrl": "http://localhost:8082/customer-cookie-portal",
-            "redirectUris": [
-                "http://localhost:8082/customer-cookie-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "customer-portal-js",
-            "enabled": true,
-            "publicClient": true,
-            "adminUrl": "http://localhost:8082/customer-portal-js",
-            "baseUrl": "http://localhost:8082/customer-portal-js",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal-js/*"
-            ]
-        },
-        {
-            "name": "customer-portal-cli",
-            "enabled": true,
-            "publicClient": true,
-            "redirectUris": [
-                "urn:ietf:wg:oauth:2.0:oob",
-                "http://localhost"
-            ]
-        },
-        {
-            "name": "product-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/product-portal",
-            "baseUrl": "http://localhost:8082/product-portal",
-            "redirectUris": [
-                "http://localhost:8082/product-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "secure-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/secure-portal",
-            "baseUrl": "http://localhost:8082/secure-portal",
-            "redirectUris": [
-                "http://localhost:8082/secure-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "session-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/session-portal",
-            "baseUrl": "http://localhost:8082/session-portal",
-            "redirectUris": [
-                "http://localhost:8082/session-portal/*"
-            ],
-            "secret": "password"
-        },
-        {
-            "name": "input-portal",
-            "enabled": true,
-            "adminUrl": "http://localhost:8082/input-portal",
-            "baseUrl": "http://localhost:8082/input-portal",
-            "redirectUris": [
-                "http://localhost:8082/input-portal/*"
-            ],
-            "secret": "password"
-        }
-    ],
-    "oauthClients": [
-        {
-            "name": "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8082/oauth-client/*",
-                "http://localhost:8082/oauth-client-cdi/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        },
+        {
+            "username" : "mposolda",
+            "enabled": true,
+            "email" : "mposolda@redhat.com",
+            "firstName": "Marek",
+            "lastName": "Posolda",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "third-party",
+            "roles": ["user"]
+        },
+        {
+            "client": "customer-portal",
+            "roles": ["user"]
+        },
+        {
+            "client": "product-portal",
+            "roles": ["user"]
+        }
+
+    ],
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/customer-portal",
+            "baseUrl": "http://localhost:8082/customer-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-cookie-portal",
+            "enabled": true,
+            "baseUrl": "http://localhost:8082/customer-cookie-portal",
+            "redirectUris": [
+                "http://localhost:8082/customer-cookie-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "customer-portal-js",
+            "enabled": true,
+            "publicClient": true,
+            "adminUrl": "http://localhost:8082/customer-portal-js",
+            "baseUrl": "http://localhost:8082/customer-portal-js",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal-js/*"
+            ]
+        },
+        {
+            "name": "customer-portal-cli",
+            "enabled": true,
+            "publicClient": true,
+            "redirectUris": [
+                "urn:ietf:wg:oauth:2.0:oob",
+                "http://localhost"
+            ]
+        },
+        {
+            "name": "product-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/product-portal",
+            "baseUrl": "http://localhost:8082/product-portal",
+            "redirectUris": [
+                "http://localhost:8082/product-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "secure-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/secure-portal",
+            "baseUrl": "http://localhost:8082/secure-portal",
+            "redirectUris": [
+                "http://localhost:8082/secure-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "session-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/session-portal",
+            "baseUrl": "http://localhost:8082/session-portal",
+            "redirectUris": [
+                "http://localhost:8082/session-portal/*"
+            ],
+            "secret": "password"
+        },
+        {
+            "name": "input-portal",
+            "enabled": true,
+            "adminUrl": "http://localhost:8082/input-portal",
+            "baseUrl": "http://localhost:8082/input-portal",
+            "redirectUris": [
+                "http://localhost:8082/input-portal/*"
+            ],
+            "secret": "password"
+        }
+    ],
+    "oauthClients": [
+        {
+            "name": "third-party",
+            "enabled": true,
+            "redirectUris": [
+                "http://localhost:8082/oauth-client/*",
+                "http://localhost:8082/oauth-client-cdi/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/input-portal/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/input-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/input-portal/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/input-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/product-portal/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/product-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/product-portal/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/product-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/secure-portal/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/secure-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/session-portal/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/adapter-test/session-portal/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/session-portal/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/session-portal/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/tomcat-test/demorealm.json b/testsuite/tomcat8/src/test/resources/tomcat-test/demorealm.json
index 0efd923..d122c19 100755
--- a/testsuite/tomcat8/src/test/resources/tomcat-test/demorealm.json
+++ b/testsuite/tomcat8/src/test/resources/tomcat-test/demorealm.json
@@ -1,55 +1,55 @@
-{
-    "id": "demo",
-    "realm": "demo",
-    "enabled": true,
-    "accessTokenLifespan": 3000,
-    "accessCodeLifespan": 10,
-    "accessCodeLifespanUserAction": 6000,
-    "sslRequired": "external",
-    "registrationAllowed": false,
-    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
-    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "requiredCredentials": [ "password" ],
-    "users" : [
-        {
-            "username" : "bburke@redhat.com",
-            "enabled": true,
-            "email" : "bburke@redhat.com",
-            "firstName": "Bill",
-            "lastName": "Burke",
-            "credentials" : [
-                { "type" : "password",
-                    "value" : "password" }
-            ],
-            "realmRoles": [ "user", "admin" ],
-            "applicationRoles": {
-                "account": [ "manage-account" ]
-            }
-        }
-    ],
-    "roles" : {
-        "realm" : [
-            {
-                "name": "user",
-                "description": "User privileges"
-            },
-            {
-                "name": "admin",
-                "description": "Administrator privileges"
-            }
-        ]
-    },
-    "applications": [
-        {
-            "name": "customer-portal",
-            "enabled": true,
-            "fullScopeAllowed": true,
-            "adminUrl": "http://localhost:8080/customer-portal",
-            "baseUrl": "http://localhost:8080/customer-portal",
-            "redirectUris": [
-                "http://localhost:8080/customer-portal/*"
-            ],
-            "secret": "password"
-        }
-    ]
-}
+{
+    "id": "demo",
+    "realm": "demo",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user", "admin" ],
+            "applicationRoles": {
+                "account": [ "manage-account" ]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "applications": [
+        {
+            "name": "customer-portal",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "adminUrl": "http://localhost:8080/customer-portal",
+            "baseUrl": "http://localhost:8080/customer-portal",
+            "redirectUris": [
+                "http://localhost:8080/customer-portal/*"
+            ],
+            "secret": "password"
+        }
+    ]
+}
diff --git a/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/META-INF/context.xml b/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/META-INF/context.xml
index 6f24639..8e2c70d 100755
--- a/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/META-INF/context.xml
+++ b/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/META-INF/context.xml
@@ -1,3 +1,3 @@
-<Context path="/customer-portal">
-    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
+<Context path="/customer-portal">
+    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
 </Context>
\ No newline at end of file
diff --git a/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/WEB-INF/keycloak.json b/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/WEB-INF/keycloak.json
index 4e2fe1e..d9caa3f 100755
--- a/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/WEB-INF/keycloak.json
+++ b/testsuite/tomcat8/src/test/resources/tomcat-test/webapp/WEB-INF/keycloak.json
@@ -1,10 +1,10 @@
-{
-    "realm": "demo",
-    "resource": "customer-portal",
-    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
-    "auth-server-url": "http://localhost:8081/auth",
-    "ssl-required" : "external",
-    "credentials": {
-        "secret": "password"
-    }
-}
+{
+    "realm": "demo",
+    "resource": "customer-portal",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "http://localhost:8081/auth",
+    "ssl-required" : "external",
+    "credentials": {
+        "secret": "password"
+    }
+}

timer/api/pom.xml 54(+27 -27)

diff --git a/timer/api/pom.xml b/timer/api/pom.xml
index 23d6470..f6de546 100755
--- a/timer/api/pom.xml
+++ b/timer/api/pom.xml
@@ -1,27 +1,27 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-timer-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-timer-api</artifactId>
-    <name>Keycloak Timer API</name>
-    <description/>
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-timer-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-timer-api</artifactId>
+    <name>Keycloak Timer API</name>
+    <description/>
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>

timer/basic/pom.xml 76(+38 -38)

diff --git a/timer/basic/pom.xml b/timer/basic/pom.xml
index 1017fce..5850230 100755
--- a/timer/basic/pom.xml
+++ b/timer/basic/pom.xml
@@ -1,38 +1,38 @@
-<?xml version="1.0"?>
-<project>
-    <parent>
-        <artifactId>keycloak-timer-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-timer-basic</artifactId>
-    <name>Keycloak Timer Basic Provider</name>
-    <description/>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-timer-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
+<?xml version="1.0"?>
+<project>
+    <parent>
+        <artifactId>keycloak-timer-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-timer-basic</artifactId>
+    <name>Keycloak Timer Basic Provider</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-timer-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>

timer/pom.xml 44(+22 -22)

diff --git a/timer/pom.xml b/timer/pom.xml
index de37631..85a540e 100755
--- a/timer/pom.xml
+++ b/timer/pom.xml
@@ -1,22 +1,22 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-parent</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.4.0.Final-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <name>Keycloak Timer Parent</name>
-    <description/>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.keycloak</groupId>
-    <artifactId>keycloak-timer-parent</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>api</module>
-        <module>basic</module>
-    </modules>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.4.0.Final-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <name>Keycloak Timer Parent</name>
+    <description/>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.keycloak</groupId>
+    <artifactId>keycloak-timer-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>api</module>
+        <module>basic</module>
+    </modules>
+</project>