keycloak-memoizeit

Changes

.travis.yml 9(+9 -0)

Details

.travis.yml 9(+9 -0)

diff --git a/.travis.yml b/.travis.yml
index 8275e00..8146d6e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,8 @@
 language: java
 
+jdk:
+  - oraclejdk8
+
 cache:
     directories:
         - $HOME/.m2
@@ -7,4 +10,10 @@ cache:
 before_cache:
   - rm -rf $HOME/.m2/repository/org/keycloak
 
+install: mvn install -Pdistribution -DskipTests=true -B -V
+
+script:
+  - mvn test -B
+  - mvn -file testsuite/integration-arquillian test -B
+
 sudo: false
diff --git a/core/src/main/java/org/keycloak/representations/idm/RequiredActionProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RequiredActionProviderRepresentation.java
index e145818..d94fe5b 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RequiredActionProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RequiredActionProviderRepresentation.java
@@ -1,73 +1,73 @@
-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 RequiredActionProviderRepresentation {
-
-    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 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.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 RequiredActionProviderRepresentation {
+
+    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 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/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml
index 094e426..59ae243 100755
--- a/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml
+++ b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml
@@ -27,4 +27,10 @@
             <outputDirectory>modules</outputDirectory>
         </fileSet>
     </fileSets>
+    <files>
+        <file>
+             <source>../../shared-cli/adapter-install.cli</source>
+             <outputDirectory>bin</outputDirectory>
+        </file>
+    </files>
 </assembly>
diff --git a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml
index 4e29b1b..0f6c462 100755
--- a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml
+++ b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml
@@ -27,4 +27,10 @@
             <outputDirectory>modules/system/layers/base</outputDirectory>
         </fileSet>
     </fileSets>
+    <files>
+        <file>
+             <source>../../shared-cli/adapter-install.cli</source>
+             <outputDirectory>bin</outputDirectory>
+        </file>
+    </files>
 </assembly>
diff --git a/distribution/adapters/shared-cli/adapter-install.cli b/distribution/adapters/shared-cli/adapter-install.cli
new file mode 100644
index 0000000..b4a396b
--- /dev/null
+++ b/distribution/adapters/shared-cli/adapter-install.cli
@@ -0,0 +1,4 @@
+/subsystem=security/security-domain=keycloak/:add
+/subsystem=security/security-domain=keycloak/authentication=classic/:add(login-modules=[{ "code" => "org.keycloak.adapters.jboss.KeycloakLoginModule","flag" => "required"}])
+/extension=org.keycloak.keycloak-adapter-subsystem/:add(module=org.keycloak.keycloak-adapter-subsystem)
+/subsystem=keycloak:add
\ No newline at end of file
diff --git a/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml b/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
index 3f5d887..da4e127 100755
--- a/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
+++ b/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
@@ -28,4 +28,10 @@
             <outputDirectory>modules/system/layers/base</outputDirectory>
         </fileSet>
     </fileSets>
+    <files>
+        <file>
+             <source>../../shared-cli/adapter-install.cli</source>
+             <outputDirectory>bin</outputDirectory>
+        </file>
+    </files>
 </assembly>
diff --git a/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml b/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml
index e81d4e4..764b76d 100755
--- a/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml
+++ b/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml
@@ -27,4 +27,10 @@
             <outputDirectory>modules/system/layers/base</outputDirectory>
         </fileSet>
     </fileSets>
+    <files>
+        <file>
+             <source>../../shared-cli/adapter-install.cli</source>
+             <outputDirectory>bin</outputDirectory>
+        </file>
+    </files>
 </assembly>
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
index 1ead8b9..1d978dd 100755
--- a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
@@ -40,6 +40,14 @@
             <source>src/main/providers/README.txt</source>
             <outputDirectory>standalone/configuration/providers</outputDirectory>
         </file>
+        <file>
+            <source>cli/keycloak-prepare.cli</source>
+            <outputDirectory>bin</outputDirectory>
+        </file>
+        <file>
+            <source>cli/keycloak-install.cli</source>
+            <outputDirectory>bin</outputDirectory>
+        </file>
     </files>
 
 </assembly>
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-install.cli b/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-install.cli
new file mode 100644
index 0000000..cc59431
--- /dev/null
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-install.cli
@@ -0,0 +1,2 @@
+/extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
+/subsystem=keycloak-server:add(web-context=auth)
\ No newline at end of file
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-prepare.cli b/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-prepare.cli
new file mode 100644
index 0000000..000cbfa
--- /dev/null
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/cli/keycloak-prepare.cli
@@ -0,0 +1,2 @@
+/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true,enabled=true)
+/subsystem=logging/logger=org.jboss.resteasy.resteasy_jaxrs.i18n/:add(level=ERROR)
\ No newline at end of file
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone.xsl b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone.xsl
index 69ea1c1..519b4a7 100755
--- a/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone.xsl
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone.xsl
@@ -44,22 +44,6 @@
         </xsl:copy>
     </xsl:template>
 
-    <xsl:template match="//sec:security-domains">
-        <xsl:copy>
-            <xsl:apply-templates select="node()[name(.)='security-domain']"/>
-            <security-domain name="keycloak">
-                <authentication>
-                    <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule" flag="required"/>
-                </authentication>
-            </security-domain>
-            <security-domain name="sp" cache-type="default">
-                <authentication>
-                    <login-module code="org.picketlink.identity.federation.bindings.wildfly.SAML2LoginModule" flag="required"/>
-                </authentication>
-            </security-domain>
-        </xsl:copy>
-    </xsl:template>
-
     <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $log)]">
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
diff --git a/distribution/server-overlay/wf9-server-overlay/assembly.xml b/distribution/server-overlay/wf9-server-overlay/assembly.xml
index 4d87e69..e7fcb1b 100755
--- a/distribution/server-overlay/wf9-server-overlay/assembly.xml
+++ b/distribution/server-overlay/wf9-server-overlay/assembly.xml
@@ -62,6 +62,10 @@
             <source>${project.build.directory}/unpacked/keycloak-${project.version}/standalone/configuration/keycloak-server.json</source>
             <outputDirectory>standalone/configuration</outputDirectory>
         </file>
