diff --git a/.travis.yml b/.travis.yml
index 8275e00333..8146d6e1ed 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 e145818cc2..d94fe5b735 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 Bill Burke
-* @version $Revision: 1 $
-*/
-public class RequiredActionProviderRepresentation {
-
- private String alias;
- private String name;
- private String providerId;
- private boolean enabled;
- private boolean defaultAction;
- private Map config = new HashMap();
-
-
- 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 getConfig() {
- return config;
- }
-
- public void setConfig(Map config) {
- this.config = config;
- }
-}
+package org.keycloak.representations.idm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+* @author Bill Burke
+* @version $Revision: 1 $
+*/
+public class RequiredActionProviderRepresentation {
+
+ private String alias;
+ private String name;
+ private String providerId;
+ private boolean enabled;
+ private boolean defaultAction;
+ private Map config = new HashMap();
+
+
+ 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 getConfig() {
+ return config;
+ }
+
+ public void setConfig(Map 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 094e4268d4..59ae243e0c 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 @@
modules
+
+
+
+ bin
+
+
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 4e29b1b9c3..0f6c462771 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 @@
modules/system/layers/base
+
+
+
+ bin
+
+
diff --git a/distribution/adapters/shared-cli/adapter-install.cli b/distribution/adapters/shared-cli/adapter-install.cli
new file mode 100644
index 0000000000..b4a396ba7a
--- /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 3f5d8878d9..da4e127bc4 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 @@
modules/system/layers/base
+
+
+
+ bin
+
+
diff --git a/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml b/distribution/adapters/wf9-adapter/wf9-adapter-zip/assembly.xml
index e81d4e4e0f..764b76dbba 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 @@
modules/system/layers/base
+
+
+
+ bin
+
+
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
index 1ead8b9e8e..1d978dde84 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 @@
standalone/configuration/providers
+
+
+ bin
+
+
+
+ bin
+
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 0000000000..cc594313f9
--- /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 0000000000..000cbfa3d8
--- /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 69ea1c1f00..519b4a71b6 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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/distribution/server-overlay/wf9-server-overlay/assembly.xml b/distribution/server-overlay/wf9-server-overlay/assembly.xml
index 4d87e6912e..e7fcb1b112 100755
--- a/distribution/server-overlay/wf9-server-overlay/assembly.xml
+++ b/distribution/server-overlay/wf9-server-overlay/assembly.xml
@@ -62,6 +62,10 @@
standalone/configuration
+
+
+ bin
+
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 0000000000..ac5ca0b81c
--- /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 52877de44f..9e2d4a1ce9 100755
--- a/docbook/reference/en/en-US/modules/jboss-adapter.xml
+++ b/docbook/reference/en/en-US/modules/jboss-adapter.xml
@@ -48,6 +48,15 @@ $ unzip keycloak-as7-adapter-dist.zip
After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration:
domain.xml or standalone.xml.
+
+ 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:
+
+$ cd $JBOSS_HOME/bin
+$ jboss-cli.sh -c --file=adapter-install.cli
+
+ The script will add the extension, subsystem, and optional security-domain as described below.
+
@@ -65,8 +74,7 @@ $ unzip keycloak-as7-adapter-dist.zip
- 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.
diff --git a/docbook/reference/en/en-US/modules/server-installation.xml b/docbook/reference/en/en-US/modules/server-installation.xml
index 9584852177..6b39bf664f 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 @@
keycloak-overlay-&project.version;.zip or keycloak-overlay-&project.version;.tar.gz.
Once downloaded extract into the root directory of your WildFly installation. To start WildFly with Keycloak
run:
- keycloak-&project.version;/bin/standalone.sh --server-config=standalone-keycloak.xml
+ <WILDFLY_HOME>/bin/standalone.sh --server-config=standalone-keycloak.xml
or:
- keycloak-&project.version;/bin/standalone.bat --server-config=standalone-keycloak.xml
+ <WILDFLY_HOME>/bin/standalone.bat --server-config=standalone-keycloak.xml
Once the server is started log into the admin console at
@@ -60,15 +60,9 @@
enter in a new password.
- To add Keycloak to other sever configurations (standalone.xml, standalone-ha.xml, etc.) open
- standalone/configuration/standalone-keycloak.xml and the configuration you want to add it
- to, for example standalone/configuration/standalone.xml. From standalone-keycloak.xml
- you need to copy 3 elements:
-
- <extension module="org.keycloak.keycloak-server-subsystem"/>
- <datasource jndi-name="java:jboss/datasources/KeycloakDS" ...>
- <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1" ...>
-
+ 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:
+ <WILDFLY_HOME>/bin/jboss-cli.sh -c --file=keycloak-install.cli
@@ -76,6 +70,19 @@
Same procedure as WildFly 9.0.0.Final, but download keycloak-overlay-eap6-&project.version;.zip or keycloak-overlay-eap6-&project.version;.tar.gz.
+
+ 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:
+
+
+ <EAP_HOME>/bin/jboss-cli.sh -c --file=keycloak-prepare.cli
+
+ Restart the server with the same server-config.
+
+ <EAP_HOME>/bin/jboss-cli.sh -c --file=keycloak-install.cli
+
+
+
Install Development Bundle
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 29433ef7c5..60d413c4ad 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
- * WEB-INF/keycloak.json
file generated by Keycloak.
+ * keycloak.json
resource file.
*
* @author Scott Rossillo
* @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 79d20d5011..55ddb9b50b 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 c40656b46e..9b3af31618 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 Bill Burke
- * @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 Bill Burke
+ * @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/MailServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/MailServer.java
index 1acaafb2a9..f56f0aaaa3 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("-------------------------------------------------------");
}
}
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 56adc8961b..c448a927ea 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 Stian Thorgersen
- */
-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 Stian Thorgersen
+ */
+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 bf47e0c5ed..7178f1de10 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 Stian Thorgersen
- */
-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 Stian Thorgersen
+ */
+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());
+ }
+
+}