keycloak-aplcache

Changes

Details

diff --git a/adapters/saml/undertow/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension b/adapters/saml/undertow/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension
new file mode 100644
index 0000000..f385fd0
--- /dev/null
+++ b/adapters/saml/undertow/src/main/resources/META-INF/services/io.undertow.servlet.ServletExtension
@@ -0,0 +1,18 @@
+#
+# Copyright 2018 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.keycloak.adapters.saml.undertow.SamlServletExtension
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index db66179..1c7bcf3 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1086,7 +1086,7 @@ public class RepresentationToModel {
      * @return
      */
     public static ClientModel createClient(KeycloakSession session, RealmModel realm, ClientRepresentation resourceRep, boolean addDefaultRoles) {
-        logger.debug("Create client: {0}" + resourceRep.getClientId());
+        logger.debugv("Create client: {0}", resourceRep.getClientId());
 
         ClientModel client = resourceRep.getId() != null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId());
         if (resourceRep.getName() != null) client.setName(resourceRep.getName());
diff --git a/testsuite/integration-arquillian/servers/app-server/undertow/pom.xml b/testsuite/integration-arquillian/servers/app-server/undertow/pom.xml
index c54e7e9..39ba1c8 100644
--- a/testsuite/integration-arquillian/servers/app-server/undertow/pom.xml
+++ b/testsuite/integration-arquillian/servers/app-server/undertow/pom.xml
@@ -33,6 +33,10 @@
             <artifactId>keycloak-undertow-adapter</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-undertow-adapter</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.keycloak.testsuite</groupId>
             <artifactId>integration-arquillian-servers-app-server-spi</artifactId>
             <version>${project.version}</version>
diff --git a/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/container/UndertowDeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/container/UndertowDeploymentArchiveProcessor.java
index dd8e8e2..6b0ecf4 100644
--- a/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/container/UndertowDeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/container/UndertowDeploymentArchiveProcessor.java
@@ -39,6 +39,10 @@ public class UndertowDeploymentArchiveProcessor implements ApplicationArchivePro
         modifyWebXML(archive, testClass);
 
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
+
+        modifySAMLAdapterConfig(archive, DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH);
+        modifySAMLAdapterConfig(archive, DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH_TENANT1);
+        modifySAMLAdapterConfig(archive, DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH_TENANT2);
     }
 
     private void modifyWebXML(Archive<?> archive, TestClass testClass) {
@@ -56,4 +60,11 @@ public class UndertowDeploymentArchiveProcessor implements ApplicationArchivePro
 
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
+
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
+
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
+    }
 }
diff --git a/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/saml/util/RestSamlApplicationConfig.java b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/saml/util/RestSamlApplicationConfig.java
new file mode 100644
index 0000000..1f9084a
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/saml/util/RestSamlApplicationConfig.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.arquillian.undertow.saml.util;
+
+import java.util.Set;
+import javax.ws.rs.core.Application;
+
+/**
+ * Wildfly JAX-RS Integration has support for scanning  deployment for annotations.
+ * 
+ * https://github.com/wildfly/wildfly/blob/14.0.1.Final/jaxrs/src/main/java/org/jboss/as/jaxrs/deployment/JaxrsAnnotationProcessor.java
+ * 
+ * On undertow we have to set Application Class manually:
+ * 
+ * ResteasyDeployment deployment = new ResteasyDeployment();
+ * deployment.setApplication(application);
+ * 
+ * @author vramik
+ */
+public class RestSamlApplicationConfig extends Application {
+
+    private final Set<Class<?>> classes;
+
+    public RestSamlApplicationConfig(Set<Class<?>> classes) {
+        this.classes = classes;
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return classes;
+    }
+}
diff --git a/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/UndertowAppServer.java b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/UndertowAppServer.java
index 81f9980..01a4a08 100644
--- a/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/UndertowAppServer.java
+++ b/testsuite/integration-arquillian/servers/app-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/UndertowAppServer.java
@@ -27,12 +27,18 @@ import io.undertow.servlet.api.ServletInfo;
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Field;
+import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 import javax.servlet.ServletException;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.arquillian.undertow.UndertowContainerConfiguration;
 import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
 import org.jboss.arquillian.container.spi.client.container.DeploymentException;