+        <file>
+            <source>cli/keycloak-install.cli</source>
+            <outputDirectory>bin</outputDirectory>
+        </file>
     </files>
 
 </assembly>
diff --git a/distribution/server-overlay/wf9-server-overlay/cli/keycloak-install.cli b/distribution/server-overlay/wf9-server-overlay/cli/keycloak-install.cli
new file mode 100644
index 0000000..ac5ca0b
--- /dev/null
+++ b/distribution/server-overlay/wf9-server-overlay/cli/keycloak-install.cli
@@ -0,0 +1,3 @@
+/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true)
+/extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
+/subsystem=keycloak-server:add(web-context=auth)
\ 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 52877de..9e2d4a1 100755
--- a/docbook/reference/en/en-US/modules/jboss-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jboss-adapter.xml
@@ -49,6 +49,15 @@ $ unzip keycloak-as7-adapter-dist.zip
         <literal>domain.xml</literal> or <literal>standalone.xml</literal>.
     </para>
     <para>
+        There is a CLI script that will help you modify your server configuration.  Start the server and run the script 
+        from the server's bin directory:
+<programlisting>
+$ cd $JBOSS_HOME/bin
+$ jboss-cli.sh -c --file=adapter-install.cli
+</programlisting>
+        The script will add the extension, subsystem, and optional security-domain as described below.
+    </para>
+    <para>
 <programlisting><![CDATA[
 <server xmlns="urn:jboss:domain:1.4">
 
@@ -65,8 +74,7 @@ $ unzip keycloak-as7-adapter-dist.zip
 </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
+            The keycloak 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>
diff --git a/docbook/reference/en/en-US/modules/server-installation.xml b/docbook/reference/en/en-US/modules/server-installation.xml
index 9584852..6b39bf6 100755
--- a/docbook/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/reference/en/en-US/modules/server-installation.xml
@@ -49,9 +49,9 @@
                 <literal>keycloak-overlay-&project.version;.zip</literal> or <literal>keycloak-overlay-&project.version;.tar.gz</literal>.
                 Once downloaded extract into the root directory of your WildFly installation. To start WildFly with Keycloak
                 run:
-                <programlisting>keycloak-&project.version;/bin/standalone.sh --server-config=standalone-keycloak.xml</programlisting>
+                <programlisting>&lt;WILDFLY_HOME&gt;/bin/standalone.sh --server-config=standalone-keycloak.xml</programlisting>
                 or:
-                <programlisting>keycloak-&project.version;/bin/standalone.bat --server-config=standalone-keycloak.xml</programlisting>
+                <programlisting>&lt;WILDFLY_HOME&gt;/bin/standalone.bat --server-config=standalone-keycloak.xml</programlisting>
             </para>
             <para>
                 Once the server is started log into the admin console at
@@ -60,15 +60,9 @@
                 enter in a new password.
             </para>
             <para>
-                To add Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) open
-                <literal>standalone/configuration/standalone-keycloak.xml</literal> and the configuration you want to add it
-                to, for example <literal>standalone/configuration/standalone.xml</literal>. From <literal>standalone-keycloak.xml</literal>
-                you need to copy 3 elements:
-                <itemizedlist>
-                    <listitem><literal>&lt;extension module="org.keycloak.keycloak-server-subsystem"/&gt;</literal></listitem>
-                    <listitem><literal>&lt;datasource jndi-name="java:jboss/datasources/KeycloakDS" ...&gt;</literal></listitem>
-                    <listitem><literal>&lt;subsystem xmlns="urn:jboss:domain:keycloak-server:1.1" ...&gt;</literal></listitem>
-                </itemizedlist>
+                To add Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) start the server with
+                the desired server-config.  Then execute the following CLI script:
+                <programlisting>&lt;WILDFLY_HOME&gt;/bin/jboss-cli.sh -c --file=keycloak-install.cli</programlisting>
             </para>
         </section>
         <section>
@@ -76,6 +70,19 @@
             <para>
                 Same procedure as WildFly 9.0.0.Final, but download <literal>keycloak-overlay-eap6-&project.version;.zip</literal> or <literal>keycloak-overlay-eap6-&project.version;.tar.gz</literal>.
             </para>