@@ -43,11 +49,14 @@ import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaD
 import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
+import org.jboss.resteasy.spi.ResteasyDeployment;
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.asset.ClassAsset;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.jboss.shrinkwrap.descriptor.api.Descriptor;
 import org.jboss.shrinkwrap.undertow.api.UndertowWebArchive;
 import org.keycloak.common.util.reflections.Reflections;
+import org.keycloak.testsuite.arquillian.undertow.saml.util.RestSamlApplicationConfig;
 import org.keycloak.testsuite.utils.undertow.UndertowDeployerHelper;
 import org.keycloak.testsuite.utils.undertow.UndertowWarClassLoader;
 
@@ -115,7 +124,13 @@ public class UndertowAppServer implements DeployableContainer<UndertowAppServerC
         if (archive instanceof UndertowWebArchive) {
             di = ((UndertowWebArchive) archive).getDeploymentInfo();
         } else if (archive instanceof WebArchive) {
-            di = new UndertowDeployerHelper().getDeploymentInfo(configuration, (WebArchive)archive);
+            WebArchive webArchive = (WebArchive)archive;
+            if (isJaxrsApp(webArchive)) {
+                di = new UndertowDeployerHelper().getDeploymentInfo(configuration, webArchive, 
+                        undertow.undertowDeployment(getCustomResteasyDeployment(webArchive)));
+            } else {
+                di = new UndertowDeployerHelper().getDeploymentInfo(configuration, webArchive);
+            }
         } else {
             throw new IllegalArgumentException("UndertowContainer only supports UndertowWebArchive or WebArchive.");
         }
@@ -191,4 +206,29 @@ public class UndertowAppServer implements DeployableContainer<UndertowAppServerC
         }
         return httpContext;
     }
+
+    private boolean isJaxrsApp(WebArchive archive) throws DeploymentException {
+        try {
+            return IOUtils.toString(archive.get("/WEB-INF/web.xml").getAsset().openStream(), Charset.forName("UTF-8"))
+                    .contains(Application.class.getName());
+        } catch (IOException e) {
+            throw new DeploymentException("Unable to read archive.", e);
+        }
+    }
+
+    private ResteasyDeployment getCustomResteasyDeployment(WebArchive webArchive) {
+        //take all classes from war and add those with @Path annotation to RestSamlApplicationConfig
+        Set<Class<?>> classes = webArchive.getContent(archivePath -> 
+                archivePath.get().startsWith("/WEB-INF/classes/") &&
+                archivePath.get().endsWith(".class")
+        ).values().stream()
+                .filter(node -> node.getAsset() instanceof ClassAsset)
+                .map(node -> ((ClassAsset)node.getAsset()).getSource())
+                .filter(clazz -> clazz.isAnnotationPresent(Path.class))
+                .collect(Collectors.toSet());
+
+        ResteasyDeployment deployment = new ResteasyDeployment();
+        deployment.setApplication(new RestSamlApplicationConfig(classes));
+        return deployment;
+    }
 }
diff --git a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlMultiTenantResolver.java b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlMultiTenantResolver.java
index 559a4ef..47cc83c 100644
--- a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlMultiTenantResolver.java
+++ b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlMultiTenantResolver.java
@@ -38,7 +38,7 @@ public class SamlMultiTenantResolver implements SamlConfigResolver {
             throw new IllegalStateException("Not able to resolve realm from the request path!");
         }
 
-        InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak-saml.xml");
+        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/" + realm + "-keycloak-saml.xml");
         if (is == null) {
             throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak-saml.xml");
         }
@@ -46,10 +46,10 @@ public class SamlMultiTenantResolver implements SamlConfigResolver {
         ResourceLoader loader = new ResourceLoader() {
             @Override
             public InputStream getResourceAsStream(String path) {
-                return getClass().getResourceAsStream(path);
+                return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
             }
         };
-        
+
         try {
             return new DeploymentBuilder().build(is, loader);
         } catch (ParsingException e) {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant1Saml.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant1Saml.java
index bb08f88..9965c57 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant1Saml.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant1Saml.java
@@ -45,7 +45,7 @@ public class MultiTenant1Saml extends SAMLServlet {
     
     @Override
     public void logout() {
-        driver.navigate().to(getUriBuilder().queryParam("GLO", "true").queryParam("realm", "tenant1").build().toASCIIString());
+        driver.navigate().to(getUriBuilder().clone().queryParam("GLO", "true").queryParam("realm", "tenant1").build().toASCIIString());
         getUriBuilder().replaceQueryParam("GLO");
         pause(300);
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant2Saml.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant2Saml.java
index e2623d1..1d81d6c 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant2Saml.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant2Saml.java
@@ -45,7 +45,7 @@ public class MultiTenant2Saml extends SAMLServlet {
     
     @Override
     public void logout() {
-        driver.navigate().to(getUriBuilder().queryParam("GLO", "true").queryParam("realm", "tenant2").build().toASCIIString());
+        driver.navigate().to(getUriBuilder().clone().queryParam("GLO", "true").queryParam("realm", "tenant2").build().toASCIIString());
         getUriBuilder().replaceQueryParam("GLO");
         pause(300);
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
index 2f226b9..0714303 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
@@ -17,9 +17,12 @@
 
 package org.keycloak.testsuite.adapter.page;
 
+import javax.ws.rs.core.UriBuilder;
 import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
+import org.keycloak.testsuite.util.WaitUtils;
 
 import static org.keycloak.testsuite.util.WaitUtils.pause;
+import org.openqa.selenium.By;
 
 /**
  * @author mhajas
@@ -27,8 +30,7 @@ import static org.keycloak.testsuite.util.WaitUtils.pause;
 public abstract class SAMLServlet extends AbstractPageWithInjectedUrl {
 
     public void logout() {
-        driver.navigate().to(getUriBuilder().queryParam("GLO", "true").build().toASCIIString());
-        getUriBuilder().replaceQueryParam("GLO");
+        driver.navigate().to(getUriBuilder().clone().queryParam("GLO", "true").build().toASCIIString());
         pause(300);
     }
 
@@ -41,7 +43,14 @@ public abstract class SAMLServlet extends AbstractPageWithInjectedUrl {
     }
 
     public void checkRolesEndPoint(boolean value) {
-        driver.navigate().to(getUriBuilder().build().toASCIIString() + "/" + (value ? "" : "un") + "checkRoles");
+        driver.navigate().to(getUriBuilder().clone().path((value ? "" : "un") + "checkRoles").build().toASCIIString());
         pause(300);
     }
+
+    public void setRolesToCheck(String roles) {
+        UriBuilder uriBuilder = getUriBuilder().clone();
+        String toASCIIString = uriBuilder.path("setCheckRoles").queryParam("roles", roles).build().toASCIIString();
+        driver.navigate().to(toASCIIString);
+        WaitUtils.waitUntilElement(By.tagName("body")).text().contains("These roles will be checked:");
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AdapterTestExecutionDecider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AdapterTestExecutionDecider.java
index 84b9f17..1ecb542 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AdapterTestExecutionDecider.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AdapterTestExecutionDecider.java
@@ -53,7 +53,11 @@ public class AdapterTestExecutionDecider implements TestExecutionDecider {
         if (testContext.isAdapterContainerEnabled() || testContext.isAdapterContainerEnabledCluster()) {
 
             if (method.isAnnotationPresent(AppServerContainer.class)) { // taking method level annotation first as it has higher priority
-                if (getCorrespondingAnnotation(method).skip()) {
+                if (getCorrespondingAnnotation(method) == null) { //no corresponding annotation - taking class level annotation
+                    if (getCorrespondingAnnotation(testContext.getTestClass()).skip()) {
+                        return execute(method, Boolean.FALSE, "Skipped by @AppServerContainer class level annotation.");
+                    }
+                } else if (getCorrespondingAnnotation(method).skip()) { //corresponding annotation
                     return execute(method, Boolean.FALSE, "Skipped by @AppServerContainer method level annotation.");
                 }
             } else { //taking class level annotation
@@ -88,7 +92,7 @@ public class AdapterTestExecutionDecider implements TestExecutionDecider {
         return appServerContainers.stream()
                 .filter(annotation -> annotation.value().equals(testContextInstance.get().getAppServerContainerName()))
                 .findFirst()
-                .orElseThrow(() -> new IllegalStateException("Not found the @AppServerContainer annotation with current app server."));
+                .orElse(null);
     }
 
     private AppServerContainer getCorrespondingAnnotation(Class testClass) {
@@ -107,7 +111,7 @@ public class AdapterTestExecutionDecider implements TestExecutionDecider {
         return appServerContainers.stream()
                 .filter(annotation -> annotation.value().equals(testContextInstance.get().getAppServerContainerName()))
                 .findFirst()
-                .orElseThrow(() -> new IllegalStateException("Not found the @AppServerContainer annotation with current app server."));
+                .orElse(null);
     }
 
     private ExecutionDecision execute(Method method, Boolean execute, String message) {
@@ -116,7 +120,7 @@ public class AdapterTestExecutionDecider implements TestExecutionDecider {
             return ExecutionDecision.execute();
         } else {
             cache.put(method, new CachedRecord(Boolean.FALSE, message));
-            log.debug(message);
+            log.debug(method.getName() + " " + message);
             return ExecutionDecision.dontExecute(message);
         }
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLFilterServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLFilterServletAdapterTest.java
index b53be7a..8c0af72 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLFilterServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLFilterServletAdapterTest.java
@@ -11,6 +11,7 @@ import org.keycloak.testsuite.arquillian.containers.ContainerConstants;
 /**
  * @author mhajas
  */
+@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
 @AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
 @AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY_DEPRECATED)
 @AppServerContainer(ContainerConstants.APP_SERVER_EAP)
@@ -94,4 +95,18 @@ public class SAMLFilterServletAdapterTest extends SAMLServletAdapterTest {
     public void testErrorHandlingSigned() {
 
     }
+
+    @Test
+    @Override
+    @Ignore
+    public void multiTenant1SamlTest() throws Exception {
+
+    }
+
+    @Test
+    @Override
+    @Ignore
+    public void multiTenant2SamlTest() throws Exception {
+
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
index 47a2b9b..431efb4 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
@@ -166,6 +166,7 @@ import org.xml.sax.SAXException;
 /**
  * @author mhajas
  */
+@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
 @AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
 @AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY_DEPRECATED)
 @AppServerContainer(ContainerConstants.APP_SERVER_EAP)
@@ -265,10 +266,10 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
     protected EcpSP ecpSPPage;
 
     @Page
-    protected MultiTenant1Saml mutiTenant1SamlPage;
+    protected MultiTenant1Saml multiTenant1SamlPage;
     
     @Page
-    protected MultiTenant2Saml mutiTenant2SamlPage;
+    protected MultiTenant2Saml multiTenant2SamlPage;
     
     @Page
     protected SAMLPostLoginTenant1 tenant1RealmSAMLPostLoginPage;
@@ -595,38 +596,50 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
 
     @Test
     public void multiTenant1SamlTest() throws Exception {
-        UserRepresentation user1 = createUserRepresentation("user-tenant1", "user-tenant1@redhat.com", "Bill", "Burke", true);
-        setPasswordFor(user1, "user-tenant1");
-        // check the user in the tenant logs in ok
-        assertSuccessfulLogin(mutiTenant1SamlPage, user1, tenant1RealmSAMLPostLoginPage, "principal=user-tenant1");
-        // check the issuer is the correct tenant
-        driver.navigate().to(mutiTenant1SamlPage.getUriBuilder().path("getAssertionIssuer").build().toASCIIString());
-        waitUntilElement(By.xpath("//body")).text().contains("/auth/realms/tenant1");
-        // check logout
-        mutiTenant1SamlPage.logout();
-        checkLoggedOut(mutiTenant1SamlPage, tenant1RealmSAMLPostLoginPage);
-        // check a user in the other tenant doesn't login
-        UserRepresentation user2 = createUserRepresentation("user-tenant2", "user-tenant2@redhat.com", "Bill", "Burke", true);
-        setPasswordFor(user2, "user-tenant2");
-        assertFailedLogin(mutiTenant1SamlPage, user2, tenant1RealmSAMLPostLoginPage);
+        multiTenant1SamlPage.setRolesToCheck("user");
+
+        try {
+            UserRepresentation user1 = createUserRepresentation("user-tenant1", "user-tenant1@redhat.com", "Bill", "Burke", true);
+            setPasswordFor(user1, "user-tenant1");
+            // check the user in the tenant logs in ok
+            assertSuccessfulLogin(multiTenant1SamlPage, user1, tenant1RealmSAMLPostLoginPage, "principal=user-tenant1");
+            // check the issuer is the correct tenant
+            driver.navigate().to(multiTenant1SamlPage.getUriBuilder().clone().path("getAssertionIssuer").build().toASCIIString());
+            waitUntilElement(By.xpath("//body")).text().contains("/auth/realms/tenant1");
+            // check logout
+            multiTenant1SamlPage.logout();
+            checkLoggedOut(multiTenant1SamlPage, tenant1RealmSAMLPostLoginPage);
+            // check a user in the other tenant doesn't login
+            UserRepresentation user2 = createUserRepresentation("user-tenant2", "user-tenant2@redhat.com", "Bill", "Burke", true);
+            setPasswordFor(user2, "user-tenant2");
+            assertFailedLogin(multiTenant1SamlPage, user2, tenant1RealmSAMLPostLoginPage);
+        } finally {
+            multiTenant1SamlPage.checkRolesEndPoint(false);
+        }
     }
-    
+
     @Test
     public void multiTenant2SamlTest() throws Exception {
-        UserRepresentation user2 = createUserRepresentation("user-tenant2", "user-tenant2@redhat.com", "Bill", "Burke", true);
-        setPasswordFor(user2, "user-tenant2");
-        // check the user in the tenant logs in ok
-        assertSuccessfulLogin(mutiTenant2SamlPage, user2, tenant2RealmSAMLPostLoginPage, "principal=user-tenant2");
-        // check the issuer is the correct tenant
-        driver.navigate().to(mutiTenant2SamlPage.getUriBuilder().path("getAssertionIssuer").build().toASCIIString());
-        waitUntilElement(By.xpath("//body")).text().contains("/auth/realms/tenant2");
-        // check logout
-        mutiTenant2SamlPage.logout();
-        checkLoggedOut(mutiTenant2SamlPage, tenant2RealmSAMLPostLoginPage);
-        // check a user in the other tenant doesn't login
-        UserRepresentation user1 = createUserRepresentation("user-tenant1", "user-tenant1@redhat.com", "Bill", "Burke", true);
-        setPasswordFor(user1, "user-tenant1");
-        assertFailedLogin(mutiTenant2SamlPage, user1, tenant2RealmSAMLPostLoginPage);
+        multiTenant2SamlPage.setRolesToCheck("user");
+
+        try {
+            UserRepresentation user2 = createUserRepresentation("user-tenant2", "user-tenant2@redhat.com", "Bill", "Burke", true);
+            setPasswordFor(user2, "user-tenant2");
+            // check the user in the tenant logs in ok
+            assertSuccessfulLogin(multiTenant2SamlPage, user2, tenant2RealmSAMLPostLoginPage, "principal=user-tenant2");
+            // check the issuer is the correct tenant
+            driver.navigate().to(multiTenant2SamlPage.getUriBuilder().clone().path("getAssertionIssuer").build().toASCIIString());
+            waitUntilElement(By.xpath("//body")).text().contains("/auth/realms/tenant2");
+            // check logout
+            multiTenant2SamlPage.logout();
+            checkLoggedOut(multiTenant2SamlPage, tenant2RealmSAMLPostLoginPage);
+            // check a user in the other tenant doesn't login
+            UserRepresentation user1 = createUserRepresentation("user-tenant1", "user-tenant1@redhat.com", "Bill", "Burke", true);
+            setPasswordFor(user1, "user-tenant1");
+            assertFailedLogin(multiTenant2SamlPage, user1, tenant2RealmSAMLPostLoginPage);
+        } finally {
+            multiTenant2SamlPage.checkRolesEndPoint(false);
+        }
     }
 
     private static final KeyPair NEW_KEY_PAIR = KeyUtils.generateRsaKeyPair(1024);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/NonIDERunListener.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/NonIDERunListener.java
index 17947e4..d6aff45 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/NonIDERunListener.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/NonIDERunListener.java
@@ -40,12 +40,27 @@ public class NonIDERunListener extends RunListener {
     }
 
     private void disableKeycloakLogging() {
-        String loggingLevel = System.getProperty(KEYCLOAK_LOGGING_LEVEL_NAME);
-        if (loggingLevel == null || loggingLevel.isEmpty()) {
+        String loggingLevel = System.getProperty(KEYCLOAK_LOGGING_LEVEL_NAME, "").toLowerCase();
+        if (loggingLevel.isEmpty()) {
 
             log.infof("Setting %s to off. Keycloak server logging will be disabled", KEYCLOAK_LOGGING_LEVEL_NAME);
             System.setProperty(KEYCLOAK_LOGGING_LEVEL_NAME, "off");
             org.apache.log4j.Logger.getLogger("org.keycloak").setLevel(Level.OFF);
+        } else {
+            switch (loggingLevel) {
+                case "debug":
+                    org.apache.log4j.Logger.getLogger("org.keycloak").setLevel(Level.DEBUG);
+                    break;
+                case "trace":
+                    org.apache.log4j.Logger.getLogger("org.keycloak").setLevel(Level.TRACE);
+                    break;
+                case "all":
+                    org.apache.log4j.Logger.getLogger("org.keycloak").setLevel(Level.ALL);
+                    break;
+                default:
+                    org.apache.log4j.Logger.getLogger("org.keycloak").setLevel(Level.INFO);
+                    break;
+            }
         }
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/web.xml
index 1720657..a4f67a8 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/web.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/web.xml
@@ -45,6 +45,18 @@
             <role-name>user</role-name>
         </auth-constraint>
     </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Unsecured-setCheckRoles</web-resource-name>
+            <url-pattern>/setCheckRoles/*</url-pattern>
+        </web-resource-collection>
+    </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Unsecured-uncheckRoles</web-resource-name>
+            <url-pattern>/uncheckRoles/*</url-pattern>
+        </web-resource-collection>
+    </security-constraint>
 
     <login-config>
         <auth-method>KEYCLOAK-SAML</auth-method>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
index ab98a52..825985f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
@@ -45,6 +45,18 @@
             <role-name>manager</role-name>
         </auth-constraint>
     </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Unsecured-setCheckRoles</web-resource-name>
+            <url-pattern>/setCheckRoles/*</url-pattern>
+        </web-resource-collection>
+    </security-constraint>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Unsecured-uncheckRoles</web-resource-name>
+            <url-pattern>/uncheckRoles/*</url-pattern>
+        </web-resource-collection>
+    </security-constraint>
 
     <login-config>
         <auth-method>KEYCLOAK-SAML</auth-method>
diff --git a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/SimpleWebXmlParser.java b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/SimpleWebXmlParser.java
index eeef219..a77b6ef 100644
--- a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/SimpleWebXmlParser.java
+++ b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/SimpleWebXmlParser.java
@@ -55,33 +55,35 @@ class SimpleWebXmlParser {
         try {
             DocumentWrapper document = new DocumentWrapper(webXml);
 
-            // SERVLETS
-
-            Map<String, String> servletMappings = new HashMap<>();
-            List<ElementWrapper> sm = document.getElementsByTagName("servlet-mapping");
-            for (ElementWrapper mapping : sm) {
-                String servletName = mapping.getElementByTagName("servlet-name").getText();
-                String path = mapping.getElementByTagName("url-pattern").getText();
-                servletMappings.put(servletName, path);
-            }
+            if (di.getServlets().get("ResteasyServlet") == null) {
+
+                // SERVLETS
+                Map<String, String> servletMappings = new HashMap<>();
+                List<ElementWrapper> sm = document.getElementsByTagName("servlet-mapping");
+                for (ElementWrapper mapping : sm) {
+                    String servletName = mapping.getElementByTagName("servlet-name").getText();
+                    String path = mapping.getElementByTagName("url-pattern").getText();
+                    servletMappings.put(servletName, path);
+                }
 
-            List<ElementWrapper> servlets = document.getElementsByTagName("servlet");
-            for (ElementWrapper servlet : servlets) {
-                String servletName = servlet.getElementByTagName("servlet-name").getText();
-                ElementWrapper servletClassEw = servlet.getElementByTagName("servlet-class");
-                String servletClass = servletClassEw == null ? servletName : servletClassEw.getText();
-                ElementWrapper loadOnStartupEw = servlet.getElementByTagName("load-on-startup");
-                Integer loadOnStartup = loadOnStartupEw == null ? null : Integer.valueOf(loadOnStartupEw.getText());
-
-                Class<? extends Servlet> servletClazz = (Class<? extends Servlet>) Class.forName(servletClass);
-                ServletInfo undertowServlet = new ServletInfo(servletName, servletClazz);
-
-                if (servletMappings.containsKey(servletName)) {
-                    undertowServlet.addMapping(servletMappings.get(servletName));
-                    undertowServlet.setLoadOnStartup(loadOnStartup);
-                    di.addServlet(undertowServlet);
-                } else {
-                    log.warnf("Missing servlet-mapping for '%s'", servletName);
+                List<ElementWrapper> servlets = document.getElementsByTagName("servlet");
+                for (ElementWrapper servlet : servlets) {
+                    String servletName = servlet.getElementByTagName("servlet-name").getText();
+                    ElementWrapper servletClassEw = servlet.getElementByTagName("servlet-class");
+                    String servletClass = servletClassEw == null ? servletName : servletClassEw.getText();
+                    ElementWrapper loadOnStartupEw = servlet.getElementByTagName("load-on-startup");
+                    Integer loadOnStartup = loadOnStartupEw == null ? null : Integer.valueOf(loadOnStartupEw.getText());
+
+                    Class<? extends Servlet> servletClazz = (Class<? extends Servlet>) Class.forName(servletClass);
+                    ServletInfo undertowServlet = new ServletInfo(servletName, servletClazz);
+
+                    if (servletMappings.containsKey(servletName)) {
+                        undertowServlet.addMapping(servletMappings.get(servletName));
+                        undertowServlet.setLoadOnStartup(loadOnStartup);
+                        di.addServlet(undertowServlet);
+                    } else {
+                        log.warnf("Missing servlet-mapping for '%s'", servletName);
+                    }
                 }
             }
 
@@ -180,21 +182,29 @@ class SimpleWebXmlParser {
             ElementWrapper sessionCfg = document.getElementByTagName("session-config");
             if (sessionCfg != null) {
                 ElementWrapper cookieConfig = sessionCfg.getElementByTagName("cookie-config");
-                String httpOnly = cookieConfig.getElementByTagName("http-only").getText();
                 String cookieName = cookieConfig.getElementByTagName("name").getText();
 
                 ServletSessionConfig cfg = new ServletSessionConfig();
-                cfg.setHttpOnly(Boolean.parseBoolean(httpOnly));
+                if (cookieConfig.getElementByTagName("http-only") != null) {
+                    cfg.setHttpOnly(Boolean.parseBoolean(cookieConfig.getElementByTagName("http-only").getText()));
+                }
                 cfg.setName(cookieName);
                 di.setServletSessionConfig(cfg);
             }
             
             // ERROR PAGES
             List<ElementWrapper> errorPages = document.getElementsByTagName("error-page");
-            for (ElementWrapper errorPage : errorPages) {
-                int errorCode = Integer.parseInt(errorPage.getElementByTagName("error-code").getText());
-                String location = errorPage.getElementByTagName("location").getText();
-                di.addErrorPage(new ErrorPage(location, errorCode));
+            for (ElementWrapper errorPageWrapper : errorPages) {
+                String location = errorPageWrapper.getElementByTagName("location").getText();
+
+                ErrorPage errorPage;
+                if (errorPageWrapper.getElementByTagName("error-code") != null) {
+                    errorPage = new ErrorPage(location, Integer.parseInt(errorPageWrapper.getElementByTagName("error-code").getText()));
+                } else {
+                    errorPage = new ErrorPage(location);
+                }
+
+                di.addErrorPage(errorPage);
             }
 
         } catch (ClassNotFoundException cnfe) {
diff --git a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java
index bcd25b7..cb91e39 100644
--- a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java
+++ b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java
@@ -25,8 +25,6 @@ import io.undertow.server.handlers.resource.ResourceManager;
 import io.undertow.server.handlers.resource.URLResource;
 import io.undertow.servlet.api.DeploymentInfo;
 import io.undertow.servlet.api.ServletInfo;
-import org.apache.jasper.deploy.JspPropertyGroup;
-import org.apache.jasper.deploy.TagLibraryInfo;
 import org.arquillian.undertow.UndertowContainerConfiguration;
 import org.jboss.logging.Logger;
 import org.jboss.shrinkwrap.api.Archive;
@@ -58,6 +56,10 @@ public class UndertowDeployerHelper {
     private static final Logger log = Logger.getLogger(UndertowDeployerHelper.class);
 
     public DeploymentInfo getDeploymentInfo(UndertowContainerConfiguration config, WebArchive archive) {
+        return getDeploymentInfo(config, archive, null);
+    }
+
+    public DeploymentInfo getDeploymentInfo(UndertowContainerConfiguration config, WebArchive archive, DeploymentInfo di) {
         String archiveName = archive.getName();
 
         String appName = archive.getName().substring(0, archive.getName().lastIndexOf('.'));
@@ -69,7 +71,9 @@ public class UndertowDeployerHelper {
         String appContextUrl = "http://" + config.getBindAddress() + ":" + config.getBindHttpPort() + contextPath;
 
         try {
-            DeploymentInfo di = new DeploymentInfo();
+            if (di == null) {
+                di = new DeploymentInfo();
+            }
 
             UndertowWarClassLoader classLoader = new UndertowWarClassLoader(UndertowDeployerHelper.class.getClassLoader(), archive);
             di.setClassLoader(classLoader);
@@ -89,7 +93,7 @@ public class UndertowDeployerHelper {
 
             di.addWelcomePages("index.html", "index.jsp");
 
-            JspServletBuilder.setupDeployment(di, new HashMap<String, JspPropertyGroup>(), new HashMap<String, TagLibraryInfo>(), new HackInstanceManager());
+            JspServletBuilder.setupDeployment(di, new HashMap<>(), new HashMap<>(), new HackInstanceManager());
 
             addAnnotatedServlets(di, archive);