+            <para>
+                However, for EAP, adding Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) requires two CLI scripts. Start the server with
+                the desired server-config.  Then execute the following CLI scripts with a restart in between:
+                <orderedlist>
+                    <listitem>
+                        <programlisting>&lt;EAP_HOME&gt;/bin/jboss-cli.sh -c --file=keycloak-prepare.cli</programlisting>
+                    </listitem>
+                    <listitem>Restart the server with the same server-config.</listitem>
+                    <listitem>
+                        <programlisting>&lt;EAP_HOME&gt;/bin/jboss-cli.sh -c --file=keycloak-install.cli</programlisting>
+                    </listitem>
+                </orderedlist>
+            </para>
         </section>
         <section>
             <title id="demo_install">Install Development Bundle</title>
diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java
index 29433ef..60d413c 100644
--- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java
+++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/AdapterDeploymentContextBean.java
@@ -9,30 +9,48 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.core.io.Resource;
 
-import java.io.InputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
 
 /**
  * Bean holding the {@link KeycloakDeployment} and {@link AdapterDeploymentContext} for this
  * Spring application context. The Keycloak deployment is loaded from the required
- * <code>WEB-INF/keycloak.json</code> file generated by Keycloak.
+ * <code>keycloak.json</code> resource file.
  *
  * @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
  * @version $Revision: 1 $
  */
 public class AdapterDeploymentContextBean implements ApplicationContextAware, InitializingBean {
 
+    private static final String KEYCLOAK_CONFIG_FILE = "keycloak.json";
+    private static final String KEYCLOAK_CONFIG_WEB_RESOURCE = "WEB-INF/" + KEYCLOAK_CONFIG_FILE;
+    private static final String KEYCLOAK_CONFIG_CLASSPATH_RESOURCE = "classpath:" + KEYCLOAK_CONFIG_FILE;
+
     private ApplicationContext applicationContext;
     private AdapterDeploymentContext deploymentContext;
     private KeycloakDeployment deployment;
 
     @Override
     public void afterPropertiesSet() throws Exception {
-        Resource resource = applicationContext.getResource("WEB-INF/keycloak.json");
-        InputStream is = resource.getInputStream();
-        this.deployment = KeycloakDeploymentBuilder.build(is);
+        this.deployment = loadKeycloakDeployment();
         this.deploymentContext = new AdapterDeploymentContext(deployment);
     }
 
+    private KeycloakDeployment loadKeycloakDeployment() throws IOException {
+
+        Resource resource = applicationContext.getResource(KEYCLOAK_CONFIG_WEB_RESOURCE);
+
+        if (!resource.isReadable()) {
+            resource=  applicationContext.getResource(KEYCLOAK_CONFIG_CLASSPATH_RESOURCE);
+        }
+
+        if (!resource.isReadable()) {
+            throw new FileNotFoundException(String.format("Unable to locate Keycloak from %s or %s", KEYCLOAK_CONFIG_WEB_RESOURCE, KEYCLOAK_CONFIG_CLASSPATH_RESOURCE));
+        }
+
+        return KeycloakDeploymentBuilder.build(resource.getInputStream());
+    }
+
     /**
      * Returns the Keycloak {@link AdapterDeploymentContext} for this application context.
      *
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 79d20d5..55ddb9b 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -623,6 +623,7 @@ public class LoginActionsService {
         if (clientSession.getAction().equals(ClientSessionModel.Action.RECOVER_PASSWORD.name())) {
             String actionCookieValue = getActionCookie();
             if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
+                session.sessions().removeClientSession(realm, clientSession);
                 return session.getProvider(LoginFormsProvider.class)
                         .setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED)
                         .createInfoPage();
@@ -657,6 +658,7 @@ public class LoginActionsService {
 
             String actionCookieValue = getActionCookie();
             if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
+                session.sessions().removeClientSession(realm, clientSession);
                 return session.getProvider(LoginFormsProvider.class)
                         .setSuccess(Messages.EMAIL_VERIFIED)
                         .createInfoPage();
diff --git a/services/src/main/java/org/keycloak/utils/CredentialHelper.java b/services/src/main/java/org/keycloak/utils/CredentialHelper.java
index c40656b..9b3af31 100755
--- a/services/src/main/java/org/keycloak/utils/CredentialHelper.java
+++ b/services/src/main/java/org/keycloak/utils/CredentialHelper.java
@@ -1,58 +1,58 @@
-package org.keycloak.utils;
-
-import org.keycloak.authentication.Authenticator;
-import org.keycloak.authentication.AuthenticatorFactory;
-import org.keycloak.authentication.ConfigurableAuthenticatorFactory;
-import org.keycloak.authentication.FormAction;
-import org.keycloak.authentication.FormActionFactory;
-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.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.representations.idm.CredentialRepresentation;
-
-/**
- * used to set an execution a state based on type.
- *
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CredentialHelper {
-
-    public static void setRequiredCredential(KeycloakSession session, String type, RealmModel realm) {
-        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.REQUIRED;
-        authenticationRequirement(session, realm, type, requirement);
-    }
-
-    public static void setAlternativeCredential(KeycloakSession session, String type, RealmModel realm) {
-        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
-        authenticationRequirement(session, realm, type, requirement);
-    }
-
-    public static void authenticationRequirement(KeycloakSession session, RealmModel realm, String type, AuthenticationExecutionModel.Requirement requirement) {
-        for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
-            for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) {
-                String providerId = execution.getAuthenticator();
-                ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, providerId);
-                if (factory == null) continue;
-                if (type.equals(factory.getReferenceCategory())) {
-                    execution.setRequirement(requirement);
-                    realm.updateAuthenticatorExecution(execution);
-                }
-            }
-        }
-    }
-
-     public static ConfigurableAuthenticatorFactory getConfigurableAuthenticatorFactory(KeycloakSession session, String providerId) {
-        ConfigurableAuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, providerId);
-        if (factory == null) {
-            factory = (FormActionFactory)session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, providerId);
-        }
-        return factory;
-    }
-}
+package org.keycloak.utils;
+
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.authentication.ConfigurableAuthenticatorFactory;
+import org.keycloak.authentication.FormAction;
+import org.keycloak.authentication.FormActionFactory;
+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.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.idm.CredentialRepresentation;
+
+/**
+ * used to set an execution a state based on type.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CredentialHelper {
+
+    public static void setRequiredCredential(KeycloakSession session, String type, RealmModel realm) {
+        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.REQUIRED;
+        authenticationRequirement(session, realm, type, requirement);
+    }
+
+    public static void setAlternativeCredential(KeycloakSession session, String type, RealmModel realm) {
+        AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.ALTERNATIVE;
+        authenticationRequirement(session, realm, type, requirement);
+    }
+
+    public static void authenticationRequirement(KeycloakSession session, RealmModel realm, String type, AuthenticationExecutionModel.Requirement requirement) {
+        for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
+            for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) {
+                String providerId = execution.getAuthenticator();
+                ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, providerId);
+                if (factory == null) continue;
+                if (type.equals(factory.getReferenceCategory())) {
+                    execution.setRequirement(requirement);
+                    realm.updateAuthenticatorExecution(execution);
+                }
+            }
+        }
+    }
+
+     public static ConfigurableAuthenticatorFactory getConfigurableAuthenticatorFactory(KeycloakSession session, String providerId) {
+        ConfigurableAuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, providerId);
+        if (factory == null) {
+            factory = (FormActionFactory)session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, providerId);
+        }
+        return factory;
+    }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
index 56adc89..c448a92 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
@@ -1,223 +1,223 @@
-/*
- * 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.actions;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.authentication.requiredactions.UpdateTotp;
-import org.keycloak.events.Details;
-import org.keycloak.events.Event;
-import org.keycloak.events.EventType;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredActionProviderModel;
-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.testsuite.AssertEvents;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.AccountTotpPage;
-import org.keycloak.testsuite.pages.AppPage;
-import org.keycloak.testsuite.pages.AppPage.RequestType;
-import org.keycloak.testsuite.pages.LoginConfigTotpPage;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.pages.LoginTotpPage;
-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.keycloak.utils.CredentialHelper;
-import org.openqa.selenium.WebDriver;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class RequiredActionTotpSetupTest {
-
-    @ClassRule
-    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() {
-
-        @Override
-        public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
-            CredentialHelper.setRequiredCredential(manager.getSession(), CredentialRepresentation.TOTP, appRealm);
-            //appRealm.addRequiredCredential(CredentialRepresentation.TOTP);
-            RequiredActionProviderModel requiredAction = appRealm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
-            requiredAction.setDefaultAction(true);
-            appRealm.updateRequiredActionProvider(requiredAction);
-            appRealm.setResetPasswordAllowed(true);
-        }
-
-    });
-
-    @Rule
-    public AssertEvents events = new AssertEvents(keycloakRule);
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @WebResource
-    protected AppPage appPage;
-
-    @WebResource
-    protected LoginPage loginPage;
-
-    @WebResource
-    protected LoginTotpPage loginTotpPage;
-
-    @WebResource
-    protected LoginConfigTotpPage totpPage;
-
-    @WebResource
-    protected AccountTotpPage accountTotpPage;
-
-    @WebResource
-    protected OAuthClient oauth;
-
-    @WebResource
-    protected RegisterPage registerPage;
-
-    protected TimeBasedOTP totp = new TimeBasedOTP();
-
-    @Test
-    public void setupTotpRegister() {
-        loginPage.open();
-        loginPage.clickRegister();
-        registerPage.register("firstName", "lastName", "email@mail.com", "setupTotp", "password", "password");
-
-        String userId = events.expectRegister("setupTotp", "email@mail.com").assertEvent().getUserId();
-
-        totpPage.assertCurrent();
-
-        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
-
-        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp").assertEvent().getSessionId();
-
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        events.expectLogin().user(userId).session(sessionId).detail(Details.USERNAME, "setuptotp").assertEvent();
-    }
-
-    @Test
-    public void setupTotpExisting() {
-        loginPage.open();
-        loginPage.login("test-user@localhost", "password");
-
-        totpPage.assertCurrent();
-
-        String totpSecret = totpPage.getTotpSecret();
-
-        totpPage.configure(totp.generate(totpSecret));
-
-        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).assertEvent().getSessionId();
-
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        Event loginEvent = events.expectLogin().session(sessionId).assertEvent();
-
-        oauth.openLogout();
-
-        events.expectLogout(loginEvent.getSessionId()).assertEvent();
-
-        loginPage.open();
-        loginPage.login("test-user@localhost", "password");
-        String src = driver.getPageSource();
-        loginTotpPage.login(totp.generate(totpSecret));
-
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        events.expectLogin().assertEvent();
-    }
-
-    @Test
-    public void setupTotpRegisteredAfterTotpRemoval() {
-        // Register new user
-        loginPage.open();
-        loginPage.clickRegister();
-        registerPage.register("firstName2", "lastName2", "email2@mail.com", "setupTotp2", "password2", "password2");
-
-        String userId = events.expectRegister("setupTotp2", "email2@mail.com").assertEvent().getUserId();
-
-        // Configure totp
-        totpPage.assertCurrent();
-
-        String totpCode = totpPage.getTotpSecret();
-        totpPage.configure(totp.generate(totpCode));
-
-        // After totp config, user should be on the app page
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
-
-        Event loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
-
-        // Logout
-        oauth.openLogout();
-        events.expectLogout(loginEvent.getSessionId()).user(userId).assertEvent();
-
-        // Try to login after logout
-        loginPage.open();
-        loginPage.login("setupTotp2", "password2");
-
-        // Totp is already configured, thus one-time password is needed, login page should be loaded
-        Assert.assertTrue(loginPage.isCurrent());
-        Assert.assertFalse(totpPage.isCurrent());
-
-        // Login with one-time password
-        loginTotpPage.login(totp.generate(totpCode));
-
-        loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
-
-        // Open account page
-        accountTotpPage.open();
-        accountTotpPage.assertCurrent();
-
-        // Remove google authentificator
-        accountTotpPage.removeTotp();
-
-        events.expectAccount(EventType.REMOVE_TOTP).user(userId).assertEvent();
-
-        // Logout
-        oauth.openLogout();
-        events.expectLogout(loginEvent.getSessionId()).user(userId).assertEvent();
-
-        // Try to login
-        loginPage.open();
-        loginPage.login("setupTotp2", "password2");
-
-        // Since the authentificator was removed, it has to be set up again
-        totpPage.assertCurrent();
-        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
-
-        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent().getSessionId();
-
-        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
-        events.expectLogin().user(userId).session(sessionId).detail(Details.USERNAME, "setuptotp2").assertEvent();
-    }
-
-}
+/*
+ * 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.actions;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.authentication.requiredactions.UpdateTotp;
+import org.keycloak.events.Details;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventType;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredActionProviderModel;
+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.testsuite.AssertEvents;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AccountTotpPage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.AppPage.RequestType;
+import org.keycloak.testsuite.pages.LoginConfigTotpPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.LoginTotpPage;
+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.keycloak.utils.CredentialHelper;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class RequiredActionTotpSetupTest {
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() {
+
+        @Override
+        public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
+            CredentialHelper.setRequiredCredential(manager.getSession(), CredentialRepresentation.TOTP, appRealm);
+            //appRealm.addRequiredCredential(CredentialRepresentation.TOTP);
+            RequiredActionProviderModel requiredAction = appRealm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+            requiredAction.setDefaultAction(true);
+            appRealm.updateRequiredActionProvider(requiredAction);
+            appRealm.setResetPasswordAllowed(true);
+        }
+
+    });
+
+    @Rule
+    public AssertEvents events = new AssertEvents(keycloakRule);
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected AppPage appPage;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @WebResource
+    protected LoginTotpPage loginTotpPage;
+
+    @WebResource
+    protected LoginConfigTotpPage totpPage;
+
+    @WebResource
+    protected AccountTotpPage accountTotpPage;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected RegisterPage registerPage;
+
+    protected TimeBasedOTP totp = new TimeBasedOTP();
+
+    @Test
+    public void setupTotpRegister() {
+        loginPage.open();
+        loginPage.clickRegister();
+        registerPage.register("firstName", "lastName", "email@mail.com", "setupTotp", "password", "password");
+
+        String userId = events.expectRegister("setupTotp", "email@mail.com").assertEvent().getUserId();
+
+        totpPage.assertCurrent();
+
+        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
+
+        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp").assertEvent().getSessionId();
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectLogin().user(userId).session(sessionId).detail(Details.USERNAME, "setuptotp").assertEvent();
+    }
+
+    @Test
+    public void setupTotpExisting() {
+        loginPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        totpPage.assertCurrent();
+
+        String totpSecret = totpPage.getTotpSecret();
+
+        totpPage.configure(totp.generate(totpSecret));
+
+        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).assertEvent().getSessionId();
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        Event loginEvent = events.expectLogin().session(sessionId).assertEvent();
+
+        oauth.openLogout();
+
+        events.expectLogout(loginEvent.getSessionId()).assertEvent();
+
+        loginPage.open();
+        loginPage.login("test-user@localhost", "password");
+        String src = driver.getPageSource();
+        loginTotpPage.login(totp.generate(totpSecret));
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectLogin().assertEvent();
+    }
+
+    @Test
+    public void setupTotpRegisteredAfterTotpRemoval() {
+        // Register new user
+        loginPage.open();
+        loginPage.clickRegister();
+        registerPage.register("firstName2", "lastName2", "email2@mail.com", "setupTotp2", "password2", "password2");
+
+        String userId = events.expectRegister("setupTotp2", "email2@mail.com").assertEvent().getUserId();
+
+        // Configure totp
+        totpPage.assertCurrent();
+
+        String totpCode = totpPage.getTotpSecret();
+        totpPage.configure(totp.generate(totpCode));
+
+        // After totp config, user should be on the app page
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
+
+        Event loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
+
+        // Logout
+        oauth.openLogout();
+        events.expectLogout(loginEvent.getSessionId()).user(userId).assertEvent();
+
+        // Try to login after logout
+        loginPage.open();
+        loginPage.login("setupTotp2", "password2");
+
+        // Totp is already configured, thus one-time password is needed, login page should be loaded
+        Assert.assertTrue(loginPage.isCurrent());
+        Assert.assertFalse(totpPage.isCurrent());
+
+        // Login with one-time password
+        loginTotpPage.login(totp.generate(totpCode));
+
+        loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
+
+        // Open account page
+        accountTotpPage.open();
+        accountTotpPage.assertCurrent();
+
+        // Remove google authentificator
+        accountTotpPage.removeTotp();
+
+        events.expectAccount(EventType.REMOVE_TOTP).user(userId).assertEvent();
+
+        // Logout
+        oauth.openLogout();
+        events.expectLogout(loginEvent.getSessionId()).user(userId).assertEvent();
+
+        // Try to login
+        loginPage.open();
+        loginPage.login("setupTotp2", "password2");
+
+        // Since the authentificator was removed, it has to be set up again
+        totpPage.assertCurrent();
+        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
+
+        String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent().getSessionId();
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectLogin().user(userId).session(sessionId).detail(Details.USERNAME, "setuptotp2").assertEvent();
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index bf47e0c..7178f1d 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -1,296 +1,296 @@
-/*
- * 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.enums.SslRequired;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-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.AccessToken;
-import org.keycloak.services.managers.ClientManager;
-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.openqa.selenium.WebDriver;
-
-import java.security.PublicKey;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class CompositeRoleTest {
-
-    public static PublicKey realmPublicKey;
-    @ClassRule
-    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
-        @Override
-        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
-            RealmModel realm = manager.createRealm("test");
-            KeycloakModelUtils.generateRealmKeys(realm);
-            realmPublicKey = realm.getPublicKey();
-            realm.setSsoSessionIdleTimeout(3000);
-            realm.setAccessTokenLifespan(10000);
-            realm.setSsoSessionMaxLifespan(10000);
-            realm.setAccessCodeLifespanUserAction(1000);
-            realm.setAccessCodeLifespan(1000);
-            realm.setSslRequired(SslRequired.EXTERNAL);
-            realm.setEnabled(true);
-            realm.addRequiredCredential(UserCredentialModel.PASSWORD);
-            final RoleModel realmRole1 = realm.addRole("REALM_ROLE_1");
-            final RoleModel realmRole2 = realm.addRole("REALM_ROLE_2");
-            final RoleModel realmRole3 = realm.addRole("REALM_ROLE_3");
-            final RoleModel realmComposite1 = realm.addRole("REALM_COMPOSITE_1");
-            realmComposite1.addCompositeRole(realmRole1);
-
-            final UserModel realmComposite1User = session.users().addUser(realm, "REALM_COMPOSITE_1_USER");
-            realmComposite1User.setEnabled(true);
-            realmComposite1User.updateCredential(UserCredentialModel.password("password"));
-            realmComposite1User.grantRole(realmComposite1);
-
-            final UserModel realmRole1User = session.users().addUser(realm, "REALM_ROLE_1_USER");
-            realmRole1User.setEnabled(true);
-            realmRole1User.updateCredential(UserCredentialModel.password("password"));
-            realmRole1User.grantRole(realmRole1);
-
-            final ClientModel realmComposite1Application = new ClientManager(manager).createClient(realm, "REALM_COMPOSITE_1_APPLICATION");
-            realmComposite1Application.setFullScopeAllowed(false);
-            realmComposite1Application.setEnabled(true);
-            realmComposite1Application.addScopeMapping(realmComposite1);
-            realmComposite1Application.addRedirectUri("http://localhost:8081/app/*");
-            realmComposite1Application.setBaseUrl("http://localhost:8081/app");
-            realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
-            realmComposite1Application.setSecret("password");
-
-            final ClientModel realmRole1Application = new ClientManager(manager).createClient(realm, "REALM_ROLE_1_APPLICATION");
-            realmRole1Application.setFullScopeAllowed(false);
-            realmRole1Application.setEnabled(true);
-            realmRole1Application.addScopeMapping(realmRole1);
-            realmRole1Application.addRedirectUri("http://localhost:8081/app/*");
-            realmRole1Application.setBaseUrl("http://localhost:8081/app");
-            realmRole1Application.setManagementUrl("http://localhost:8081/app/logout");
-            realmRole1Application.setSecret("password");
-
-
-            final ClientModel appRoleApplication = new ClientManager(manager).createClient(realm, "APP_ROLE_APPLICATION");
-            appRoleApplication.setFullScopeAllowed(false);
-            appRoleApplication.setEnabled(true);
-            appRoleApplication.addRedirectUri("http://localhost:8081/app/*");
-            appRoleApplication.setBaseUrl("http://localhost:8081/app");
-            appRoleApplication.setManagementUrl("http://localhost:8081/app/logout");
-            appRoleApplication.setSecret("password");
-            final RoleModel appRole1 = appRoleApplication.addRole("APP_ROLE_1");
-            final RoleModel appRole2 = appRoleApplication.addRole("APP_ROLE_2");
-
-            final RoleModel realmAppCompositeRole = realm.addRole("REALM_APP_COMPOSITE_ROLE");
-            realmAppCompositeRole.addCompositeRole(appRole1);
-
-            final UserModel realmAppCompositeUser = session.users().addUser(realm, "REALM_APP_COMPOSITE_USER");
-            realmAppCompositeUser.setEnabled(true);
-            realmAppCompositeUser.updateCredential(UserCredentialModel.password("password"));
-            realmAppCompositeUser.grantRole(realmAppCompositeRole);
-
-            final UserModel realmAppRoleUser = session.users().addUser(realm, "REALM_APP_ROLE_USER");
-            realmAppRoleUser.setEnabled(true);
-            realmAppRoleUser.updateCredential(UserCredentialModel.password("password"));
-            realmAppRoleUser.grantRole(appRole2);
-
-            final ClientModel appCompositeApplication = new ClientManager(manager).createClient(realm, "APP_COMPOSITE_APPLICATION");
-            appCompositeApplication.setFullScopeAllowed(false);
-            appCompositeApplication.setEnabled(true);
-            appCompositeApplication.addRedirectUri("http://localhost:8081/app/*");
-            appCompositeApplication.setBaseUrl("http://localhost:8081/app");
-            appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout");
-            appCompositeApplication.setSecret("password");
-            final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE");
-            appCompositeApplication.addScopeMapping(appRole2);
-            appCompositeRole.addCompositeRole(realmRole1);
-            appCompositeRole.addCompositeRole(realmRole2);
-            appCompositeRole.addCompositeRole(realmRole3);
-            appCompositeRole.addCompositeRole(appRole1);
-
-            final UserModel appCompositeUser = session.users().addUser(realm, "APP_COMPOSITE_USER");
-            appCompositeUser.setEnabled(true);
-            appCompositeUser.updateCredential(UserCredentialModel.password("password"));
-            appCompositeUser.grantRole(realmAppCompositeRole);
-            appCompositeUser.grantRole(realmComposite1);
-
-            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"));
-
-        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
-        Assert.assertEquals(200, refreshResponse.getStatusCode());
-    }
-
-
-    @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"));
-
-        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
-        Assert.assertEquals(200, refreshResponse.getStatusCode());
-    }
-
-    @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"));
-
-        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
-        Assert.assertEquals(200, refreshResponse.getStatusCode());
-    }
-
-    @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"));
-
-        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
-        Assert.assertEquals(200, refreshResponse.getStatusCode());
-    }
-
-    @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"));
-
-        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
-        Assert.assertEquals(200, refreshResponse.getStatusCode());
-    }
-
-}
+/*
+ * 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.enums.SslRequired;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+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.AccessToken;
+import org.keycloak.services.managers.ClientManager;
+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.openqa.selenium.WebDriver;
+
+import java.security.PublicKey;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class CompositeRoleTest {
+
+    public static PublicKey realmPublicKey;
+    @ClassRule
+    public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
+        @Override
+        protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
+            RealmModel realm = manager.createRealm("test");
+            KeycloakModelUtils.generateRealmKeys(realm);
+            realmPublicKey = realm.getPublicKey();
+            realm.setSsoSessionIdleTimeout(3000);
+            realm.setAccessTokenLifespan(10000);
+            realm.setSsoSessionMaxLifespan(10000);
+            realm.setAccessCodeLifespanUserAction(1000);
+            realm.setAccessCodeLifespan(1000);
+            realm.setSslRequired(SslRequired.EXTERNAL);
+            realm.setEnabled(true);
+            realm.addRequiredCredential(UserCredentialModel.PASSWORD);
+            final RoleModel realmRole1 = realm.addRole("REALM_ROLE_1");
+            final RoleModel realmRole2 = realm.addRole("REALM_ROLE_2");
+            final RoleModel realmRole3 = realm.addRole("REALM_ROLE_3");
+            final RoleModel realmComposite1 = realm.addRole("REALM_COMPOSITE_1");
+            realmComposite1.addCompositeRole(realmRole1);
+
+            final UserModel realmComposite1User = session.users().addUser(realm, "REALM_COMPOSITE_1_USER");
+            realmComposite1User.setEnabled(true);
+            realmComposite1User.updateCredential(UserCredentialModel.password("password"));
+            realmComposite1User.grantRole(realmComposite1);
+
+            final UserModel realmRole1User = session.users().addUser(realm, "REALM_ROLE_1_USER");
+            realmRole1User.setEnabled(true);
+            realmRole1User.updateCredential(UserCredentialModel.password("password"));
+            realmRole1User.grantRole(realmRole1);
+
+            final ClientModel realmComposite1Application = new ClientManager(manager).createClient(realm, "REALM_COMPOSITE_1_APPLICATION");
+            realmComposite1Application.setFullScopeAllowed(false);
+            realmComposite1Application.setEnabled(true);
+            realmComposite1Application.addScopeMapping(realmComposite1);
+            realmComposite1Application.addRedirectUri("http://localhost:8081/app/*");
+            realmComposite1Application.setBaseUrl("http://localhost:8081/app");
+            realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
+            realmComposite1Application.setSecret("password");
+
+            final ClientModel realmRole1Application = new ClientManager(manager).createClient(realm, "REALM_ROLE_1_APPLICATION");
+            realmRole1Application.setFullScopeAllowed(false);
+            realmRole1Application.setEnabled(true);
+            realmRole1Application.addScopeMapping(realmRole1);
+            realmRole1Application.addRedirectUri("http://localhost:8081/app/*");
+            realmRole1Application.setBaseUrl("http://localhost:8081/app");
+            realmRole1Application.setManagementUrl("http://localhost:8081/app/logout");
+            realmRole1Application.setSecret("password");
+
+
+            final ClientModel appRoleApplication = new ClientManager(manager).createClient(realm, "APP_ROLE_APPLICATION");
+            appRoleApplication.setFullScopeAllowed(false);
+            appRoleApplication.setEnabled(true);
+            appRoleApplication.addRedirectUri("http://localhost:8081/app/*");
+            appRoleApplication.setBaseUrl("http://localhost:8081/app");
+            appRoleApplication.setManagementUrl("http://localhost:8081/app/logout");
+            appRoleApplication.setSecret("password");
+            final RoleModel appRole1 = appRoleApplication.addRole("APP_ROLE_1");
+            final RoleModel appRole2 = appRoleApplication.addRole("APP_ROLE_2");
+
+            final RoleModel realmAppCompositeRole = realm.addRole("REALM_APP_COMPOSITE_ROLE");
+            realmAppCompositeRole.addCompositeRole(appRole1);
+
+            final UserModel realmAppCompositeUser = session.users().addUser(realm, "REALM_APP_COMPOSITE_USER");
+            realmAppCompositeUser.setEnabled(true);
+            realmAppCompositeUser.updateCredential(UserCredentialModel.password("password"));
+            realmAppCompositeUser.grantRole(realmAppCompositeRole);
+
+            final UserModel realmAppRoleUser = session.users().addUser(realm, "REALM_APP_ROLE_USER");
+            realmAppRoleUser.setEnabled(true);
+            realmAppRoleUser.updateCredential(UserCredentialModel.password("password"));
+            realmAppRoleUser.grantRole(appRole2);
+
+            final ClientModel appCompositeApplication = new ClientManager(manager).createClient(realm, "APP_COMPOSITE_APPLICATION");
+            appCompositeApplication.setFullScopeAllowed(false);
+            appCompositeApplication.setEnabled(true);
+            appCompositeApplication.addRedirectUri("http://localhost:8081/app/*");
+            appCompositeApplication.setBaseUrl("http://localhost:8081/app");
+            appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout");
+            appCompositeApplication.setSecret("password");
+            final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE");
+            appCompositeApplication.addScopeMapping(appRole2);
+            appCompositeRole.addCompositeRole(realmRole1);
+            appCompositeRole.addCompositeRole(realmRole2);
+            appCompositeRole.addCompositeRole(realmRole3);
+            appCompositeRole.addCompositeRole(appRole1);
+
+            final UserModel appCompositeUser = session.users().addUser(realm, "APP_COMPOSITE_USER");
+            appCompositeUser.setEnabled(true);
+            appCompositeUser.updateCredential(UserCredentialModel.password("password"));
+            appCompositeUser.grantRole(realmAppCompositeRole);
+            appCompositeUser.grantRole(realmComposite1);
+
+            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"));
+
+        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+        Assert.assertEquals(200, refreshResponse.getStatusCode());
+    }
+
+
+    @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"));
+
+        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+        Assert.assertEquals(200, refreshResponse.getStatusCode());
+    }
+
+    @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"));
+
+        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+        Assert.assertEquals(200, refreshResponse.getStatusCode());
+    }
+
+    @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"));
+
+        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+        Assert.assertEquals(200, refreshResponse.getStatusCode());
+    }
+
+    @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"));
+
+        AccessTokenResponse refreshResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+        Assert.assertEquals(200, refreshResponse.getStatusCode());
+    }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/MailServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/MailServer.java
index 1acaafb..f56f0aa 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/MailServer.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/MailServer.java
@@ -5,6 +5,7 @@ import com.icegreen.greenmail.util.ServerSetup;
 
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMessage.RecipientType;
+import javax.mail.internet.MimeMultipart;
 
 public class MailServer {
 
@@ -22,9 +23,20 @@ public class MailServer {
 
             if (greenMail.waitForIncomingEmail(Long.MAX_VALUE, c + 1)) {
                 MimeMessage message = greenMail.getReceivedMessages()[c++];
+                System.out.println("-------------------------------------------------------");
                 System.out.println("Received mail to " + message.getRecipients(RecipientType.TO)[0]);
-                System.out.println();
-                System.out.println(message.getContent());
+                if (message.getContent() instanceof MimeMultipart) {
+                    MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
+                    for (int i = 0; i < mimeMultipart.getCount(); i++) {
+                        System.out.println("----");
+                        System.out.println(mimeMultipart.getBodyPart(i).getContentType() + ":");
+                        System.out.println();
+                        System.out.println(mimeMultipart.getBodyPart(i).getContent());
+                    }
+                } else {
+                    System.out.println();
+                    System.out.println(message.getContent());
+                }
                 System.out.println("-------------------------------------------------------");
             }
         }